|  | @@ -18,13 +18,11 @@ static int16 line = 1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static jmp_buf errorJump;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*#define RETURN_BUFFER 16
 | 
	
		
			
				|  |  | +#define RETURN_BUFFER 16
 | 
	
		
			
				|  |  |  #define BREAK_BUFFER 32
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define DT_OPERATION(op)                                                       \
 | 
	
		
			
				|  |  | -    case DT_INT32: cAddOperation(OP_##op##_INT32); break;                      \
 | 
	
		
			
				|  |  | -    case DT_INT64: cAddOperation(OP_##op##_INT64); break;                      \
 | 
	
		
			
				|  |  | -    case DT_BOOL: cAddOperation(OP_##op##_BOOL); break;                        \
 | 
	
		
			
				|  |  | +    case DT_INT: cAddOperation(OP_##op##_INT); break;                          \
 | 
	
		
			
				|  |  |      case DT_FLOAT: cAddOperation(OP_##op##_FLOAT); break;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef DataType (*Parser)(void);
 | 
	
	
		
			
				|  | @@ -49,33 +47,30 @@ static int continueAt = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef struct {
 | 
	
		
			
				|  |  |      Operation intOp;
 | 
	
		
			
				|  |  | -    Operation longOp;
 | 
	
		
			
				|  |  |      Operation floatOp;
 | 
	
		
			
				|  |  | -    Operation boolOp;
 | 
	
		
			
				|  |  |      Operation pointerOp;
 | 
	
		
			
				|  |  |      const char* name;
 | 
	
		
			
				|  |  |  } TypedOp;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define TYPE_OP(NAME, FLOAT, BOOL, POINTER, text)                              \
 | 
	
		
			
				|  |  | -    static const TypedOp TYPED_##NAME = {OP_##NAME##_INT32, OP_##NAME##_INT64, \
 | 
	
		
			
				|  |  | -                                         OP_##FLOAT,        OP_##BOOL,         \
 | 
	
		
			
				|  |  | -                                         OP_##POINTER,      text};
 | 
	
		
			
				|  |  | -TYPE_OP(MUL, MUL_FLOAT, NOTHING, NOTHING, "*")
 | 
	
		
			
				|  |  | -TYPE_OP(DIV, DIV_FLOAT, NOTHING, NOTHING, "/")
 | 
	
		
			
				|  |  | -TYPE_OP(MOD, NOTHING, NOTHING, NOTHING, "%")
 | 
	
		
			
				|  |  | -TYPE_OP(ADD, ADD_FLOAT, NOTHING, NOTHING, "+")
 | 
	
		
			
				|  |  | -TYPE_OP(SUB, SUB_FLOAT, NOTHING, NOTHING, "-")
 | 
	
		
			
				|  |  | -TYPE_OP(LESS, LESS_FLOAT, NOTHING, NOTHING, "<")
 | 
	
		
			
				|  |  | -TYPE_OP(LESS_EQUAL, LESS_EQUAL_FLOAT, NOTHING, NOTHING, "<=")
 | 
	
		
			
				|  |  | -TYPE_OP(GREATER, GREATER_FLOAT, NOTHING, NOTHING, ">")
 | 
	
		
			
				|  |  | -TYPE_OP(GREATER_EQUAL, GREATER_EQUAL_FLOAT, NOTHING, NOTHING, ">=")
 | 
	
		
			
				|  |  | -TYPE_OP(EQUAL, EQUAL_FLOAT, EQUAL_BOOL, EQUAL_POINTER, "==")
 | 
	
		
			
				|  |  | -TYPE_OP(NOT_EQUAL, NOT_EQUAL_FLOAT, NOT_EQUAL_BOOL, NOT_EQUAL_POINTER, "!=")
 | 
	
		
			
				|  |  | -TYPE_OP(BIT_OR, NOTHING, NOTHING, NOTHING, "|")
 | 
	
		
			
				|  |  | -TYPE_OP(BIT_XOR, NOTHING, NOTHING, NOTHING, "^")
 | 
	
		
			
				|  |  | -TYPE_OP(BIT_AND, NOTHING, NOTHING, NOTHING, "&")
 | 
	
		
			
				|  |  | -TYPE_OP(LEFT_SHIFT, NOTHING, NOTHING, NOTHING, "<<")
 | 
	
		
			
				|  |  | -TYPE_OP(RIGHT_SHIFT, NOTHING, NOTHING, NOTHING, ">>")
 | 
	
		
			
				|  |  | +#define TYPE_OP(NAME, FLOAT, POINTER, text)                                    \
 | 
	
		
			
				|  |  | +    static const TypedOp TYPED_##NAME = {OP_##NAME##_INT, OP_##FLOAT,          \
 | 
	
		
			
				|  |  | +                                         OP_##POINTER, text};
 | 
	
		
			
				|  |  | +TYPE_OP(MUL, MUL_FLOAT, NOTHING, "*")
 | 
	
		
			
				|  |  | +TYPE_OP(DIV, DIV_FLOAT, NOTHING, "/")
 | 
	
		
			
				|  |  | +TYPE_OP(MOD, NOTHING, NOTHING, "%")
 | 
	
		
			
				|  |  | +TYPE_OP(ADD, ADD_FLOAT, NOTHING, "+")
 | 
	
		
			
				|  |  | +TYPE_OP(SUB, SUB_FLOAT, NOTHING, "-")
 | 
	
		
			
				|  |  | +TYPE_OP(LESS, LESS_FLOAT, NOTHING, "<")
 | 
	
		
			
				|  |  | +TYPE_OP(LESS_EQUAL, LESS_EQUAL_FLOAT, NOTHING, "<=")
 | 
	
		
			
				|  |  | +TYPE_OP(GREATER, GREATER_FLOAT, NOTHING, ">")
 | 
	
		
			
				|  |  | +TYPE_OP(GREATER_EQUAL, GREATER_EQUAL_FLOAT, NOTHING, ">=")
 | 
	
		
			
				|  |  | +TYPE_OP(EQUAL, EQUAL_FLOAT, EQUAL_POINTER, "==")
 | 
	
		
			
				|  |  | +TYPE_OP(NOT_EQUAL, NOT_EQUAL_FLOAT, NOT_EQUAL_POINTER, "!=")
 | 
	
		
			
				|  |  | +TYPE_OP(BIT_OR, NOTHING, NOTHING, "|")
 | 
	
		
			
				|  |  | +TYPE_OP(BIT_XOR, NOTHING, NOTHING, "^")
 | 
	
		
			
				|  |  | +TYPE_OP(BIT_AND, NOTHING, NOTHING, "&")
 | 
	
		
			
				|  |  | +TYPE_OP(LEFT_SHIFT, NOTHING, NOTHING, "<<")
 | 
	
		
			
				|  |  | +TYPE_OP(RIGHT_SHIFT, NOTHING, NOTHING, ">>")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cError(const char* format, ...) {
 | 
	
		
			
				|  |  |      va_list args;
 | 
	
	
		
			
				|  | @@ -109,6 +104,19 @@ static void cUnexpectedToken(Token t) {
 | 
	
		
			
				|  |  |      cError("unexpected token: %s", tGetName(t));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#define BUFFER_SIZE 256
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void cUnknownFunction(Function* f) {
 | 
	
		
			
				|  |  | +    int max = 0;
 | 
	
		
			
				|  |  | +    char buffer[BUFFER_SIZE] = {'\0'};
 | 
	
		
			
				|  |  | +    for(int i = 0; i < f->arguments; i++) {
 | 
	
		
			
				|  |  | +        const char* name = dtGetName(&structs, f->argumentTypes[i]);
 | 
	
		
			
				|  |  | +        max += snprintf(buffer + max, BUFFER_SIZE - max, i > 0 ? ", %s" : "%s",
 | 
	
		
			
				|  |  | +                        name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cError("unknown function: %s(%s)", f->name, buffer);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void cAddOperation(Operation token) {
 | 
	
		
			
				|  |  |      unsigned char c = token;
 | 
	
		
			
				|  |  |      bcAddBytes(code, &c, 1);
 | 
	
	
		
			
				|  | @@ -126,10 +134,6 @@ static void cAddInt32(int32 i) {
 | 
	
		
			
				|  |  |      bcAddBytes(code, &i, sizeof(int32));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cAddInt64(int64 i) {
 | 
	
		
			
				|  |  | -    bcAddBytes(code, &i, sizeof(int64));
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static void cAddInt32Operation(Operation token, int32 i) {
 | 
	
		
			
				|  |  |      cAddOperation(token);
 | 
	
		
			
				|  |  |      cAddInt32(i);
 | 
	
	
		
			
				|  | @@ -140,18 +144,18 @@ static void cAddByteOperation(Operation token, int8 i) {
 | 
	
		
			
				|  |  |      bcAddBytes(code, &i, sizeof(int8));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cAddLine(int16 i) {
 | 
	
		
			
				|  |  | +static void cAddLine(int16 line) {
 | 
	
		
			
				|  |  |      cAddOperation(OP_LINE);
 | 
	
		
			
				|  |  | -    bcAddBytes(code, &i, sizeof(int16));
 | 
	
		
			
				|  |  | +    bcAddBytes(code, &line, sizeof(int16));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static Token cReadTokenAndLine() {
 | 
	
		
			
				|  |  | -    // hasReturn--;
 | 
	
		
			
				|  |  | -    Token t = tReadToken();
 | 
	
		
			
				|  |  | -    if(tReadInt16(&line)) {
 | 
	
		
			
				|  |  | -        return t;
 | 
	
		
			
				|  |  | +    hasReturn--;
 | 
	
		
			
				|  |  | +    Token t;
 | 
	
		
			
				|  |  | +    if(tReadTokenAndLine(&t, &line)) {
 | 
	
		
			
				|  |  | +        return T_END;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return T_END;
 | 
	
		
			
				|  |  | +    return t;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cConsumeToken(Token wanted) {
 | 
	
	
		
			
				|  | @@ -167,24 +171,15 @@ static bool cConsumeTokenIf(Token t) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cConstantInt32() {
 | 
	
		
			
				|  |  |      int32 value;
 | 
	
		
			
				|  |  | -    if(!tReadInt32(&value)) {
 | 
	
		
			
				|  |  | +    if(tReadInt32(&value)) {
 | 
	
		
			
				|  |  |          cError("int token without an int");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    cAddInt32Operation(OP_PUSH_INT32, value);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void cConstantInt64() {
 | 
	
		
			
				|  |  | -    int64 value;
 | 
	
		
			
				|  |  | -    if(!tReadInt64(&value)) {
 | 
	
		
			
				|  |  | -        cError("long token without an long");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    cAddOperation(OP_PUSH_INT64);
 | 
	
		
			
				|  |  | -    cAddInt64(value);
 | 
	
		
			
				|  |  | +    cAddInt32Operation(OP_PUSH_INT, value);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cConstantFloat() {
 | 
	
		
			
				|  |  |      float value;
 | 
	
		
			
				|  |  | -    if(!tReadFloat(&value)) {
 | 
	
		
			
				|  |  | +    if(tReadFloat(&value)) {
 | 
	
		
			
				|  |  |          cError("float token without a float");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      cAddOperation(OP_PUSH_FLOAT);
 | 
	
	
		
			
				|  | @@ -203,33 +198,18 @@ static int cGetSize(DataType dt) {
 | 
	
		
			
				|  |  |      return dtGetSize(dt, &structs);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static DataType cDereference(DataType dt) {
 | 
	
		
			
				|  |  | -    if(dtDereference(&dt)) {
 | 
	
		
			
				|  |  | -        cError("%s dereferenced too often", cGetName(dt));
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return dt;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static DataType cExtendType(DataType dt, bool constant) {
 | 
	
		
			
				|  |  | -    while(cConsumeTokenIf(T_MUL)) {
 | 
	
		
			
				|  |  | -        dt = cDereference(dt);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if(constant) {
 | 
	
		
			
				|  |  | -        dt = dtConst(dt);
 | 
	
		
			
				|  |  | +static DataType cExtendType(DataType dt) {
 | 
	
		
			
				|  |  | +    if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
 | 
	
		
			
				|  |  | +        cConsumeToken(T_CLOSE_SQUARE_BRACKET);
 | 
	
		
			
				|  |  | +        dt = dtToArray(dt);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return dt;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cReadType(Token t, bool force) {
 | 
	
		
			
				|  |  | -    bool c = t == T_CONST;
 | 
	
		
			
				|  |  | -    if(c) {
 | 
	
		
			
				|  |  | -        t = cReadTokenAndLine();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |      switch(t) {
 | 
	
		
			
				|  |  | -        case T_INT32: return cExtendType(dtInt32(), c);
 | 
	
		
			
				|  |  | -        case T_INT64: return cExtendType(dtInt64(), c);
 | 
	
		
			
				|  |  | -        case T_BOOL: return cExtendType(dtBool(), c);
 | 
	
		
			
				|  |  | -        case T_FLOAT: return cExtendType(dtFloat(), c);
 | 
	
		
			
				|  |  | +        case T_INT: return dtInt();
 | 
	
		
			
				|  |  | +        case T_FLOAT: return dtFloat();
 | 
	
		
			
				|  |  |          case T_LITERAL: {
 | 
	
		
			
				|  |  |              Struct* st = stsSearch(&structs, cReadString());
 | 
	
		
			
				|  |  |              if(st == NULL) {
 | 
	
	
		
			
				|  | @@ -239,7 +219,7 @@ static DataType cReadType(Token t, bool force) {
 | 
	
		
			
				|  |  |                      return dtVoid();
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            return cExtendType(dtStruct(st), c);
 | 
	
		
			
				|  |  | +            return dtStruct(st);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          default:
 | 
	
		
			
				|  |  |              if(force) {
 | 
	
	
		
			
				|  | @@ -249,22 +229,29 @@ static DataType cReadType(Token t, bool force) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static DataType cReadExtendedType(Token t, bool force) {
 | 
	
		
			
				|  |  | +    DataType dt = cReadType(t, force);
 | 
	
		
			
				|  |  | +    if(!dtIsVoid(dt)) {
 | 
	
		
			
				|  |  | +        dt = cExtendType(dt);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return dt;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static DataType cExpression();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cLoadRef(DataType type) {
 | 
	
		
			
				|  |  | -    if(dtIsPointer(type)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_REFERENCE);
 | 
	
		
			
				|  |  | +    if(dtIsArray(type)) {
 | 
	
		
			
				|  |  | +        cAddOperation(OP_LOAD_ARRAY);
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      switch(type.type) {
 | 
	
		
			
				|  |  |          DT_OPERATION(LOAD);
 | 
	
		
			
				|  |  | -        case DT_STRUCT: cAddInt32Operation(OP_LOAD, cGetSize(type)); break;
 | 
	
		
			
				|  |  |          default: cError("cannot load type %s", cGetName(type));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cUnpack(DataType dt) {
 | 
	
		
			
				|  |  | -    if(dtRemoveVariable(&dt)) {
 | 
	
		
			
				|  |  | +    if(dt.type != DT_STRUCT && dtRemovePointer(&dt)) {
 | 
	
		
			
				|  |  |          cLoadRef(dt);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return dt;
 | 
	
	
		
			
				|  | @@ -297,14 +284,14 @@ static DataType cCallFunction(const char* name) {
 | 
	
		
			
				|  |  |      onLine = false;
 | 
	
		
			
				|  |  |      cCallFunctionArguments(&f);
 | 
	
		
			
				|  |  |      onLine = oldOnLine;
 | 
	
		
			
				|  |  | -    Function* found = fsSearch(&functions, &f, false);
 | 
	
		
			
				|  |  | +    Function* found = fsSearch(&functions, &f);
 | 
	
		
			
				|  |  |      if(found == NULL) {
 | 
	
		
			
				|  |  | -        cError("unknown function");
 | 
	
		
			
				|  |  | +        cUnknownFunction(&f);
 | 
	
		
			
				|  |  |      } else if(found->global) {
 | 
	
		
			
				|  |  |          cAddInt32Operation(OP_CALL, found->line);
 | 
	
		
			
				|  |  |          return found->returnType;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    char push[1 + sizeof(int32)] = {OP_PUSH_INT32};
 | 
	
		
			
				|  |  | +    char push[1 + sizeof(int32)] = {OP_PUSH_INT};
 | 
	
		
			
				|  |  |      bcInsertBytes(code, push, sizeof(push), returnAddress);
 | 
	
		
			
				|  |  |      cAddOperation(OP_GOSUB);
 | 
	
		
			
				|  |  |      if(found->address == -1) {
 | 
	
	
		
			
				|  | @@ -319,15 +306,14 @@ static DataType cCallFunction(const char* name) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cStore(DataType left, DataType right, const char* name) {
 | 
	
		
			
				|  |  | -    if(dtIsPointer(left)) {
 | 
	
		
			
				|  |  | -        if(!dtNullCompare(left, right) &&
 | 
	
		
			
				|  |  | -           !dtNullCompare(left, dtConst(right))) {
 | 
	
		
			
				|  |  | +    if(dtIsArray(left)) {
 | 
	
		
			
				|  |  | +        if(!dtCompare(left, right)) {
 | 
	
		
			
				|  |  |              cInvalidOperation(left, right, name);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        cAddOperation(OP_STORE_POINTER);
 | 
	
		
			
				|  |  | +        cAddOperation(OP_STORE_ARRAY);
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    if(!dtNullCompare(left, right) && !dtNullCompare(dtConst(left), right)) {
 | 
	
		
			
				|  |  | +    if(!dtCompare(left, right)) {
 | 
	
		
			
				|  |  |          cInvalidOperation(left, right, name);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      switch(left.type) {
 | 
	
	
		
			
				|  | @@ -343,11 +329,19 @@ static DataType cLiteral() {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      Variable v;
 | 
	
		
			
				|  |  |      if(!vsSearch(&vars, &v, literal)) {
 | 
	
		
			
				|  |  | -        cAddInt32Operation(OP_DEREFERENCE_VAR, v.address);
 | 
	
		
			
				|  |  | -        return dtToVariable(v.type);
 | 
	
		
			
				|  |  | +        if(v.type.pointer != 0) {
 | 
	
		
			
				|  |  | +            if(v.type.type != DT_STRUCT) {
 | 
	
		
			
				|  |  | +                cError("non struct type %s should not be a pointer here",
 | 
	
		
			
				|  |  | +                       cGetName(v.type));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            cAddInt32Operation(OP_PUSH_STRUCT_REFERENCE, v.address);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            cAddInt32Operation(OP_DEREFERENCE_VAR, v.address);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return dtToPointer(v.type);
 | 
	
		
			
				|  |  |      } else if(!vsSearch(&globalVars, &v, literal)) {
 | 
	
		
			
				|  |  |          cAddInt32Operation(OP_DEREFERENCE_GVAR, v.address);
 | 
	
		
			
				|  |  | -        return dtToVariable(v.type);
 | 
	
		
			
				|  |  | +        return dtToPointer(v.type);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      cNotDeclared(literal);
 | 
	
		
			
				|  |  |      return dtVoid();
 | 
	
	
		
			
				|  | @@ -358,12 +352,12 @@ static DataType cText() {
 | 
	
		
			
				|  |  |      int32 lengthAddress = cReserveInt32();
 | 
	
		
			
				|  |  |      int32 length = 0;
 | 
	
		
			
				|  |  |      int32 c;
 | 
	
		
			
				|  |  | -    while(tReadInt32(&c) && c != 0) {
 | 
	
		
			
				|  |  | +    while(!tReadInt32(&c) && c != 0) {
 | 
	
		
			
				|  |  |          cAddInt32(c);
 | 
	
		
			
				|  |  |          length++;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      cSetInt32(lengthAddress, length);
 | 
	
		
			
				|  |  | -    return dtConst(dtText());
 | 
	
		
			
				|  |  | +    return dtText();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cBracketPrimary() {
 | 
	
	
		
			
				|  | @@ -372,39 +366,38 @@ static DataType cBracketPrimary() {
 | 
	
		
			
				|  |  |      return result;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cArrayIndex(const char* name) {
 | 
	
		
			
				|  |  | -    if(!dtIsInt32(cUnpackedExpression())) {
 | 
	
		
			
				|  |  | -        cError("array %s must be an int", name);
 | 
	
		
			
				|  |  | +static void cArrayIndex() {
 | 
	
		
			
				|  |  | +    if(!dtIsInt(cUnpackedExpression())) {
 | 
	
		
			
				|  |  | +        cError("array index must be an int");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cAllocArray() {
 | 
	
		
			
				|  |  |      DataType dt = cReadType(cReadTokenAndLine(), true);
 | 
	
		
			
				|  |  | +    if(dt.array != 0) {
 | 
	
		
			
				|  |  | +        cError("array type must not be an array");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      cConsumeToken(T_OPEN_SQUARE_BRACKET);
 | 
	
		
			
				|  |  | -    cArrayIndex("size");
 | 
	
		
			
				|  |  | +    cArrayIndex();
 | 
	
		
			
				|  |  |      cConsumeToken(T_CLOSE_SQUARE_BRACKET);
 | 
	
		
			
				|  |  |      cAddInt32Operation(OP_NEW, cGetSize(dt));
 | 
	
		
			
				|  |  | -    return cDereference(dt);
 | 
	
		
			
				|  |  | +    return dtToArray(dt);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cLength() {
 | 
	
		
			
				|  |  | -    DataType pointer = cUnpackedExpression();
 | 
	
		
			
				|  |  | -    if(!dtIsPointer(pointer)) {
 | 
	
		
			
				|  |  | -        cError("length expects a pointer");
 | 
	
		
			
				|  |  | +    DataType array = cUnpackedExpression();
 | 
	
		
			
				|  |  | +    if(!dtIsArray(array)) {
 | 
	
		
			
				|  |  | +        cError("length expects an array");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      cAddOperation(OP_LENGTH);
 | 
	
		
			
				|  |  | -    return dtInt32();
 | 
	
		
			
				|  |  | +    return dtInt();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cPrimary() {
 | 
	
		
			
				|  |  |      Token t = cReadTokenAndLine();
 | 
	
		
			
				|  |  |      switch(t) {
 | 
	
		
			
				|  |  | -        case T_CONST_INT32: cConstantInt32(); return dtInt32();
 | 
	
		
			
				|  |  | -        case T_CONST_INT64: cConstantInt64(); return dtInt64();
 | 
	
		
			
				|  |  | -        case T_CONST_FLOAT: cConstantFloat(); return dtFloat();
 | 
	
		
			
				|  |  | -        case T_TRUE: cAddOperation(OP_PUSH_TRUE); return dtBool();
 | 
	
		
			
				|  |  | -        case T_FALSE: cAddOperation(OP_PUSH_FALSE); return dtBool();
 | 
	
		
			
				|  |  | -        case T_NULLPTR: cAddOperation(OP_PUSH_NULLPTR); return dtNull();
 | 
	
		
			
				|  |  | +        case T_INT_VALUE: cConstantInt32(); return dtInt();
 | 
	
		
			
				|  |  | +        case T_FLOAT_VALUE: cConstantFloat(); return dtFloat();
 | 
	
		
			
				|  |  |          case T_TEXT: return cText();
 | 
	
		
			
				|  |  |          case T_OPEN_BRACKET: return cBracketPrimary();
 | 
	
		
			
				|  |  |          case T_LITERAL: return cLiteral();
 | 
	
	
		
			
				|  | @@ -415,7 +408,7 @@ static DataType cPrimary() {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cRemoveReference(DataType* dt, const char* name) {
 | 
	
		
			
				|  |  | -    if(!dtRemoveVariable(dt)) {
 | 
	
		
			
				|  |  | +    if(!dtRemovePointer(dt)) {
 | 
	
		
			
				|  |  |          cError("%s needs a reference not %s", name, cGetName(*dt));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -438,19 +431,17 @@ static void cChangeType(DataType* dt, Operation op, Operation pushOp,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cPostChange(DataType* dt, int change, const char* name) {
 | 
	
		
			
				|  |  |      cRemoveReference(dt, name);
 | 
	
		
			
				|  |  | -    if(dtIsInt32(*dt)) {
 | 
	
		
			
				|  |  | -        cChangeType(dt, OP_CHANGE_INT32, OP_PUSH_POST_CHANGE_INT32, change);
 | 
	
		
			
				|  |  | -    } else if(dtIsInt64(*dt)) {
 | 
	
		
			
				|  |  | -        cChangeType(dt, OP_CHANGE_INT64, OP_PUSH_POST_CHANGE_INT64, change);
 | 
	
		
			
				|  |  | +    if(dtIsInt(*dt)) {
 | 
	
		
			
				|  |  | +        cChangeType(dt, OP_CHANGE_INT, OP_PUSH_POST_CHANGE_INT, change);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -        cError("%s needs an int or long not %s", name, cGetName(*dt));
 | 
	
		
			
				|  |  | +        cError("%s needs an int not %s", name, cGetName(*dt));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static DataType cStructAccess(DataType dt, int pointers) {
 | 
	
		
			
				|  |  | +static DataType cStructAccess(DataType dt) {
 | 
	
		
			
				|  |  |      Struct* st = dtGetStruct(&structs, dt);
 | 
	
		
			
				|  |  | -    if(st == NULL || dt.pointers != pointers) {
 | 
	
		
			
				|  |  | -        cError(pointers == 0 ? ". expects a struct" : "-> expects a struct*");
 | 
	
		
			
				|  |  | +    if(st == NULL) {
 | 
	
		
			
				|  |  | +        cError(". expects a struct not %s", cGetName(dt));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  |      const char* name = cReadString();
 | 
	
	
		
			
				|  | @@ -458,12 +449,10 @@ static DataType cStructAccess(DataType dt, int pointers) {
 | 
	
		
			
				|  |  |      if(vSearchStruct(&inner, &structs, st, name)) {
 | 
	
		
			
				|  |  |          cError("%s has no member %s", st->name, name);
 | 
	
		
			
				|  |  |      } else if(inner.address > 0) {
 | 
	
		
			
				|  |  | -        cAddInt32Operation(OP_PUSH_INT32, inner.address);
 | 
	
		
			
				|  |  | +        cAddInt32Operation(OP_PUSH_INT, inner.address);
 | 
	
		
			
				|  |  |          cAddInt32Operation(OP_ADD_REFERENCE, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    DataType r = dtToVariable(inner.type);
 | 
	
		
			
				|  |  | -    r.constant = dt.constant;
 | 
	
		
			
				|  |  | -    return r;
 | 
	
		
			
				|  |  | +    return dtToPointer(inner.type);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cAccess() {
 | 
	
	
		
			
				|  | @@ -475,19 +464,17 @@ static DataType cAccess() {
 | 
	
		
			
				|  |  |              cPostChange(&dt, -1, "--");
 | 
	
		
			
				|  |  |          } else if(cConsumeTokenIf(T_POINT)) {
 | 
	
		
			
				|  |  |              cRemoveReference(&dt, ".");
 | 
	
		
			
				|  |  | -            dt = cStructAccess(dt, 0);
 | 
	
		
			
				|  |  | -        } else if(cConsumeTokenIf(T_ARROW)) {
 | 
	
		
			
				|  |  | -            dt = cStructAccess(cUnpack(dt), 1);
 | 
	
		
			
				|  |  | +            dt = cStructAccess(dt);
 | 
	
		
			
				|  |  |          } else if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
 | 
	
		
			
				|  |  | -            dt = cUnpack(dt);
 | 
	
		
			
				|  |  | -            if(!dtIsPointer(dt)) {
 | 
	
		
			
				|  |  | -                cError("[] needs a pointer");
 | 
	
		
			
				|  |  | +            if(!dtIsArray(dt)) {
 | 
	
		
			
				|  |  | +                cError("[] needs an array");
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            cAddOperation(OP_LOAD_ARRAY);
 | 
	
		
			
				|  |  | +            dtRemovePointer(&dt);
 | 
	
		
			
				|  |  |              cArrayIndex("index");
 | 
	
		
			
				|  |  |              cConsumeToken(T_CLOSE_SQUARE_BRACKET);
 | 
	
		
			
				|  |  | -            dt = dtReference(dt);
 | 
	
		
			
				|  |  |              cAddInt32Operation(OP_ADD_REFERENCE, cGetSize(dt));
 | 
	
		
			
				|  |  | -            dt = dtToVariable(dt);
 | 
	
		
			
				|  |  | +            dt = dtToPointer(dtRemoveArray(dt));
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |              return dt;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -496,21 +483,17 @@ static DataType cAccess() {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cPreChange(DataType dt, int change, const char* name) {
 | 
	
		
			
				|  |  |      cRemoveReference(&dt, name);
 | 
	
		
			
				|  |  | -    if(dtIsInt32(dt)) {
 | 
	
		
			
				|  |  | -        cChangeType(&dt, OP_CHANGE_INT32, OP_PUSH_PRE_CHANGE_INT32, change);
 | 
	
		
			
				|  |  | -    } else if(dtIsInt64(dt)) {
 | 
	
		
			
				|  |  | -        cChangeType(&dt, OP_CHANGE_INT64, OP_PUSH_PRE_CHANGE_INT64, change);
 | 
	
		
			
				|  |  | +    if(dtIsInt(dt)) {
 | 
	
		
			
				|  |  | +        cChangeType(&dt, OP_CHANGE_INT, OP_PUSH_PRE_CHANGE_INT, change);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -        cError("%s needs an int or long not %s", name, cGetName(dt));
 | 
	
		
			
				|  |  | +        cError("%s needs an int not %s", name, cGetName(dt));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return dt;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cInvertSign(DataType dt) {
 | 
	
		
			
				|  |  | -    if(dtIsInt32(dt)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_INVERT_SIGN_INT32);
 | 
	
		
			
				|  |  | -    } else if(dtIsInt64(dt)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_INVERT_SIGN_INT64);
 | 
	
		
			
				|  |  | +    if(dtIsInt(dt)) {
 | 
	
		
			
				|  |  | +        cAddOperation(OP_INVERT_SIGN_INT);
 | 
	
		
			
				|  |  |      } else if(dtIsFloat(dt)) {
 | 
	
		
			
				|  |  |          cAddOperation(OP_INVERT_SIGN_FLOAT);
 | 
	
		
			
				|  |  |      } else {
 | 
	
	
		
			
				|  | @@ -519,12 +502,9 @@ static DataType cInvertSign(DataType dt) {
 | 
	
		
			
				|  |  |      return dt;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static DataType cCast(DataType in, DataType a, Operation aOp, DataType b,
 | 
	
		
			
				|  |  | -                      Operation bOp, DataType out) {
 | 
	
		
			
				|  |  | +static DataType cCast(DataType in, DataType a, Operation aOp, DataType out) {
 | 
	
		
			
				|  |  |      if(dtCompare(in, a)) {
 | 
	
		
			
				|  |  |          cAddOperation(aOp);
 | 
	
		
			
				|  |  | -    } else if(dtCompare(in, b)) {
 | 
	
		
			
				|  |  | -        cAddOperation(bOp);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |          cError("cannot cast %s to %s", cGetName(in), cGetName(out));
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -532,36 +512,16 @@ static DataType cCast(DataType in, DataType a, Operation aOp, DataType b,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cUnaryNot(DataType dt) {
 | 
	
		
			
				|  |  | -    cExpectType(dt, dtBool(), "!");
 | 
	
		
			
				|  |  | +    cExpectType(dt, dtInt(), "!");
 | 
	
		
			
				|  |  |      cAddOperation(OP_NOT);
 | 
	
		
			
				|  |  |      return dt;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static DataType cUnaryBitNot(DataType dt) {
 | 
	
		
			
				|  |  | -    if(dtIsInt32(dt)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_BIT_NOT_INT32);
 | 
	
		
			
				|  |  | -    } else if(dtIsInt64(dt)) {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_BIT_NOT_INT64);
 | 
	
		
			
				|  |  | +    if(dtIsInt(dt)) {
 | 
	
		
			
				|  |  | +        cAddOperation(OP_BIT_NOT_INT);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -        cError("~ needs an int or long not %s", cGetName(dt));
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return dt;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static DataType cUnaryDereference(DataType dt) {
 | 
	
		
			
				|  |  | -    cRemoveReference(&dt, "&");
 | 
	
		
			
				|  |  | -    return cDereference(dt);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static DataType cUnaryReference(DataType dt) {
 | 
	
		
			
				|  |  | -    if(!dtIsPointer(dt)) {
 | 
	
		
			
				|  |  | -        cError("* expects a pointer");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    dt = dtReference(dt);
 | 
	
		
			
				|  |  | -    if(!dtIsPointer(dt) && !dtIsVariable(dt)) {
 | 
	
		
			
				|  |  | -        dt = dtToVariable(dt);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -        cAddOperation(OP_REFERENCE);
 | 
	
		
			
				|  |  | +        cError("~ needs an int not %s", cGetName(dt));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return dt;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -570,16 +530,11 @@ static DataType cPreUnary() {
 | 
	
		
			
				|  |  |      int marker = tGetMarker();
 | 
	
		
			
				|  |  |      if(cConsumeTokenIf(T_OPEN_BRACKET)) {
 | 
	
		
			
				|  |  |          if(cConsumeTokenIf(T_FLOAT) && cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | -            return cCast(cUnpack(cPreUnary()), dtInt32(), OP_INT32_TO_FLOAT,
 | 
	
		
			
				|  |  | -                         dtInt64(), OP_INT64_TO_FLOAT, dtFloat());
 | 
	
		
			
				|  |  | -        } else if(cConsumeTokenIf(T_INT32) &&
 | 
	
		
			
				|  |  | -                  cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | -            return cCast(cUnpack(cPreUnary()), dtFloat(), OP_FLOAT_TO_INT32,
 | 
	
		
			
				|  |  | -                         dtInt64(), OP_INT64_TO_INT32, dtInt32());
 | 
	
		
			
				|  |  | -        } else if(cConsumeTokenIf(T_INT64) &&
 | 
	
		
			
				|  |  | -                  cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | -            return cCast(cUnpack(cPreUnary()), dtInt32(), OP_INT32_TO_INT64,
 | 
	
		
			
				|  |  | -                         dtFloat(), OP_FLOAT_TO_INT64, dtInt64());
 | 
	
		
			
				|  |  | +            return cCast(cUnpack(cPreUnary()), dtInt(), OP_INT_TO_FLOAT,
 | 
	
		
			
				|  |  | +                         dtFloat());
 | 
	
		
			
				|  |  | +        } else if(cConsumeTokenIf(T_INT) && cConsumeTokenIf(T_CLOSE_BRACKET)) {
 | 
	
		
			
				|  |  | +            return cCast(cUnpack(cPreUnary()), dtFloat(), OP_FLOAT_TO_INT,
 | 
	
		
			
				|  |  | +                         dtInt());
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      tReset(marker);
 | 
	
	
		
			
				|  | @@ -593,10 +548,6 @@ static DataType cPreUnary() {
 | 
	
		
			
				|  |  |          return cUnaryNot(cPreUnary());
 | 
	
		
			
				|  |  |      } else if(cConsumeTokenIf(T_BIT_NOT)) {
 | 
	
		
			
				|  |  |          return cUnaryBitNot(cPreUnary());
 | 
	
		
			
				|  |  | -    } else if(cConsumeTokenIf(T_BIT_AND)) {
 | 
	
		
			
				|  |  | -        return cUnaryDereference(cPreUnary());
 | 
	
		
			
				|  |  | -    } else if(cConsumeTokenIf(T_MUL)) {
 | 
	
		
			
				|  |  | -        return cUnaryReference(cPreUnary());
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return cAccess();
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -604,19 +555,13 @@ static DataType cPreUnary() {
 | 
	
		
			
				|  |  |  static void cAddTypeOperation(DataType* a, Parser bf, const TypedOp* op) {
 | 
	
		
			
				|  |  |      *a = cUnpack(*a);
 | 
	
		
			
				|  |  |      DataType b = cUnpack(bf());
 | 
	
		
			
				|  |  | -    a->constant = 0;
 | 
	
		
			
				|  |  | -    b.constant = 0;
 | 
	
		
			
				|  |  | -    if(!dtNullCompare(*a, b)) {
 | 
	
		
			
				|  |  | +    if(!dtCompare(*a, b)) {
 | 
	
		
			
				|  |  |          cInvalidOperation(*a, b, op->name);
 | 
	
		
			
				|  |  | -    } else if(dtIsInt32(*a) && op->intOp != OP_NOTHING) {
 | 
	
		
			
				|  |  | +    } else if(dtIsInt(*a) && op->intOp != OP_NOTHING) {
 | 
	
		
			
				|  |  |          cAddOperation(op->intOp);
 | 
	
		
			
				|  |  | -    } else if(dtIsInt64(*a) && op->longOp != OP_NOTHING) {
 | 
	
		
			
				|  |  | -        cAddOperation(op->longOp);
 | 
	
		
			
				|  |  |      } else if(dtIsFloat(*a) && op->floatOp != OP_NOTHING) {
 | 
	
		
			
				|  |  |          cAddOperation(op->floatOp);
 | 
	
		
			
				|  |  | -    } else if(dtIsBool(*a) && op->boolOp != OP_NOTHING) {
 | 
	
		
			
				|  |  | -        cAddOperation(op->boolOp);
 | 
	
		
			
				|  |  | -    } else if(dtIsPointer(*a) && op->pointerOp != OP_NOTHING) {
 | 
	
		
			
				|  |  | +    } else if(dtIsArray(*a) && op->pointerOp != OP_NOTHING) {
 | 
	
		
			
				|  |  |          cAddOperation(op->pointerOp);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |          cInvalidOperation(*a, b, op->name);
 | 
	
	
		
			
				|  | @@ -669,16 +614,16 @@ static DataType cComparison() {
 | 
	
		
			
				|  |  |      while(true) {
 | 
	
		
			
				|  |  |          if(cConsumeTokenIf(T_LESS)) {
 | 
	
		
			
				|  |  |              cAddTypeOperation(&a, cShift, &TYPED_LESS);
 | 
	
		
			
				|  |  | -            a = dtBool();
 | 
	
		
			
				|  |  | +            a = dtInt();
 | 
	
		
			
				|  |  |          } else if(cConsumeTokenIf(T_LESS_EQUAL)) {
 | 
	
		
			
				|  |  |              cAddTypeOperation(&a, cShift, &TYPED_LESS_EQUAL);
 | 
	
		
			
				|  |  | -            a = dtBool();
 | 
	
		
			
				|  |  | +            a = dtInt();
 | 
	
		
			
				|  |  |          } else if(cConsumeTokenIf(T_GREATER)) {
 | 
	
		
			
				|  |  |              cAddTypeOperation(&a, cShift, &TYPED_GREATER);
 | 
	
		
			
				|  |  | -            a = dtBool();
 | 
	
		
			
				|  |  | +            a = dtInt();
 | 
	
		
			
				|  |  |          } else if(cConsumeTokenIf(T_GREATER_EQUAL)) {
 | 
	
		
			
				|  |  |              cAddTypeOperation(&a, cShift, &TYPED_GREATER_EQUAL);
 | 
	
		
			
				|  |  | -            a = dtBool();
 | 
	
		
			
				|  |  | +            a = dtInt();
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |              return a;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -690,10 +635,10 @@ static DataType cEqual() {
 | 
	
		
			
				|  |  |      while(true) {
 | 
	
		
			
				|  |  |          if(cConsumeTokenIf(T_EQUAL)) {
 | 
	
		
			
				|  |  |              cAddTypeOperation(&a, cComparison, &TYPED_EQUAL);
 | 
	
		
			
				|  |  | -            a = dtBool();
 | 
	
		
			
				|  |  | +            a = dtInt();
 | 
	
		
			
				|  |  |          } else if(cConsumeTokenIf(T_NOT_EQUAL)) {
 | 
	
		
			
				|  |  |              cAddTypeOperation(&a, cComparison, &TYPED_NOT_EQUAL);
 | 
	
		
			
				|  |  | -            a = dtBool();
 | 
	
		
			
				|  |  | +            a = dtInt();
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |              return a;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -723,11 +668,10 @@ static DataType cBitOr() {
 | 
	
		
			
				|  |  |  static DataType cLogical(Parser f, Token t, Operation jump, Operation op) {
 | 
	
		
			
				|  |  |      DataType a = f();
 | 
	
		
			
				|  |  |      while(cConsumeTokenIf(t)) {
 | 
	
		
			
				|  |  | -        a = cUnpack(a);
 | 
	
		
			
				|  |  |          cAddOperation(jump);
 | 
	
		
			
				|  |  |          int32 p = cReserveInt32();
 | 
	
		
			
				|  |  | -        DataType b = cUnpack(f());
 | 
	
		
			
				|  |  | -        if(!dtIsBool(a) || !dtIsBool(b)) {
 | 
	
		
			
				|  |  | +        DataType b = f();
 | 
	
		
			
				|  |  | +        if(!dtIsInt(a) || !dtIsInt(b)) {
 | 
	
		
			
				|  |  |              cInvalidOperation(a, b, tGetName(t));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          cAddOperation(op);
 | 
	
	
		
			
				|  | @@ -780,18 +724,13 @@ static void cReturn() {
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      DataType dt = cUnpackedExpression();
 | 
	
		
			
				|  |  | -    if(!dtNullCompare(returnType, dt) &&
 | 
	
		
			
				|  |  | -       !dtNullCompare(returnType, dtConst(dt))) {
 | 
	
		
			
				|  |  | +    if(!dtCompare(returnType, dt)) {
 | 
	
		
			
				|  |  |          cError("wrong return type, should be %s", cGetName(returnType));
 | 
	
		
			
				|  |  | -    } else if(dtIsInt32(dt)) {
 | 
	
		
			
				|  |  | -        cAddReturn(OP_RETURN_INT32);
 | 
	
		
			
				|  |  | -    } else if(dtIsInt64(dt)) {
 | 
	
		
			
				|  |  | -        cAddReturn(OP_RETURN_INT64);
 | 
	
		
			
				|  |  | -    } else if(dtIsBool(dt)) {
 | 
	
		
			
				|  |  | -        cAddReturn(OP_RETURN_BOOL);
 | 
	
		
			
				|  |  | +    } else if(dtIsInt(dt)) {
 | 
	
		
			
				|  |  | +        cAddReturn(OP_RETURN_INT);
 | 
	
		
			
				|  |  |      } else if(dtIsFloat(dt)) {
 | 
	
		
			
				|  |  |          cAddReturn(OP_RETURN_FLOAT);
 | 
	
		
			
				|  |  | -    } else if(dtIsPointer(dt) || dtIsNull(dt)) {
 | 
	
		
			
				|  |  | +    } else if(dtIsArray(dt)) {
 | 
	
		
			
				|  |  |          cAddReturn(OP_RETURN_POINTER);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |          cError("cannot return %s", cGetName(dt));
 | 
	
	
		
			
				|  | @@ -802,7 +741,7 @@ static void cReturn() {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cIf() {
 | 
	
		
			
				|  |  |      cConsumeToken(T_OPEN_BRACKET);
 | 
	
		
			
				|  |  | -    cExpectType(cUnpackedExpression(), dtBool(), "if");
 | 
	
		
			
				|  |  | +    cExpectType(cExpression(), dtInt(), "if");
 | 
	
		
			
				|  |  |      cConsumeToken(T_CLOSE_BRACKET);
 | 
	
		
			
				|  |  |      cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  |      int32 ifP = cReserveInt32();
 | 
	
	
		
			
				|  | @@ -833,7 +772,7 @@ static void cConsumeBreaks(int start, int address) {
 | 
	
		
			
				|  |  |  static void cWhile() {
 | 
	
		
			
				|  |  |      int start = code->length;
 | 
	
		
			
				|  |  |      cConsumeToken(T_OPEN_BRACKET);
 | 
	
		
			
				|  |  | -    cExpectType(cUnpackedExpression(), dtBool(), "while");
 | 
	
		
			
				|  |  | +    cExpectType(cExpression(), dtInt(), "while");
 | 
	
		
			
				|  |  |      cConsumeToken(T_CLOSE_BRACKET);
 | 
	
		
			
				|  |  |      cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  |      int32 ifP = cReserveInt32();
 | 
	
	
		
			
				|  | @@ -850,19 +789,8 @@ static void cWhile() {
 | 
	
		
			
				|  |  |      cConsumeBreaks(breakStart, code->length);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void cDelete() {
 | 
	
		
			
				|  |  | -    DataType pointer = cUnpackedExpression();
 | 
	
		
			
				|  |  | -    if(!dtIsPointer(pointer) || pointer.constant) {
 | 
	
		
			
				|  |  | -        cError("delete expects a non const pointer");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    cAddOperation(OP_DELETE);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static void cOperationSet(DataType left, const TypedOp* op) {
 | 
	
		
			
				|  |  |      cAddOperation(OP_DUPLICATE_REFERENCE);
 | 
	
		
			
				|  |  | -    if(left.constant) {
 | 
	
		
			
				|  |  | -        cError("cannot use %s= on const reference", op->name);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |      cLoadRef(left);
 | 
	
		
			
				|  |  |      cAddTypeOperation(&left, cUnpackedExpression, op);
 | 
	
		
			
				|  |  |      cStore(left, left, "=");
 | 
	
	
		
			
				|  | @@ -899,19 +827,16 @@ static void cDeclareSet(Variables* vs, DataType dt, const char* var,
 | 
	
		
			
				|  |  |          cDeclared(var);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      Variable* v = vsAdd(vs, var, dt, &structs);
 | 
	
		
			
				|  |  | -    if(dt.type != DT_STRUCT || dtIsPointer(dt)) {
 | 
	
		
			
				|  |  | +    if(dt.type != DT_STRUCT || dtIsArray(dt)) {
 | 
	
		
			
				|  |  |          cConsumeToken(T_SET);
 | 
	
		
			
				|  |  |          cAddInt32Operation(op, v->address);
 | 
	
		
			
				|  |  |          DataType right = cUnpackedExpression();
 | 
	
		
			
				|  |  | -        if(!right.constant) {
 | 
	
		
			
				|  |  | -            dt.constant = 0;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |          cStore(dt, right, "=");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static bool cDeclaration(Token t) {
 | 
	
		
			
				|  |  | -    DataType dt = cReadType(t, false);
 | 
	
		
			
				|  |  | +    DataType dt = cReadExtendedType(t, false);
 | 
	
		
			
				|  |  |      if(dtIsVoid(dt)) {
 | 
	
		
			
				|  |  |          return false;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -927,10 +852,8 @@ static void cLineExpression() {
 | 
	
		
			
				|  |  |      if(cDeclaration(t)) {
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    switch(t) {
 | 
	
		
			
				|  |  | -        case T_DELETE: cDelete(); break;
 | 
	
		
			
				|  |  | -        default: tReset(marker); cSetVariable();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    tReset(marker);
 | 
	
		
			
				|  |  | +    cSetVariable();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cFor() {
 | 
	
	
		
			
				|  | @@ -941,7 +864,7 @@ static void cFor() {
 | 
	
		
			
				|  |  |      cLineExpression();
 | 
	
		
			
				|  |  |      cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  |      int startCheck = code->length;
 | 
	
		
			
				|  |  | -    cExpectType(cUnpackedExpression(), dtBool(), "for");
 | 
	
		
			
				|  |  | +    cExpectType(cExpression(), dtInt(), "for");
 | 
	
		
			
				|  |  |      cConsumeToken(T_SEMICOLON);
 | 
	
		
			
				|  |  |      cAddOperation(OP_IF_GOTO);
 | 
	
		
			
				|  |  |      int32 end = cReserveInt32();
 | 
	
	
		
			
				|  | @@ -1006,6 +929,9 @@ static void cLine() {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cBuildFunction(Function* f, DataType rType, const char* name) {
 | 
	
		
			
				|  |  | +    if(rType.type == DT_STRUCT && rType.array == 0) {
 | 
	
		
			
				|  |  | +        cError("structs cannot be returned");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      fInit(f, name, line);
 | 
	
		
			
				|  |  |      f->returnType = rType;
 | 
	
		
			
				|  |  |      vsReset(&vars);
 | 
	
	
		
			
				|  | @@ -1014,12 +940,15 @@ static void cBuildFunction(Function* f, DataType rType, const char* name) {
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      while(true) {
 | 
	
		
			
				|  |  | -        DataType dt = cReadType(cReadTokenAndLine(), true);
 | 
	
		
			
				|  |  | +        DataType dt = cReadExtendedType(cReadTokenAndLine(), true);
 | 
	
		
			
				|  |  |          cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  |          const char* name = cReadString();
 | 
	
		
			
				|  |  |          if(vsInScope(&vars, name)) {
 | 
	
		
			
				|  |  |              cDeclared(name);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        if(dt.type == DT_STRUCT) {
 | 
	
		
			
				|  |  | +            dt = dtToPointer(dt);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          vsAdd(&vars, name, dt, &structs);
 | 
	
		
			
				|  |  |          if(fAddArgument(f, dt, &structs)) {
 | 
	
		
			
				|  |  |              cTooMuchArguments();
 | 
	
	
		
			
				|  | @@ -1065,7 +994,7 @@ static void cInnerFunction(Function* f) {
 | 
	
		
			
				|  |  |  static void cFunction(DataType rType, const char* name) {
 | 
	
		
			
				|  |  |      Function f;
 | 
	
		
			
				|  |  |      cBuildFunction(&f, rType, name);
 | 
	
		
			
				|  |  | -    Function* found = fsSearch(&functions, &f, true);
 | 
	
		
			
				|  |  | +    Function* found = fsSearch(&functions, &f);
 | 
	
		
			
				|  |  |      if(cConsumeTokenIf(T_SEMICOLON)) {
 | 
	
		
			
				|  |  |          cAddFunction(found, &f);
 | 
	
		
			
				|  |  |          return;
 | 
	
	
		
			
				|  | @@ -1090,7 +1019,7 @@ static void cStruct() {
 | 
	
		
			
				|  |  |      DataType self = dtStruct(st);
 | 
	
		
			
				|  |  |      cConsumeToken(T_OPEN_CURVED_BRACKET);
 | 
	
		
			
				|  |  |      while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
 | 
	
		
			
				|  |  | -        DataType dt = cReadType(cReadTokenAndLine(), true);
 | 
	
		
			
				|  |  | +        DataType dt = cReadExtendedType(cReadTokenAndLine(), true);
 | 
	
		
			
				|  |  |          if(dtCompare(dt, self)) {
 | 
	
		
			
				|  |  |              cError("struct %s contains itself", name);
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -1108,7 +1037,7 @@ static void cGlobalScope(Token t) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      DataType dt = dtVoid();
 | 
	
		
			
				|  |  |      if(t != T_VOID) {
 | 
	
		
			
				|  |  | -        dt = cReadType(t, true);
 | 
	
		
			
				|  |  | +        dt = cReadExtendedType(t, true);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      cConsumeToken(T_LITERAL);
 | 
	
		
			
				|  |  |      const char* name = cReadString();
 | 
	
	
		
			
				|  | @@ -1123,9 +1052,9 @@ static void cGlobalScope(Token t) {
 | 
	
		
			
				|  |  |  static void cCallMain() {
 | 
	
		
			
				|  |  |      Function f;
 | 
	
		
			
				|  |  |      fInit(&f, "main", line);
 | 
	
		
			
				|  |  | -    Function* found = fsSearch(&functions, &f, true);
 | 
	
		
			
				|  |  | +    Function* found = fsSearch(&functions, &f);
 | 
	
		
			
				|  |  |      if(found != NULL && dtIsVoid(found->returnType)) {
 | 
	
		
			
				|  |  | -        cAddInt32Operation(OP_PUSH_INT32, 0);
 | 
	
		
			
				|  |  | +        cAddInt32Operation(OP_PUSH_INT, 0);
 | 
	
		
			
				|  |  |          cAddInt32Operation(OP_GOSUB, found->address);
 | 
	
		
			
				|  |  |          cAddInt32(found->size);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -1149,26 +1078,17 @@ static void cForEachLine() {
 | 
	
		
			
				|  |  |  static void cLinkQueuedFunctions() {
 | 
	
		
			
				|  |  |      for(int i = 0; i < functionQueue.entries; i++) {
 | 
	
		
			
				|  |  |          Function* f = functionQueue.data + i;
 | 
	
		
			
				|  |  | -        Function* found = fsSearch(&functions, f, false);
 | 
	
		
			
				|  |  | +        Function* found = fsSearch(&functions, f);
 | 
	
		
			
				|  |  |          if(found == NULL || found->address == -1) {
 | 
	
		
			
				|  |  |              line = f->line;
 | 
	
		
			
				|  |  | -            cError("unknown function");
 | 
	
		
			
				|  |  | +            cUnknownFunction(f);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          cSetInt32(f->address, found->address);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void cScanForFunctions() {
 | 
	
		
			
				|  |  | -    /*while(true) {
 | 
	
		
			
				|  |  | -        Token t = cReadTokenAndLine();
 | 
	
		
			
				|  |  | -        if(t == T_END) {
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }*/
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void cAllocAndCompile() {
 | 
	
		
			
				|  |  | -    /*forWhileStack = 0;
 | 
	
		
			
				|  |  | +    forWhileStack = 0;
 | 
	
		
			
				|  |  |      breakIndex = 0;
 | 
	
		
			
				|  |  |      returnType = dtVoid();
 | 
	
		
			
				|  |  |      onLine = false;
 | 
	
	
		
			
				|  | @@ -1176,17 +1096,16 @@ static void cAllocAndCompile() {
 | 
	
		
			
				|  |  |      vsInit(&globalVars);
 | 
	
		
			
				|  |  |      fsInit(&functions);
 | 
	
		
			
				|  |  |      fsInit(&functionQueue);
 | 
	
		
			
				|  |  | -    stsInit(&structs);*/
 | 
	
		
			
				|  |  | +    stsInit(&structs);
 | 
	
		
			
				|  |  |      if(!setjmp(errorJump)) {
 | 
	
		
			
				|  |  | -        cScanForFunctions();
 | 
	
		
			
				|  |  | -        // cForEachLine();
 | 
	
		
			
				|  |  | -        // cLinkQueuedFunctions();
 | 
	
		
			
				|  |  | +        cForEachLine();
 | 
	
		
			
				|  |  | +        cLinkQueuedFunctions();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    /*stsDelete(&structs);
 | 
	
		
			
				|  |  | +    stsDelete(&structs);
 | 
	
		
			
				|  |  |      fsDelete(&functionQueue);
 | 
	
		
			
				|  |  |      fsDelete(&functions);
 | 
	
		
			
				|  |  |      vsDelete(&globalVars);
 | 
	
		
			
				|  |  | -    vsDelete(&vars);*/
 | 
	
		
			
				|  |  | +    vsDelete(&vars);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ByteCode* cCompile() {
 |