|  | @@ -6,13 +6,13 @@
 | 
	
		
			
				|  |  |  #include "Compiler.h"
 | 
	
		
			
				|  |  |  #include "DataType.h"
 | 
	
		
			
				|  |  |  #include "tokenizer/Tokenizer.h"
 | 
	
		
			
				|  |  | -#include "utils/FunctionMap.h"
 | 
	
		
			
				|  |  | +#include "utils/Functions.h"
 | 
	
		
			
				|  |  |  #include "utils/Variables.h"
 | 
	
		
			
				|  |  |  #include "vm/Operation.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define ERROR_LENGTH 256
 | 
	
		
			
				|  |  | -//#define RETURN_BUFFER 16
 | 
	
		
			
				|  |  | -//#define BREAK_BUFFER 32
 | 
	
		
			
				|  |  | +#define RETURN_BUFFER 16
 | 
	
		
			
				|  |  | +#define BREAK_BUFFER 32
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static jmp_buf errorJump;
 | 
	
		
			
				|  |  |  static char error[ERROR_LENGTH] = {'\0'};
 | 
	
	
		
			
				|  | @@ -22,16 +22,17 @@ static ByteCode* code;
 | 
	
		
			
				|  |  |  static int16 line = 1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static Variables vars;
 | 
	
		
			
				|  |  | -// static FunctionMap functions;
 | 
	
		
			
				|  |  | +static Functions functions;
 | 
	
		
			
				|  |  | +static Functions functionQueue;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static int returns[RETURN_BUFFER];
 | 
	
		
			
				|  |  | +static int returns[RETURN_BUFFER];
 | 
	
		
			
				|  |  |  static int returnIndex = 0;
 | 
	
		
			
				|  |  | -static int returnState = 0;
 | 
	
		
			
				|  |  | +static DataType returnType = DT_VOID;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int breaks[BREAK_BUFFER];
 | 
	
		
			
				|  |  |  static int breakIndex = 0;
 | 
	
		
			
				|  |  |  static int forWhileStack = 0;
 | 
	
		
			
				|  |  | -static int continueAt = 0;*/
 | 
	
		
			
				|  |  | +static int continueAt = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef struct {
 | 
	
		
			
				|  |  |      Operation intOp;
 | 
	
	
		
			
				|  | @@ -56,6 +57,13 @@ static const TypedOp TYPED_EQUAL = {OP_EQUAL_INT, OP_EQUAL_FLOAT, OP_EQUAL_BOOL,
 | 
	
		
			
				|  |  |                                      "=="};
 | 
	
		
			
				|  |  |  static const TypedOp TYPED_NOT_EQUAL = {OP_EQUAL_INT, OP_EQUAL_FLOAT,
 | 
	
		
			
				|  |  |                                          OP_EQUAL_BOOL, "!="};
 | 
	
		
			
				|  |  | +static const TypedOp TYPED_BIT_OR = {OP_BIT_OR, OP_NOTHING, OP_NOTHING, "|"};
 | 
	
		
			
				|  |  | +static const TypedOp TYPED_BIT_XOR = {OP_BIT_XOR, OP_NOTHING, OP_NOTHING, "^"};
 | 
	
		
			
				|  |  | +static const TypedOp TYPED_BIT_AND = {OP_BIT_AND, OP_NOTHING, OP_NOTHING, "&"};
 | 
	
		
			
				|  |  | +static const TypedOp TYPED_LEFT_SHIFT = {OP_LEFT_SHIFT, OP_NOTHING, OP_NOTHING,
 | 
	
		
			
				|  |  | +                                         "<<"};
 | 
	
		
			
				|  |  | +static const TypedOp TYPED_RIGHT_SHIFT = {OP_RIGHT_SHIFT, OP_NOTHING,
 | 
	
		
			
				|  |  | +                                          OP_NOTHING, ">>"};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cError(const char* format, ...) {
 | 
	
		
			
				|  |  |      va_list args;
 | 
	
	
		
			
				|  | @@ -73,15 +81,13 @@ static void cNotDeclared(const char* name) {
 | 
	
		
			
				|  |  |      cError("variable %s has not been declared", name);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cNotInitialized(const char* name) {
 | 
	
		
			
				|  |  | -    cError("variable %s has not been initialized", name);
 | 
	
		
			
				|  |  | +static void cDeclared(const char* name) {
 | 
	
		
			
				|  |  | +    cError("%s has already been declared", name);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static int cAddVar(const char* var) {
 | 
	
		
			
				|  |  | -    int index = vars[varIndex].entries;
 | 
	
		
			
				|  |  | -    simAdd(vars + varIndex, var, &index);
 | 
	
		
			
				|  |  | -    return index;
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +static void cTooMuchArguments() {
 | 
	
		
			
				|  |  | +    cError("too much function arguments");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cUnexpectedToken(Token t) {
 | 
	
		
			
				|  |  |      cError("unexpected token on line %d: %s", line, tGetName(t));
 | 
	
	
		
			
				|  | @@ -92,13 +98,13 @@ static void cAddOperation(Operation token) {
 | 
	
		
			
				|  |  |      bcAddBytes(code, &c, 1);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static int cReserveInt() {
 | 
	
		
			
				|  |  | +static int cReserveInt() {
 | 
	
		
			
				|  |  |      return bcReserveBytes(code, sizeof(int));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cSetInt(int p, int i) {
 | 
	
		
			
				|  |  |      bcSetBytes(code, p, &i, sizeof(int));
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cAddInt(int i) {
 | 
	
		
			
				|  |  |      bcAddBytes(code, &i, sizeof(int));
 | 
	
	
		
			
				|  | @@ -108,19 +114,6 @@ static void cAddInt16(int16 i) {
 | 
	
		
			
				|  |  |      bcAddBytes(code, &i, sizeof(int16));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static int cAddPush(int offset) {
 | 
	
		
			
				|  |  | -    cAddOperation(OP_PUSH_VARS);
 | 
	
		
			
				|  |  | -    int p = cReserveInt();
 | 
	
		
			
				|  |  | -    cAddInt(offset);
 | 
	
		
			
				|  |  | -    return p;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void cAddPop(int p, int vars) {
 | 
	
		
			
				|  |  | -    cAddOperation(OP_POP_VARS);
 | 
	
		
			
				|  |  | -    cAddInt(vars);
 | 
	
		
			
				|  |  | -    cSetInt(p, vars);
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static Token cReadTokenAndLine() {
 | 
	
		
			
				|  |  |      Token t = tReadToken();
 | 
	
		
			
				|  |  |      if(tReadInt16(&line)) {
 | 
	
	
		
			
				|  | @@ -163,17 +156,6 @@ static void cConstantFloat() {
 | 
	
		
			
				|  |  |      bcAddBytes(code, &value, sizeof(float));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void cConstantString() {
 | 
	
		
			
				|  |  | -    int length;
 | 
	
		
			
				|  |  | -    const char* s = tReadString(&length);
 | 
	
		
			
				|  |  | -    if(s == NULL) {
 | 
	
		
			
				|  |  | -        cError("text without string on line %d", line);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    cAddOperation(OP_PUSH_CONST_STRING);
 | 
	
		
			
				|  |  | -    cAddInt(length);
 | 
	
		
			
				|  |  | -    bcAddBytes(code, s, length);
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static const char* cReadString() {
 | 
	
		
			
				|  |  |      int length;
 | 
	
		
			
				|  |  |      const char* literal = tReadString(&length);
 | 
	
	
		
			
				|  | @@ -185,93 +167,97 @@ static const char* cReadString() {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cExpression();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static int cCallFunctionArguments() {
 | 
	
		
			
				|  |  | -    int arguments = 0;
 | 
	
		
			
				|  |  | +static void cCallFunctionArguments(Function* f) {
 | 
	
		
			
				|  |  |      while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | -        arguments++;
 | 
	
		
			
				|  |  | -        cExpression();
 | 
	
		
			
				|  |  | +        DataType dt = cExpression();
 | 
	
		
			
				|  |  | +        if(fAddArgument(f, dt)) {
 | 
	
		
			
				|  |  | +            cTooMuchArguments();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) {
 | 
	
		
			
				|  |  |              cUnexpectedToken(tPeekToken());
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return arguments;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cCallFunction(const char* literal, bool noReturn) {
 | 
	
		
			
				|  |  | +static DataType cCallFunction(const char* name) {
 | 
	
		
			
				|  |  |      cAddOperation(OP_PUSH_INT);
 | 
	
		
			
				|  |  |      cAddInt(0);
 | 
	
		
			
				|  |  | -    int arguments = cCallFunctionArguments();
 | 
	
		
			
				|  |  | -    Function* f = fmSearch(&functions, literal, arguments);
 | 
	
		
			
				|  |  | +    Function f;
 | 
	
		
			
				|  |  | +    fInit(&f, name, line);
 | 
	
		
			
				|  |  | +    cCallFunctionArguments(&f);
 | 
	
		
			
				|  |  |      cAddOperation(OP_GOSUB);
 | 
	
		
			
				|  |  | -    if(f == NULL) {
 | 
	
		
			
				|  |  | -        fmEnqueue(&functions, literal, arguments, line, cReserveInt(),
 | 
	
		
			
				|  |  | -                  noReturn);
 | 
	
		
			
				|  |  | -        cAddInt(arguments);
 | 
	
		
			
				|  |  | -        cAddOperation(OP_NOTHING);
 | 
	
		
			
				|  |  | +    Function* found = fsSearch(&functions, &f);
 | 
	
		
			
				|  |  | +    if(found == NULL) {
 | 
	
		
			
				|  |  | +        cError("unknown function");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(found->address == -1) {
 | 
	
		
			
				|  |  | +        f.returnType = found->returnType;
 | 
	
		
			
				|  |  | +        f.address = cReserveInt();
 | 
	
		
			
				|  |  | +        fsAdd(&functionQueue, &f);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -        if(!noReturn && !f->returns) {
 | 
	
		
			
				|  |  | -            cError("function '%s' needs a return value on line %d", f->name,
 | 
	
		
			
				|  |  | -                   line);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        cAddInt(f->address);
 | 
	
		
			
				|  |  | -        cAddInt(arguments);
 | 
	
		
			
				|  |  | -        if(f->returns && noReturn) {
 | 
	
		
			
				|  |  | -            cAddOperation(OP_POP);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        cAddInt(found->address);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +    cAddInt(found->size);
 | 
	
		
			
				|  |  | +    return found->returnType;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static DataType cLoadVariable(Variable* v) {
 | 
	
		
			
				|  |  | +    switch(v->type) {
 | 
	
		
			
				|  |  | +        case DT_INT: cAddOperation(OP_LOAD_INT); break;
 | 
	
		
			
				|  |  | +        default: cError("cannot load type %s", dtGetName(v->type));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    return v->type;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cStoreVariable(Variable* v, DataType dt, const char* name) {
 | 
	
		
			
				|  |  | +    if(v->type != dt) {
 | 
	
		
			
				|  |  | +        cInvalidOperation(v->type, dt, name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    switch(v->type) {
 | 
	
		
			
				|  |  | +        case DT_INT: cAddOperation(OP_STORE_INT); break;
 | 
	
		
			
				|  |  | +        default: cError("cannot store type %s", dtGetName(v->type));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cAddReference(int address) {
 | 
	
		
			
				|  |  | -    // if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
 | 
	
		
			
				|  |  | -    //    cExpression();
 | 
	
		
			
				|  |  | -    //    cAddOperation(OP_REFERENCE_FROM_ARRAY);
 | 
	
		
			
				|  |  | -    //    cAddInt(cAddVar(var));
 | 
	
		
			
				|  |  | -    //    cConsumeToken(T_CLOSE_SQUARE_BRACKET);
 | 
	
		
			
				|  |  | -    //} else {
 | 
	
		
			
				|  |  | -    cAddOperation(OP_REFERENCE_FROM_VAR);
 | 
	
		
			
				|  |  | -    cAddInt(address);
 | 
	
		
			
				|  |  | -    //}
 | 
	
		
			
				|  |  | +static DataType cPostChange(Variable* v, int change, const char* name) {
 | 
	
		
			
				|  |  | +    if(v->type != DT_INT) {
 | 
	
		
			
				|  |  | +        cError("%s needs an int", name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cAddOperation(OP_LOAD_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_LOAD_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_PUSH_INT);
 | 
	
		
			
				|  |  | +    cAddInt(change);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_ADD_INT);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_STORE_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    return DT_INT;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cLiteral() {
 | 
	
		
			
				|  |  |      const char* literal = cReadString();
 | 
	
		
			
				|  |  | -    /*if(cConsumeTokenIf(T_OPEN_BRACKET)) {
 | 
	
		
			
				|  |  | -        cCallFunction(literal, false);
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    if(cConsumeTokenIf(T_OPEN_BRACKET)) {
 | 
	
		
			
				|  |  | +        DataType dt = cCallFunction(literal);
 | 
	
		
			
				|  |  | +        if(dt == DT_VOID) {
 | 
	
		
			
				|  |  | +            cError("function returns void");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return dt;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      Variable* v = vSearch(&vars, literal);
 | 
	
		
			
				|  |  |      if(v == NULL) {
 | 
	
		
			
				|  |  |          cNotDeclared(literal);
 | 
	
		
			
				|  |  | -    } else if(!v->initialized) {
 | 
	
		
			
				|  |  | -        cNotInitialized(literal);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    cAddReference(v->address);
 | 
	
		
			
				|  |  | -    cAddOperation(OP_DEREFERENCE_INT);
 | 
	
		
			
				|  |  | -    return v->type;
 | 
	
		
			
				|  |  | -    /*if(cConsumeTokenIf(T_INCREMENT)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_POST_INCREMENT);
 | 
	
		
			
				|  |  | +    if(cConsumeTokenIf(T_INCREMENT)) {
 | 
	
		
			
				|  |  | +        return cPostChange(v, 1, "++");
 | 
	
		
			
				|  |  |      } else if(cConsumeTokenIf(T_DECREMENT)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_POST_DECREMENT);
 | 
	
		
			
				|  |  | -    } else if(cConsumeTokenIf(T_POINT)) {
 | 
	
		
			
				|  |  | -        cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  | -        const char* access = cReadString();
 | 
	
		
			
				|  |  | -        if(strcmp(access, "length") == 0) {
 | 
	
		
			
				|  |  | -            cAddOperation(OP_ARRAY_LENGTH);
 | 
	
		
			
				|  |  | -        } else {
 | 
	
		
			
				|  |  | -            cError("'%s' not supported after . on line %d", access, line);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_DEREFERENCE);
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +        return cPostChange(v, -1, "--");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return cLoadVariable(v);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void cArray() {
 | 
	
		
			
				|  |  | -    cConsumeToken(T_OPEN_SQUARE_BRACKET);
 | 
	
		
			
				|  |  | -    cExpression();
 | 
	
		
			
				|  |  | -    cConsumeToken(T_CLOSE_SQUARE_BRACKET);
 | 
	
		
			
				|  |  | -    cAddOperation(OP_ALLOCATE_ARRAY);
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static DataType cBracketPrimary() {
 | 
	
		
			
				|  |  |      DataType result = cExpression();
 | 
	
		
			
				|  |  |      cConsumeToken(T_CLOSE_BRACKET);
 | 
	
	
		
			
				|  | @@ -283,22 +269,34 @@ static DataType cPrimary() {
 | 
	
		
			
				|  |  |      switch(t) {
 | 
	
		
			
				|  |  |          case T_CONST_INT: cConstantInt(); return DT_INT;
 | 
	
		
			
				|  |  |          case T_FLOAT: cConstantFloat(); return DT_FLOAT;
 | 
	
		
			
				|  |  | -        // case T_TEXT: cConstantString(); break;
 | 
	
		
			
				|  |  | -        // case T_NULL: cAddOperation(OP_PUSH_NULL); break;
 | 
	
		
			
				|  |  |          case T_TRUE: cAddOperation(OP_PUSH_TRUE); return DT_BOOL;
 | 
	
		
			
				|  |  |          case T_FALSE: cAddOperation(OP_PUSH_FALSE); return DT_BOOL;
 | 
	
		
			
				|  |  |          case T_OPEN_BRACKET: return cBracketPrimary();
 | 
	
		
			
				|  |  |          case T_LITERAL: return cLiteral();
 | 
	
		
			
				|  |  | -        // case T_ARRAY: cArray(); break;
 | 
	
		
			
				|  |  |          default: cUnexpectedToken(t); return DT_VOID;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void cPreChange(Operation op) {
 | 
	
		
			
				|  |  | +static DataType cPreChange(int change, const char* name) {
 | 
	
		
			
				|  |  |      cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  | -    cAddReference(cReadString());
 | 
	
		
			
				|  |  | -    cAddOperation(op);
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +    const char* literal = cReadString();
 | 
	
		
			
				|  |  | +    Variable* v = vSearch(&vars, literal);
 | 
	
		
			
				|  |  | +    if(v == NULL) {
 | 
	
		
			
				|  |  | +        cNotDeclared(literal);
 | 
	
		
			
				|  |  | +    } else if(v->type != DT_INT) {
 | 
	
		
			
				|  |  | +        cError("%s needs an int", name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cAddOperation(OP_LOAD_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_PUSH_INT);
 | 
	
		
			
				|  |  | +    cAddInt(change);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_ADD_INT);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_STORE_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_LOAD_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    return DT_INT;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cPreUnary() {
 | 
	
		
			
				|  |  |      if(cConsumeTokenIf(T_SUB)) {
 | 
	
	
		
			
				|  | @@ -309,26 +307,34 @@ static DataType cPreUnary() {
 | 
	
		
			
				|  |  |              default: cError("cannot invert sign of %s", dtGetName(result));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          return result;
 | 
	
		
			
				|  |  | -    } /*else if(cConsumeTokenIf(T_INCREMENT)) {
 | 
	
		
			
				|  |  | -        cPreChange(OP_PRE_INCREMENT);
 | 
	
		
			
				|  |  | +    } else if(cConsumeTokenIf(T_INCREMENT)) {
 | 
	
		
			
				|  |  | +        return cPreChange(1, "++");
 | 
	
		
			
				|  |  |      } else if(cConsumeTokenIf(T_DECREMENT)) {
 | 
	
		
			
				|  |  | -        cPreChange(OP_PRE_DECREMENT);
 | 
	
		
			
				|  |  | +        return cPreChange(-1, "--");
 | 
	
		
			
				|  |  |      } else if(cConsumeTokenIf(T_NOT)) {
 | 
	
		
			
				|  |  |          int counter = 1;
 | 
	
		
			
				|  |  |          while(cConsumeTokenIf(T_NOT)) {
 | 
	
		
			
				|  |  |              counter++;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        cPrimary();
 | 
	
		
			
				|  |  | +        DataType result = cPrimary();
 | 
	
		
			
				|  |  | +        if(result != DT_BOOL) {
 | 
	
		
			
				|  |  | +            cError("! needs a bool not %s", dtGetName(result));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          cAddOperation(OP_NOT);
 | 
	
		
			
				|  |  |          if((counter & 1) == 0) {
 | 
	
		
			
				|  |  |              cAddOperation(OP_NOT);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        return DT_BOOL;
 | 
	
		
			
				|  |  |      } else if(cConsumeTokenIf(T_BIT_NOT)) {
 | 
	
		
			
				|  |  | -        cPrimary();
 | 
	
		
			
				|  |  | -        cAddOperation(OP_BIT_NOT);
 | 
	
		
			
				|  |  | -    } else {*/
 | 
	
		
			
				|  |  | +        DataType result = cPrimary();
 | 
	
		
			
				|  |  | +        if(result == DT_INT) {
 | 
	
		
			
				|  |  | +            cAddOperation(OP_BIT_NOT);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            cError("~ needs an int not %s", dtGetName(result));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      return cPrimary();
 | 
	
		
			
				|  |  | -    //}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cAddTypeOperation(DataType a, DataType b, const TypedOp* op) {
 | 
	
	
		
			
				|  | @@ -374,18 +380,17 @@ static DataType cAdd() {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cShift() {
 | 
	
		
			
				|  |  | -    return cAdd();
 | 
	
		
			
				|  |  | -    /*while(true) {
 | 
	
		
			
				|  |  | +    DataType a = cAdd();
 | 
	
		
			
				|  |  | +    while(true) {
 | 
	
		
			
				|  |  |          if(cConsumeTokenIf(T_LEFT_SHIFT)) {
 | 
	
		
			
				|  |  | -            cAdd();
 | 
	
		
			
				|  |  | -            cAddOperation(OP_LEFT_SHIFT);
 | 
	
		
			
				|  |  | +            cAddTypeOperation(a, cAdd(), &TYPED_LEFT_SHIFT);
 | 
	
		
			
				|  |  |          } else if(cConsumeTokenIf(T_RIGHT_SHIFT)) {
 | 
	
		
			
				|  |  | -            cAdd();
 | 
	
		
			
				|  |  | -            cAddOperation(OP_RIGHT_SHIFT);
 | 
	
		
			
				|  |  | +            cAddTypeOperation(a, cAdd(), &TYPED_RIGHT_SHIFT);
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return a;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cComparison() {
 | 
	
	
		
			
				|  | @@ -430,216 +435,168 @@ static DataType cEqual() {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cBitAnd() {
 | 
	
		
			
				|  |  | -    return cEqual();
 | 
	
		
			
				|  |  | -    /*while(cConsumeTokenIf(T_BIT_AND)) {
 | 
	
		
			
				|  |  | -        cEqual();
 | 
	
		
			
				|  |  | -        cAddOperation(OP_BIT_AND);
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    DataType a = cEqual();
 | 
	
		
			
				|  |  | +    while(cConsumeTokenIf(T_BIT_AND)) {
 | 
	
		
			
				|  |  | +        DataType b = cEqual();
 | 
	
		
			
				|  |  | +        cAddTypeOperation(a, b, &TYPED_BIT_AND);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return a;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cBitXor() {
 | 
	
		
			
				|  |  | -    return cBitAnd();
 | 
	
		
			
				|  |  | -    /*while(cConsumeTokenIf(T_BIT_XOR)) {
 | 
	
		
			
				|  |  | -        cBitAnd();
 | 
	
		
			
				|  |  | -        cAddOperation(OP_BIT_XOR);
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    DataType a = cBitAnd();
 | 
	
		
			
				|  |  | +    while(cConsumeTokenIf(T_BIT_XOR)) {
 | 
	
		
			
				|  |  | +        DataType b = cBitAnd();
 | 
	
		
			
				|  |  | +        cAddTypeOperation(a, b, &TYPED_BIT_XOR);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return a;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cBitOr() {
 | 
	
		
			
				|  |  | -    return cBitXor();
 | 
	
		
			
				|  |  | -    /*while(cConsumeTokenIf(T_BIT_OR)) {
 | 
	
		
			
				|  |  | -        cBitXor();
 | 
	
		
			
				|  |  | -        cAddOperation(OP_BIT_OR);
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    DataType a = cBitXor();
 | 
	
		
			
				|  |  | +    while(cConsumeTokenIf(T_BIT_OR)) {
 | 
	
		
			
				|  |  | +        DataType b = cBitXor();
 | 
	
		
			
				|  |  | +        cAddTypeOperation(a, b, &TYPED_BIT_OR);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return a;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cAnd() {
 | 
	
		
			
				|  |  | -    return cBitOr();
 | 
	
		
			
				|  |  | -    /*while(cConsumeTokenIf(T_AND)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_DUPLICATE);
 | 
	
		
			
				|  |  | -        cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  | +    DataType a = cBitOr();
 | 
	
		
			
				|  |  | +    while(cConsumeTokenIf(T_AND)) {
 | 
	
		
			
				|  |  | +        cAddOperation(OP_PEEK_FALSE_GOTO);
 | 
	
		
			
				|  |  |          int p = cReserveInt();
 | 
	
		
			
				|  |  | -        cBitOr();
 | 
	
		
			
				|  |  | +        DataType b = cBitOr();
 | 
	
		
			
				|  |  | +        if(a != DT_BOOL || b != DT_BOOL) {
 | 
	
		
			
				|  |  | +            cInvalidOperation(a, b, "&&");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          cAddOperation(OP_AND);
 | 
	
		
			
				|  |  |          cSetInt(p, code->length);
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return a;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cOr() {
 | 
	
		
			
				|  |  | -    return cAnd();
 | 
	
		
			
				|  |  | -    /*while(cConsumeTokenIf(T_OR)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_DUPLICATE);
 | 
	
		
			
				|  |  | -        cAddOperation(OP_NOT);
 | 
	
		
			
				|  |  | -        cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  | +    DataType a = cAnd();
 | 
	
		
			
				|  |  | +    while(cConsumeTokenIf(T_OR)) {
 | 
	
		
			
				|  |  | +        cAddOperation(OP_PEEK_TRUE_GOTO);
 | 
	
		
			
				|  |  |          int p = cReserveInt();
 | 
	
		
			
				|  |  | -        cAnd();
 | 
	
		
			
				|  |  | +        DataType b = cAnd();
 | 
	
		
			
				|  |  | +        if(a != DT_BOOL || b != DT_BOOL) {
 | 
	
		
			
				|  |  | +            cInvalidOperation(a, b, "||");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          cAddOperation(OP_OR);
 | 
	
		
			
				|  |  |          cSetInt(p, code->length);
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return a;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cExpression() {
 | 
	
		
			
				|  |  |      return cOr();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void cOperationSet(Operation op) {
 | 
	
		
			
				|  |  | -    cAddOperation(OP_DUPLICATE);
 | 
	
		
			
				|  |  | -    cAddOperation(OP_DEREFERENCE);
 | 
	
		
			
				|  |  | -    cExpression();
 | 
	
		
			
				|  |  | -    cAddOperation(op);
 | 
	
		
			
				|  |  | -    cAddOperation(OP_SET);
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +static void cSet(Variable* v) {
 | 
	
		
			
				|  |  | +    cStoreVariable(v, cExpression(), "=");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cOperationSet(Variable* v, const TypedOp* op) {
 | 
	
		
			
				|  |  | +    DataType a = cLoadVariable(v);
 | 
	
		
			
				|  |  | +    DataType b = cExpression();
 | 
	
		
			
				|  |  | +    cAddTypeOperation(a, b, op);
 | 
	
		
			
				|  |  | +    cStoreVariable(v, b, "=");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cAddPostLineChange(Variable* v, int change, const char* name) {
 | 
	
		
			
				|  |  | +    if(v->type != DT_INT) {
 | 
	
		
			
				|  |  | +        cError("%s needs an int", name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cAddOperation(OP_LOAD_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_PUSH_INT);
 | 
	
		
			
				|  |  | +    cAddInt(change);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_ADD_INT);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_STORE_INT);
 | 
	
		
			
				|  |  | +    cAddInt(v->address);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cLineLiteral() {
 | 
	
		
			
				|  |  |      const char* literal = cReadString();
 | 
	
		
			
				|  |  | -    /*if(cConsumeTokenIf(T_OPEN_BRACKET)) {
 | 
	
		
			
				|  |  | -        cCallFunction(literal, true);
 | 
	
		
			
				|  |  | +    if(cConsumeTokenIf(T_OPEN_BRACKET)) {
 | 
	
		
			
				|  |  | +        DataType dt = cCallFunction(literal);
 | 
	
		
			
				|  |  | +        if(dt != DT_VOID) {
 | 
	
		
			
				|  |  | +            cError("function returns %s not void", dtGetName(dt));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      Variable* v = vSearch(&vars, literal);
 | 
	
		
			
				|  |  |      if(v == NULL) {
 | 
	
		
			
				|  |  |          cNotDeclared(literal);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    cAddReference(v->address);
 | 
	
		
			
				|  |  | -    cConsumeToken(T_SET);
 | 
	
		
			
				|  |  | -    DataType dt = cExpression();
 | 
	
		
			
				|  |  | -    if(v->type != dt) {
 | 
	
		
			
				|  |  | -        cInvalidOperation(v->type, dt, "=");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if(dt == DT_INT) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_SET_INT);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -        cError("%s cannot be set", dtGetName(dt));
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    v->initialized = true;
 | 
	
		
			
				|  |  | -    /*Token t = cReadTokenAndLine();
 | 
	
		
			
				|  |  | +    Token t = cReadTokenAndLine();
 | 
	
		
			
				|  |  |      switch(t) {
 | 
	
		
			
				|  |  | -        case T_SET:
 | 
	
		
			
				|  |  | -            cExpression();
 | 
	
		
			
				|  |  | -            cAddOperation(OP_SET);
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        case T_ADD_SET: cOperationSet(OP_ADD); break;
 | 
	
		
			
				|  |  | -        case T_SUB_SET: cOperationSet(OP_SUB); break;
 | 
	
		
			
				|  |  | -        case T_MUL_SET: cOperationSet(OP_MUL); break;
 | 
	
		
			
				|  |  | -        case T_DIV_SET: cOperationSet(OP_DIV); break;
 | 
	
		
			
				|  |  | -        case T_MOD_SET: cOperationSet(OP_MOD); break;
 | 
	
		
			
				|  |  | -        case T_BIT_AND_SET: cOperationSet(OP_BIT_AND); break;
 | 
	
		
			
				|  |  | -        case T_BIT_OR_SET: cOperationSet(OP_BIT_OR); break;
 | 
	
		
			
				|  |  | -        case T_BIT_XOR_SET: cOperationSet(OP_BIT_XOR); break;
 | 
	
		
			
				|  |  | -        case T_LEFT_SHIFT_SET: cOperationSet(OP_LEFT_SHIFT); break;
 | 
	
		
			
				|  |  | -        case T_RIGHT_SHIFT_SET: cOperationSet(OP_RIGHT_SHIFT); break;
 | 
	
		
			
				|  |  | -        case T_INCREMENT:
 | 
	
		
			
				|  |  | -            cAddOperation(OP_POST_INCREMENT);
 | 
	
		
			
				|  |  | -            cAddOperation(OP_POP);
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        case T_DECREMENT:
 | 
	
		
			
				|  |  | -            cAddOperation(OP_POST_DECREMENT);
 | 
	
		
			
				|  |  | -            cAddOperation(OP_POP);
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | +        case T_SET: cSet(v); break;
 | 
	
		
			
				|  |  | +        case T_ADD_SET: cOperationSet(v, &TYPED_ADD); break;
 | 
	
		
			
				|  |  | +        case T_SUB_SET: cOperationSet(v, &TYPED_SUB); break;
 | 
	
		
			
				|  |  | +        case T_MUL_SET: cOperationSet(v, &TYPED_MUL); break;
 | 
	
		
			
				|  |  | +        case T_DIV_SET: cOperationSet(v, &TYPED_DIV); break;
 | 
	
		
			
				|  |  | +        case T_MOD_SET: cOperationSet(v, &TYPED_MOD); break;
 | 
	
		
			
				|  |  | +        case T_BIT_AND_SET: cOperationSet(v, &TYPED_BIT_AND); break;
 | 
	
		
			
				|  |  | +        case T_BIT_OR_SET: cOperationSet(v, &TYPED_BIT_OR); break;
 | 
	
		
			
				|  |  | +        case T_BIT_XOR_SET: cOperationSet(v, &TYPED_BIT_XOR); break;
 | 
	
		
			
				|  |  | +        case T_LEFT_SHIFT_SET: cOperationSet(v, &TYPED_LEFT_SHIFT); break;
 | 
	
		
			
				|  |  | +        case T_RIGHT_SHIFT_SET: cOperationSet(v, &TYPED_RIGHT_SHIFT); break;
 | 
	
		
			
				|  |  | +        case T_INCREMENT: cAddPostLineChange(v, 1, "++"); break;
 | 
	
		
			
				|  |  | +        case T_DECREMENT: cAddPostLineChange(v, -1, "--"); break;
 | 
	
		
			
				|  |  |          default: cUnexpectedToken(t);
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/*static int cFunctionArguments() {
 | 
	
		
			
				|  |  | -    int arguments = 0;
 | 
	
		
			
				|  |  | -    while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | -        cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  | -        arguments++;
 | 
	
		
			
				|  |  | -        cAddVar(cReadString());
 | 
	
		
			
				|  |  | -        if(cConsumeTokenIf(T_COMMA) && tPeekToken() != T_LITERAL) {
 | 
	
		
			
				|  |  | -            cUnexpectedToken(tPeekToken());
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return arguments;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cLine(Token t);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cConsumeBody() {
 | 
	
		
			
				|  |  | -    cConsumeToken(T_OPEN_CURVED_BRACKET);
 | 
	
		
			
				|  |  |      int oldLine = line;
 | 
	
		
			
				|  |  |      while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
 | 
	
		
			
				|  |  |          Token t = cReadTokenAndLine();
 | 
	
		
			
				|  |  |          if(t == T_END) {
 | 
	
		
			
				|  |  | -            cError(
 | 
	
		
			
				|  |  | -                "unexpected end of file: non closed curved bracket on line %d",
 | 
	
		
			
				|  |  | -                oldLine);
 | 
	
		
			
				|  |  | +            line = oldLine;
 | 
	
		
			
				|  |  | +            cError("unexpected end of file: non closed curved bracket");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          cLine(t);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cLinkReturns() {
 | 
	
		
			
				|  |  | -    for(int i = 0; i < returnIndex; i++) {
 | 
	
		
			
				|  |  | -        cSetInt(returns[i], vars[1].entries);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    returnIndex = 0;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void cFunctionBody(const char* name, int arguments) {
 | 
	
		
			
				|  |  | -    int oldLine = line;
 | 
	
		
			
				|  |  | -    cAddOperation(OP_GOTO);
 | 
	
		
			
				|  |  | -    int gotoIndex = cReserveInt();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    int address = code->length;
 | 
	
		
			
				|  |  | -    returnState = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    int p = cAddPush(arguments);
 | 
	
		
			
				|  |  | +static void cConsumeScope() {
 | 
	
		
			
				|  |  | +    Scope scope;
 | 
	
		
			
				|  |  | +    vEnterScope(&vars, &scope);
 | 
	
		
			
				|  |  |      cConsumeBody();
 | 
	
		
			
				|  |  | -    cAddPop(p, vars[1].entries);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cLinkReturns();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if(!fmAdd(&functions, name, arguments, address, returnState == 2)) {
 | 
	
		
			
				|  |  | -        cError("function registered twice on line %d", oldLine);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cAddOperation(OP_RETURN);
 | 
	
		
			
				|  |  | -    cSetInt(gotoIndex, code->length);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void cFunction() {
 | 
	
		
			
				|  |  | -    if(varIndex == 1) {
 | 
	
		
			
				|  |  | -        cError("function inside function on line %d", line);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  | -    const char* name = cReadString();
 | 
	
		
			
				|  |  | -    cConsumeToken(T_OPEN_BRACKET);
 | 
	
		
			
				|  |  | -    varIndex = 1;
 | 
	
		
			
				|  |  | -    vars[1].entries = 0;
 | 
	
		
			
				|  |  | -    cFunctionBody(name, cFunctionArguments());
 | 
	
		
			
				|  |  | -    varIndex = 0;
 | 
	
		
			
				|  |  | +    vLeaveScope(&vars, &scope);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cAddReturn() {
 | 
	
		
			
				|  |  | -    cAddOperation(OP_POP_VARS);
 | 
	
		
			
				|  |  | -    returns[returnIndex++] = cReserveInt(vars);
 | 
	
		
			
				|  |  | -    cAddOperation(OP_RETURN);
 | 
	
		
			
				|  |  | +static void cAddReturn(Operation op) {
 | 
	
		
			
				|  |  | +    cAddOperation(op);
 | 
	
		
			
				|  |  | +    returns[returnIndex++] = cReserveInt();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cReturn() {
 | 
	
		
			
				|  |  | -    if(varIndex == 0) {
 | 
	
		
			
				|  |  | -        cError("return without a function on line %d", line);
 | 
	
		
			
				|  |  | -    } else if(returnIndex >= RETURN_BUFFER) {
 | 
	
		
			
				|  |  | -        cError("too much returns in function around line %d", line);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if(cConsumeTokenIf(T_SEMICOLON)) {
 | 
	
		
			
				|  |  | -        if(returnState == 2) {
 | 
	
		
			
				|  |  | -            cError("mixed return type on line %d", line);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        returnState = 1;
 | 
	
		
			
				|  |  | -        cAddReturn();
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -        if(returnState == 1) {
 | 
	
		
			
				|  |  | -            cError("mixed return type on line %d", line);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        returnState = 2;
 | 
	
		
			
				|  |  | -        cExpression();
 | 
	
		
			
				|  |  | -        cAddOperation(OP_SET_RETURN);
 | 
	
		
			
				|  |  | -        cAddReturn();
 | 
	
		
			
				|  |  | +    if(returnIndex >= RETURN_BUFFER) {
 | 
	
		
			
				|  |  | +        cError("too much returns in function");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(returnType == DT_VOID) {
 | 
	
		
			
				|  |  |          cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  | +        cAddReturn(OP_RETURN);
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    DataType dt = cExpression();
 | 
	
		
			
				|  |  | +    if(dt != returnType) {
 | 
	
		
			
				|  |  | +        cError("wrong return type, should be %s", dtGetName(returnType));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +    switch(dt) {
 | 
	
		
			
				|  |  | +        case DT_INT: cAddReturn(OP_RETURN_INT); break;
 | 
	
		
			
				|  |  | +        case DT_BOOL: cAddReturn(OP_RETURN_BOOL); break;
 | 
	
		
			
				|  |  | +        default: cError("cannot return %s", dtGetName(dt));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cPrint() {
 | 
	
		
			
				|  |  |      DataType dt = cExpression();
 | 
	
	
		
			
				|  | @@ -647,18 +604,22 @@ static void cPrint() {
 | 
	
		
			
				|  |  |          case DT_INT: cAddOperation(OP_PRINT_INT); break;
 | 
	
		
			
				|  |  |          case DT_FLOAT: cAddOperation(OP_PRINT_FLOAT); break;
 | 
	
		
			
				|  |  |          case DT_BOOL: cAddOperation(OP_PRINT_BOOL); break;
 | 
	
		
			
				|  |  | -        default: cError("cannot print data type %s", dtGetName(dt));
 | 
	
		
			
				|  |  | +        default: cError("cannot print type %s", dtGetName(dt));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void cIf() {
 | 
	
		
			
				|  |  | +static void cIf() {
 | 
	
		
			
				|  |  |      cConsumeToken(T_OPEN_BRACKET);
 | 
	
		
			
				|  |  | -    cExpression();
 | 
	
		
			
				|  |  | +    DataType dt = cExpression();
 | 
	
		
			
				|  |  | +    if(dt != DT_BOOL) {
 | 
	
		
			
				|  |  | +        cError("if expects a bool not %s", dtGetName(dt));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      cConsumeToken(T_CLOSE_BRACKET);
 | 
	
		
			
				|  |  |      cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  |      int ifP = cReserveInt();
 | 
	
		
			
				|  |  | -    cConsumeBody();
 | 
	
		
			
				|  |  | +    cConsumeToken(T_OPEN_CURVED_BRACKET);
 | 
	
		
			
				|  |  | +    cConsumeScope();
 | 
	
		
			
				|  |  |      cSetInt(ifP, code->length);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if(cConsumeTokenIf(T_ELSE)) {
 | 
	
	
		
			
				|  | @@ -668,7 +629,8 @@ static void cPrint() {
 | 
	
		
			
				|  |  |          if(cConsumeTokenIf(T_IF)) {
 | 
	
		
			
				|  |  |              cIf();
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  | -            cConsumeBody();
 | 
	
		
			
				|  |  | +            cConsumeToken(T_OPEN_CURVED_BRACKET);
 | 
	
		
			
				|  |  | +            cConsumeScope();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          cSetInt(elseP, code->length);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -684,7 +646,10 @@ static void cConsumeBreaks(int start, int address) {
 | 
	
		
			
				|  |  |  static void cWhile() {
 | 
	
		
			
				|  |  |      int start = code->length;
 | 
	
		
			
				|  |  |      cConsumeToken(T_OPEN_BRACKET);
 | 
	
		
			
				|  |  | -    cExpression();
 | 
	
		
			
				|  |  | +    DataType dt = cExpression();
 | 
	
		
			
				|  |  | +    if(dt != DT_BOOL) {
 | 
	
		
			
				|  |  | +        cError("while expects a bool not %s", dtGetName(dt));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      cConsumeToken(T_CLOSE_BRACKET);
 | 
	
		
			
				|  |  |      cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  |      int ifP = cReserveInt();
 | 
	
	
		
			
				|  | @@ -692,58 +657,60 @@ static void cWhile() {
 | 
	
		
			
				|  |  |      forWhileStack++;
 | 
	
		
			
				|  |  |      int oldContinue = continueAt;
 | 
	
		
			
				|  |  |      continueAt = start;
 | 
	
		
			
				|  |  | -    cConsumeBody();
 | 
	
		
			
				|  |  | +    cConsumeToken(T_OPEN_CURVED_BRACKET);
 | 
	
		
			
				|  |  | +    cConsumeScope();
 | 
	
		
			
				|  |  |      continueAt = oldContinue;
 | 
	
		
			
				|  |  |      forWhileStack--;
 | 
	
		
			
				|  |  |      cAddOperation(OP_GOTO);
 | 
	
		
			
				|  |  |      cAddInt(start);
 | 
	
		
			
				|  |  |      cSetInt(ifP, code->length);
 | 
	
		
			
				|  |  |      cConsumeBreaks(breakStart, code->length);
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cInt() {
 | 
	
		
			
				|  |  |      cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  |      const char* var = cReadString();
 | 
	
		
			
				|  |  | -    Variable* v = vSearch(&vars, var);
 | 
	
		
			
				|  |  | +    Variable* v = vSearchScope(&vars, var);
 | 
	
		
			
				|  |  |      if(v != NULL) {
 | 
	
		
			
				|  |  | -        cError("%s has already been declared", var);
 | 
	
		
			
				|  |  | +        cDeclared(var);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      v = vAdd(&vars, var, DT_INT);
 | 
	
		
			
				|  |  | -    if(tPeekToken() == T_SEMICOLON) {
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |      cConsumeToken(T_SET);
 | 
	
		
			
				|  |  | -    cAddReference(v->address);
 | 
	
		
			
				|  |  | -    DataType dt = cExpression();
 | 
	
		
			
				|  |  | -    if(dt != DT_INT) {
 | 
	
		
			
				|  |  | -        cInvalidOperation(DT_INT, dt, "=");
 | 
	
		
			
				|  |  | +    cSet(v);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cAddPreLineChange(int change, const char* name) {
 | 
	
		
			
				|  |  | +    cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  | +    const char* literal = cReadString();
 | 
	
		
			
				|  |  | +    Variable* v = vSearch(&vars, literal);
 | 
	
		
			
				|  |  | +    if(v == NULL) {
 | 
	
		
			
				|  |  | +        cNotDeclared(literal);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    cAddOperation(OP_SET_INT);
 | 
	
		
			
				|  |  | -    v->initialized = true;
 | 
	
		
			
				|  |  | +    cAddPostLineChange(v, change, name);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cLineExpression(Token t) {
 | 
	
		
			
				|  |  |      switch(t) {
 | 
	
		
			
				|  |  |          case T_LITERAL: cLineLiteral(); break;
 | 
	
		
			
				|  |  |          case T_INT: cInt(); break;
 | 
	
		
			
				|  |  | -        /*case T_INCREMENT:
 | 
	
		
			
				|  |  | -            cPreChange(OP_PRE_INCREMENT);
 | 
	
		
			
				|  |  | -            cAddOperation(OP_POP);
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        case T_DECREMENT:
 | 
	
		
			
				|  |  | -            cPreChange(OP_PRE_DECREMENT);
 | 
	
		
			
				|  |  | -            cAddOperation(OP_POP);
 | 
	
		
			
				|  |  | -            break;*/
 | 
	
		
			
				|  |  | +        case T_INCREMENT: cAddPreLineChange(1, "++"); break;
 | 
	
		
			
				|  |  | +        case T_DECREMENT: cAddPreLineChange(-1, "--"); break;
 | 
	
		
			
				|  |  |          default: cUnexpectedToken(t);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void cFor() {
 | 
	
		
			
				|  |  | +static void cFor() {
 | 
	
		
			
				|  |  | +    Scope scope;
 | 
	
		
			
				|  |  | +    vEnterScope(&vars, &scope);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      cConsumeToken(T_OPEN_BRACKET);
 | 
	
		
			
				|  |  |      cLineExpression(cReadTokenAndLine());
 | 
	
		
			
				|  |  |      cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  |      int startCheck = code->length;
 | 
	
		
			
				|  |  | -    cExpression();
 | 
	
		
			
				|  |  | +    DataType dt = cExpression();
 | 
	
		
			
				|  |  | +    if(dt != DT_BOOL) {
 | 
	
		
			
				|  |  | +        cError("for expects a bool not %s", dtGetName(dt));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  |      cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  |      int end = cReserveInt();
 | 
	
	
		
			
				|  | @@ -759,6 +726,7 @@ static void cLineExpression(Token t) {
 | 
	
		
			
				|  |  |      forWhileStack++;
 | 
	
		
			
				|  |  |      int oldContinue = continueAt;
 | 
	
		
			
				|  |  |      continueAt = startPerLoop;
 | 
	
		
			
				|  |  | +    cConsumeToken(T_OPEN_CURVED_BRACKET);
 | 
	
		
			
				|  |  |      cConsumeBody();
 | 
	
		
			
				|  |  |      continueAt = oldContinue;
 | 
	
		
			
				|  |  |      forWhileStack--;
 | 
	
	
		
			
				|  | @@ -766,6 +734,8 @@ static void cLineExpression(Token t) {
 | 
	
		
			
				|  |  |      cAddInt(startPerLoop);
 | 
	
		
			
				|  |  |      cSetInt(end, code->length);
 | 
	
		
			
				|  |  |      cConsumeBreaks(breakStart, code->length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    vLeaveScope(&vars, &scope);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cBreak() {
 | 
	
	
		
			
				|  | @@ -786,64 +756,195 @@ static void cContinue() {
 | 
	
		
			
				|  |  |      cAddOperation(OP_GOTO);
 | 
	
		
			
				|  |  |      cAddInt(continueAt);
 | 
	
		
			
				|  |  |      cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cLine(Token t) {
 | 
	
		
			
				|  |  |      cAddOperation(OP_LINE);
 | 
	
		
			
				|  |  |      cAddInt16(line);
 | 
	
		
			
				|  |  |      switch(t) {
 | 
	
		
			
				|  |  | +        case T_OPEN_CURVED_BRACKET: cConsumeScope(); break;
 | 
	
		
			
				|  |  |          case T_PRINT: cPrint(); break;
 | 
	
		
			
				|  |  | -        // case T_FUNCTION: cFunction(); break;
 | 
	
		
			
				|  |  | -        // case T_RETURN: cReturn(); break;
 | 
	
		
			
				|  |  | -        // case T_IF: cIf(); break;
 | 
	
		
			
				|  |  | -        // case T_WHILE: cWhile(); break;
 | 
	
		
			
				|  |  | -        // case T_FOR: cFor(); break;
 | 
	
		
			
				|  |  | -        // case T_BREAK: cBreak(); break;
 | 
	
		
			
				|  |  | -        // case T_CONTINUE: cContinue(); break;
 | 
	
		
			
				|  |  | +        case T_RETURN: cReturn(); break;
 | 
	
		
			
				|  |  | +        case T_IF: cIf(); break;
 | 
	
		
			
				|  |  | +        case T_WHILE: cWhile(); break;
 | 
	
		
			
				|  |  | +        case T_FOR: cFor(); break;
 | 
	
		
			
				|  |  | +        case T_BREAK: cBreak(); break;
 | 
	
		
			
				|  |  | +        case T_CONTINUE: cContinue(); break;
 | 
	
		
			
				|  |  |          default: cLineExpression(t); cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void cFunctionArgument(Function* f);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cFunctionCommaOrEnd(Function* f) {
 | 
	
		
			
				|  |  | +    if(cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cConsumeToken(T_COMMA);
 | 
	
		
			
				|  |  | +    cFunctionArgument(f);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cFunctionAddArgument(Function* f, DataType dt) {
 | 
	
		
			
				|  |  | +    cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  | +    const char* name = cReadString();
 | 
	
		
			
				|  |  | +    Variable* v = vSearchScope(&vars, name);
 | 
	
		
			
				|  |  | +    if(v != NULL) {
 | 
	
		
			
				|  |  | +        cDeclared(name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    vAdd(&vars, name, dt);
 | 
	
		
			
				|  |  | +    if(fAddArgument(f, dt)) {
 | 
	
		
			
				|  |  | +        cTooMuchArguments();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cFunctionCommaOrEnd(f);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cFunctionArgument(Function* f) {
 | 
	
		
			
				|  |  | +    Token t = cReadTokenAndLine();
 | 
	
		
			
				|  |  | +    switch(t) {
 | 
	
		
			
				|  |  | +        case T_INT: cFunctionAddArgument(f, DT_INT); break;
 | 
	
		
			
				|  |  | +        default: cUnexpectedToken(t);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cFunctionArguments(Function* f) {
 | 
	
		
			
				|  |  | +    cConsumeToken(T_OPEN_BRACKET);
 | 
	
		
			
				|  |  | +    if(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | +        cFunctionArgument(f);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int cReserve(int offset) {
 | 
	
		
			
				|  |  | +    cAddOperation(OP_RESERVE);
 | 
	
		
			
				|  |  | +    int p = cReserveInt();
 | 
	
		
			
				|  |  | +    cAddInt(offset);
 | 
	
		
			
				|  |  | +    return p;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cFree(int p, int bytes) {
 | 
	
		
			
				|  |  | +    cAddOperation(OP_RETURN);
 | 
	
		
			
				|  |  | +    cAddInt(bytes);
 | 
	
		
			
				|  |  | +    cSetInt(p, bytes);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cLinkReturns(int bytes) {
 | 
	
		
			
				|  |  | +    for(int i = 0; i < returnIndex; i++) {
 | 
	
		
			
				|  |  | +        cSetInt(returns[i], bytes);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    returnIndex = 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cInnerFunction(Function* f) {
 | 
	
		
			
				|  |  | +    cConsumeToken(T_OPEN_CURVED_BRACKET);
 | 
	
		
			
				|  |  | +    int p = cReserve(f->size);
 | 
	
		
			
				|  |  | +    returnIndex = 0;
 | 
	
		
			
				|  |  | +    cConsumeScope();
 | 
	
		
			
				|  |  | +    cFree(p, vars.maxAddress);
 | 
	
		
			
				|  |  | +    cLinkReturns(vars.maxAddress);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static bool cForwardFunction(Function* found, Function* f) {
 | 
	
		
			
				|  |  | +    if(!cConsumeTokenIf(T_SEMICOLON)) {
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    } else if(found != NULL) {
 | 
	
		
			
				|  |  | +        cError("function registered twice");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    f->address = -1;
 | 
	
		
			
				|  |  | +    fsAdd(&functions, f);
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cBuildFunction(Function* f, DataType rType) {
 | 
	
		
			
				|  |  | +    cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  | +    fInit(f, cReadString(), line);
 | 
	
		
			
				|  |  | +    f->returnType = rType;
 | 
	
		
			
				|  |  | +    vReset(&vars);
 | 
	
		
			
				|  |  | +    cFunctionArguments(f);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cFunction(DataType rType) {
 | 
	
		
			
				|  |  | +    Function f;
 | 
	
		
			
				|  |  | +    cBuildFunction(&f, rType);
 | 
	
		
			
				|  |  | +    Function* found = fsSearch(&functions, &f);
 | 
	
		
			
				|  |  | +    if(cForwardFunction(found, &f)) {
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cAddOperation(OP_LINE);
 | 
	
		
			
				|  |  | +    cAddInt16(line);
 | 
	
		
			
				|  |  | +    cAddOperation(OP_GOTO);
 | 
	
		
			
				|  |  | +    int end = cReserveInt();
 | 
	
		
			
				|  |  | +    f.address = code->length;
 | 
	
		
			
				|  |  | +    if(found != NULL) {
 | 
	
		
			
				|  |  | +        if(found->address == -1) {
 | 
	
		
			
				|  |  | +            found->address = f.address;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            cError("function registered twice");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +        fsAdd(&functions, &f);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    returnType = rType;
 | 
	
		
			
				|  |  | +    cInnerFunction(&f);
 | 
	
		
			
				|  |  | +    cSetInt(end, code->length);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cGlobalScope(Token t) {
 | 
	
		
			
				|  |  | +    switch(t) {
 | 
	
		
			
				|  |  | +        case T_VOID: cFunction(DT_VOID); break;
 | 
	
		
			
				|  |  | +        case T_INT: cFunction(DT_INT); break;
 | 
	
		
			
				|  |  | +        case T_BOOL: cFunction(DT_BOOL); break;
 | 
	
		
			
				|  |  | +        default: cUnexpectedToken(t);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cCallMain() {
 | 
	
		
			
				|  |  | +    Function f;
 | 
	
		
			
				|  |  | +    fInit(&f, "main", line);
 | 
	
		
			
				|  |  | +    Function* found = fsSearch(&functions, &f);
 | 
	
		
			
				|  |  | +    if(found != NULL && found->returnType == DT_VOID) {
 | 
	
		
			
				|  |  | +        cAddOperation(OP_PUSH_INT);
 | 
	
		
			
				|  |  | +        cAddInt(0);
 | 
	
		
			
				|  |  | +        cAddOperation(OP_GOSUB);
 | 
	
		
			
				|  |  | +        cAddInt(found->address);
 | 
	
		
			
				|  |  | +        cAddInt(found->size);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void cForEachLine() {
 | 
	
		
			
				|  |  |      Token t = cReadTokenAndLine();
 | 
	
		
			
				|  |  |      while(t != T_END) {
 | 
	
		
			
				|  |  | -        cLine(t);
 | 
	
		
			
				|  |  | +        cGlobalScope(t);
 | 
	
		
			
				|  |  |          t = cReadTokenAndLine();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    cCallMain();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void cLinkQueuedFunctions() {
 | 
	
		
			
				|  |  | -    for(int i = 0; i < functions.queueEntries; i++) {
 | 
	
		
			
				|  |  | -        Function* f = fmSearch(&functions, functions.queue[i].name,
 | 
	
		
			
				|  |  | -                               functions.queue[i].arguments);
 | 
	
		
			
				|  |  | -        if(f == NULL) {
 | 
	
		
			
				|  |  | -            cError("unknown function on line %d", functions.queue[i].line);
 | 
	
		
			
				|  |  | -        } else if(!functions.queue[i].noReturn && !f->returns) {
 | 
	
		
			
				|  |  | -            cError("function '%s' needs a return value on line %d", f->name,
 | 
	
		
			
				|  |  | -                   functions.queue[i].line);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        cSetInt(functions.queue[i].reserved, f->address);
 | 
	
		
			
				|  |  | -        if(functions.queue[i].noReturn && f->returns) {
 | 
	
		
			
				|  |  | -            code->code[functions.queue[i].reserved + sizeof(int) * 2] = OP_POP;
 | 
	
		
			
				|  |  | +static void cLinkQueuedFunctions() {
 | 
	
		
			
				|  |  | +    for(int i = 0; i < functionQueue.entries; i++) {
 | 
	
		
			
				|  |  | +        Function* f = functionQueue.data + i;
 | 
	
		
			
				|  |  | +        Function* found = fsSearch(&functions, f);
 | 
	
		
			
				|  |  | +        if(found == NULL) {
 | 
	
		
			
				|  |  | +            line = f->line;
 | 
	
		
			
				|  |  | +            cError("unknown function");
 | 
	
		
			
				|  |  | +        } else if(f->returnType != found->returnType) {
 | 
	
		
			
				|  |  | +            line = f->line;
 | 
	
		
			
				|  |  | +            cError("function return type is not %s", dtGetName(f->returnType));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        cSetInt(f->address, found->address);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cAllocAndCompile() {
 | 
	
		
			
				|  |  | -    // varIndex = 0;
 | 
	
		
			
				|  |  | -    // returnIndex = 0;
 | 
	
		
			
				|  |  | -    // returnState = 0;
 | 
	
		
			
				|  |  | -    // forWhileStack = 0;
 | 
	
		
			
				|  |  | -    // breakIndex = 0;
 | 
	
		
			
				|  |  | +    forWhileStack = 0;
 | 
	
		
			
				|  |  | +    breakIndex = 0;
 | 
	
		
			
				|  |  |      vInit(&vars);
 | 
	
		
			
				|  |  | -    // fmInit(&functions);
 | 
	
		
			
				|  |  | +    fsInit(&functions);
 | 
	
		
			
				|  |  | +    fsInit(&functionQueue);
 | 
	
		
			
				|  |  |      if(!setjmp(errorJump)) {
 | 
	
		
			
				|  |  | -        // int p = cAddPush(0);
 | 
	
		
			
				|  |  |          cForEachLine();
 | 
	
		
			
				|  |  | -        // cAddPop(p, vars[varIndex].entries);
 | 
	
		
			
				|  |  | -        // cLinkQueuedFunctions();
 | 
	
		
			
				|  |  | +        cLinkQueuedFunctions();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    // fmDelete(&functions);
 | 
	
		
			
				|  |  | +    fsDelete(&functionQueue);
 | 
	
		
			
				|  |  | +    fsDelete(&functions);
 | 
	
		
			
				|  |  |      vDelete(&vars);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |