|
@@ -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);
|
|
|
}
|
|
|
|