|
@@ -78,6 +78,13 @@ static size_t codeGetWritePosition(const Context* c) {
|
|
|
return c->code->code.writeIndex;
|
|
return c->code->code.writeIndex;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static size_t codePushInstructionI32(Context* c, Instruction i, i32 v) {
|
|
|
|
|
+ codePushInstruction(c, i);
|
|
|
|
|
+ size_t pos = codeGetWritePosition(c);
|
|
|
|
|
+ codePushI32(c, v);
|
|
|
|
|
+ return pos;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void codeRewriteI32(Context* c, size_t pos, i32 i) {
|
|
static void codeRewriteI32(Context* c, size_t pos, i32 i) {
|
|
|
size_t oldPos = codeGetWritePosition(c);
|
|
size_t oldPos = codeGetWritePosition(c);
|
|
|
c->code->code.writeIndex = pos;
|
|
c->code->code.writeIndex = pos;
|
|
@@ -182,33 +189,24 @@ static void addReturn(Context* c, i32 address, bool hasArgument) {
|
|
|
c->returns = r;
|
|
c->returns = r;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#define CLEAN_LIST(Type, field) \
|
|
|
|
|
+ do { \
|
|
|
|
|
+ Type* v = c->field; \
|
|
|
|
|
+ while(v != nullptr) { \
|
|
|
|
|
+ Type* next = v->next; \
|
|
|
|
|
+ memoryFree(v); \
|
|
|
|
|
+ v = next; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ c->field = nullptr; \
|
|
|
|
|
+ } while(false)
|
|
|
|
|
+
|
|
|
static void cleanReturns(Context* c) {
|
|
static void cleanReturns(Context* c) {
|
|
|
- Return* r = c->returns;
|
|
|
|
|
- while(r != nullptr) {
|
|
|
|
|
- Return* next = r->next;
|
|
|
|
|
- memoryFree(r);
|
|
|
|
|
- r = next;
|
|
|
|
|
- }
|
|
|
|
|
- c->returns = nullptr;
|
|
|
|
|
|
|
+ CLEAN_LIST(Return, returns);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void cleanContext(Context* c) {
|
|
static void cleanContext(Context* c) {
|
|
|
- Variable* v = c->variables;
|
|
|
|
|
- while(v != nullptr) {
|
|
|
|
|
- Variable* next = v->next;
|
|
|
|
|
- memoryFree(v);
|
|
|
|
|
- v = next;
|
|
|
|
|
- }
|
|
|
|
|
- c->variables = nullptr;
|
|
|
|
|
-
|
|
|
|
|
- Function* f = c->functions;
|
|
|
|
|
- while(f != nullptr) {
|
|
|
|
|
- Function* next = f->next;
|
|
|
|
|
- memoryFree(f);
|
|
|
|
|
- f = next;
|
|
|
|
|
- }
|
|
|
|
|
- c->functions = nullptr;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ CLEAN_LIST(Variable, variables);
|
|
|
|
|
+ CLEAN_LIST(Function, functions);
|
|
|
cleanReturns(c);
|
|
cleanReturns(c);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -226,8 +224,20 @@ static Token consumeToken(Context* c, TokenType type) {
|
|
|
return actual;
|
|
return actual;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static bool peekToken(Context* c, TokenType type) {
|
|
|
|
|
+ return tokenizerPeek(c->tokenizer).type == type;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static bool consumeTokenIf(Context* c, TokenType type) {
|
|
|
|
|
+ if(peekToken(c, type)) {
|
|
|
|
|
+ consumeToken(c, type);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void consumeNewline(Context* c) {
|
|
static void consumeNewline(Context* c) {
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_INVALID) {
|
|
|
|
|
|
|
+ if(peekToken(c, TT_INVALID)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
consumeToken(c, TT_NEWLINE);
|
|
consumeToken(c, TT_NEWLINE);
|
|
@@ -236,8 +246,7 @@ static void consumeNewline(Context* c) {
|
|
|
|
|
|
|
|
static void compileReadVariable(Context* c, Token token, bool forceGlobal) {
|
|
static void compileReadVariable(Context* c, Token token, bool forceGlobal) {
|
|
|
i32 index = addVariable(c, token.stringValue, forceGlobal);
|
|
i32 index = addVariable(c, token.stringValue, forceGlobal);
|
|
|
- codePushInstruction(c, READ_VARIABLE);
|
|
|
|
|
- codePushI32(c, index);
|
|
|
|
|
|
|
+ codePushInstructionI32(c, READ_VARIABLE, index);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void compileCallFunction(Context* c, Token t);
|
|
static void compileCallFunction(Context* c, Token t);
|
|
@@ -248,10 +257,9 @@ static void compileConstant(Context* c) {
|
|
|
codePushInstruction(c, PUSH_CONSTANT_STRING);
|
|
codePushInstruction(c, PUSH_CONSTANT_STRING);
|
|
|
codePushConstantString(c, token.stringValue);
|
|
codePushConstantString(c, token.stringValue);
|
|
|
} else if(token.type == TT_INT32) {
|
|
} else if(token.type == TT_INT32) {
|
|
|
- codePushInstruction(c, PUSH_INT32);
|
|
|
|
|
- codePushI32(c, token.intValue);
|
|
|
|
|
|
|
+ codePushInstructionI32(c, PUSH_INT32, token.intValue);
|
|
|
} else if(token.type == TT_LITERAL) {
|
|
} else if(token.type == TT_LITERAL) {
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_OPEN_ROUND_BRACKET) {
|
|
|
|
|
|
|
+ if(peekToken(c, TT_OPEN_ROUND_BRACKET)) {
|
|
|
compileCallFunction(c, token);
|
|
compileCallFunction(c, token);
|
|
|
} else {
|
|
} else {
|
|
|
compileReadVariable(c, token, false);
|
|
compileReadVariable(c, token, false);
|
|
@@ -265,8 +273,7 @@ static void compileConstant(Context* c) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void compileUnary(Context* c) {
|
|
static void compileUnary(Context* c) {
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_NOT) {
|
|
|
|
|
- consumeToken(c, TT_NOT);
|
|
|
|
|
|
|
+ if(consumeTokenIf(c, TT_NOT)) {
|
|
|
compileUnary(c);
|
|
compileUnary(c);
|
|
|
codePushInstruction(c, NOT);
|
|
codePushInstruction(c, NOT);
|
|
|
} else {
|
|
} else {
|
|
@@ -277,13 +284,10 @@ static void compileUnary(Context* c) {
|
|
|
static void compileMul(Context* c) {
|
|
static void compileMul(Context* c) {
|
|
|
compileUnary(c);
|
|
compileUnary(c);
|
|
|
while(true) {
|
|
while(true) {
|
|
|
- Token t = tokenizerPeek(c->tokenizer);
|
|
|
|
|
- if(t.type == TT_MULTIPLY) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ if(consumeTokenIf(c, TT_MULTIPLY)) {
|
|
|
compileUnary(c);
|
|
compileUnary(c);
|
|
|
codePushInstruction(c, MUL);
|
|
codePushInstruction(c, MUL);
|
|
|
- } else if(t.type == TT_DIVIDE) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_DIVIDE)) {
|
|
|
compileUnary(c);
|
|
compileUnary(c);
|
|
|
codePushInstruction(c, DIV);
|
|
codePushInstruction(c, DIV);
|
|
|
} else {
|
|
} else {
|
|
@@ -295,13 +299,10 @@ static void compileMul(Context* c) {
|
|
|
static void compileAdd(Context* c) {
|
|
static void compileAdd(Context* c) {
|
|
|
compileMul(c);
|
|
compileMul(c);
|
|
|
while(true) {
|
|
while(true) {
|
|
|
- Token t = tokenizerPeek(c->tokenizer);
|
|
|
|
|
- if(t.type == TT_ADD) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ if(consumeTokenIf(c, TT_ADD)) {
|
|
|
compileMul(c);
|
|
compileMul(c);
|
|
|
codePushInstruction(c, ADD);
|
|
codePushInstruction(c, ADD);
|
|
|
- } else if(t.type == TT_SUBTRACT) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_SUBTRACT)) {
|
|
|
compileMul(c);
|
|
compileMul(c);
|
|
|
codePushInstruction(c, SUB);
|
|
codePushInstruction(c, SUB);
|
|
|
} else {
|
|
} else {
|
|
@@ -313,29 +314,22 @@ static void compileAdd(Context* c) {
|
|
|
static void compileCompare(Context* c) {
|
|
static void compileCompare(Context* c) {
|
|
|
compileAdd(c);
|
|
compileAdd(c);
|
|
|
while(true) {
|
|
while(true) {
|
|
|
- Token t = tokenizerPeek(c->tokenizer);
|
|
|
|
|
- if(t.type == TT_EQUAL) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ if(consumeTokenIf(c, TT_EQUAL)) {
|
|
|
compileAdd(c);
|
|
compileAdd(c);
|
|
|
codePushInstruction(c, EQUAL);
|
|
codePushInstruction(c, EQUAL);
|
|
|
- } else if(t.type == TT_NOT_EQUAL) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_NOT_EQUAL)) {
|
|
|
compileAdd(c);
|
|
compileAdd(c);
|
|
|
codePushInstruction(c, NOT_EQUAL);
|
|
codePushInstruction(c, NOT_EQUAL);
|
|
|
- } else if(t.type == TT_GREATER) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_GREATER)) {
|
|
|
compileAdd(c);
|
|
compileAdd(c);
|
|
|
codePushInstruction(c, GREATER);
|
|
codePushInstruction(c, GREATER);
|
|
|
- } else if(t.type == TT_SMALLER) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_SMALLER)) {
|
|
|
compileAdd(c);
|
|
compileAdd(c);
|
|
|
codePushInstruction(c, SMALLER);
|
|
codePushInstruction(c, SMALLER);
|
|
|
- } else if(t.type == TT_GREATER_OR_EQUAL) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_GREATER_OR_EQUAL)) {
|
|
|
compileAdd(c);
|
|
compileAdd(c);
|
|
|
codePushInstruction(c, GREATER_OR_EQUAL);
|
|
codePushInstruction(c, GREATER_OR_EQUAL);
|
|
|
- } else if(t.type == TT_SMALLER_OR_EQUAL) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_SMALLER_OR_EQUAL)) {
|
|
|
compileAdd(c);
|
|
compileAdd(c);
|
|
|
codePushInstruction(c, SMALLER_OR_EQUAL);
|
|
codePushInstruction(c, SMALLER_OR_EQUAL);
|
|
|
} else {
|
|
} else {
|
|
@@ -347,13 +341,10 @@ static void compileCompare(Context* c) {
|
|
|
static void compileLogical(Context* c) {
|
|
static void compileLogical(Context* c) {
|
|
|
compileCompare(c);
|
|
compileCompare(c);
|
|
|
while(true) {
|
|
while(true) {
|
|
|
- Token t = tokenizerPeek(c->tokenizer);
|
|
|
|
|
- if(t.type == TT_AND) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ if(consumeTokenIf(c, TT_AND)) {
|
|
|
compileCompare(c);
|
|
compileCompare(c);
|
|
|
codePushInstruction(c, AND);
|
|
codePushInstruction(c, AND);
|
|
|
- } else if(t.type == TT_OR) {
|
|
|
|
|
- tokenizerNext(c->tokenizer);
|
|
|
|
|
|
|
+ } else if(consumeTokenIf(c, TT_OR)) {
|
|
|
compileCompare(c);
|
|
compileCompare(c);
|
|
|
codePushInstruction(c, OR);
|
|
codePushInstruction(c, OR);
|
|
|
} else {
|
|
} else {
|
|
@@ -370,11 +361,9 @@ static void compileLine(Context* c, Token token);
|
|
|
|
|
|
|
|
static void compileIf(Context* c) {
|
|
static void compileIf(Context* c) {
|
|
|
compileExpression(c);
|
|
compileExpression(c);
|
|
|
- codePushInstruction(c, JUMP_ON_0);
|
|
|
|
|
- size_t posIndex = codeGetWritePosition(c);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
|
|
+ size_t posIndex = codePushInstructionI32(c, JUMP_ON_0, 0);
|
|
|
consumeNewline(c);
|
|
consumeNewline(c);
|
|
|
- while(tokenizerPeek(c->tokenizer).type != TT_END) {
|
|
|
|
|
|
|
+ while(!peekToken(c, TT_END)) {
|
|
|
compileLine(c, tokenizerNext(c->tokenizer));
|
|
compileLine(c, tokenizerNext(c->tokenizer));
|
|
|
}
|
|
}
|
|
|
consumeToken(c, TT_END);
|
|
consumeToken(c, TT_END);
|
|
@@ -385,9 +374,29 @@ static void compileIf(Context* c) {
|
|
|
static void compileSetVariable(Context* c, const char* name, bool forceGlobal) {
|
|
static void compileSetVariable(Context* c, const char* name, bool forceGlobal) {
|
|
|
consumeToken(c, TT_ASSIGN);
|
|
consumeToken(c, TT_ASSIGN);
|
|
|
compileExpression(c);
|
|
compileExpression(c);
|
|
|
- i32 index = addVariable(c, name, forceGlobal);
|
|
|
|
|
- codePushInstruction(c, SET_VARIABLE);
|
|
|
|
|
- codePushI32(c, index);
|
|
|
|
|
|
|
+ codePushInstructionI32(c, SET_VARIABLE, addVariable(c, name, forceGlobal));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static i32 compileFunctionArguments(Context* c) {
|
|
|
|
|
+ consumeToken(c, TT_OPEN_ROUND_BRACKET);
|
|
|
|
|
+ i32 vars = 0;
|
|
|
|
|
+ while(!peekToken(c, TT_CLOSE_ROUND_BRACKET)) {
|
|
|
|
|
+ if(vars > 0) {
|
|
|
|
|
+ consumeToken(c, TT_COMMA);
|
|
|
|
|
+ }
|
|
|
|
|
+ Token varToken = consumeToken(c, TT_LITERAL);
|
|
|
|
|
+ addVariable(c, varToken.stringValue, false);
|
|
|
|
|
+ vars++;
|
|
|
|
|
+ }
|
|
|
|
|
+ consumeToken(c, TT_CLOSE_ROUND_BRACKET);
|
|
|
|
|
+ return vars;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void rewriteReturns(Context* c, i32 address) {
|
|
|
|
|
+ for(Return* r = c->returns; r != nullptr; r = r->next) {
|
|
|
|
|
+ codeRewriteI32(c, (size_t)r->address, address);
|
|
|
|
|
+ }
|
|
|
|
|
+ cleanReturns(c);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void compileFunction(Context* c) {
|
|
static void compileFunction(Context* c) {
|
|
@@ -395,50 +404,22 @@ static void compileFunction(Context* c) {
|
|
|
THROW_ERROR("Functions in functions are not allowed");
|
|
THROW_ERROR("Functions in functions are not allowed");
|
|
|
}
|
|
}
|
|
|
c->inFunction = true;
|
|
c->inFunction = true;
|
|
|
-
|
|
|
|
|
- codePushInstruction(c, JUMP);
|
|
|
|
|
- size_t pos = codeGetWritePosition(c);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ size_t functionEnd = codePushInstructionI32(c, JUMP, 0);
|
|
|
i32 functionStart = (i32)codeGetWritePosition(c);
|
|
i32 functionStart = (i32)codeGetWritePosition(c);
|
|
|
Token t = consumeToken(c, TT_LITERAL);
|
|
Token t = consumeToken(c, TT_LITERAL);
|
|
|
-
|
|
|
|
|
- codePushInstruction(c, PUSH_STACK_VARIABLES);
|
|
|
|
|
- size_t stackVarsLoc = codeGetWritePosition(c);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
-
|
|
|
|
|
- consumeToken(c, TT_OPEN_ROUND_BRACKET);
|
|
|
|
|
- i32 vars = 0;
|
|
|
|
|
|
|
+ size_t stackVarsLoc = codePushInstructionI32(c, PUSH_STACK_VARIABLES, 0);
|
|
|
Variable* resetVar = c->variables;
|
|
Variable* resetVar = c->variables;
|
|
|
- while(true) {
|
|
|
|
|
- if(tokenizerPeek(c->tokenizer).type != TT_LITERAL) {
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- Token varToken = consumeToken(c, TT_LITERAL);
|
|
|
|
|
- addVariable(c, varToken.stringValue, false);
|
|
|
|
|
- vars++;
|
|
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_COMMA) {
|
|
|
|
|
- consumeToken(c, TT_COMMA);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ i32 vars = compileFunctionArguments(c);
|
|
|
addFunction(c, t.stringValue, functionStart, vars);
|
|
addFunction(c, t.stringValue, functionStart, vars);
|
|
|
- consumeToken(c, TT_CLOSE_ROUND_BRACKET);
|
|
|
|
|
- while(true) {
|
|
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_END) {
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ while(!peekToken(c, TT_END)) {
|
|
|
compileLine(c, tokenizerNext(c->tokenizer));
|
|
compileLine(c, tokenizerNext(c->tokenizer));
|
|
|
}
|
|
}
|
|
|
consumeToken(c, TT_END);
|
|
consumeToken(c, TT_END);
|
|
|
i32 popVars = hasLocalVar(c) ? -c->variables->index : 0;
|
|
i32 popVars = hasLocalVar(c) ? -c->variables->index : 0;
|
|
|
- codePushInstruction(c, PUSH_INT32);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
- codePushInstruction(c, RETURN_VALUE);
|
|
|
|
|
- codePushI32(c, popVars);
|
|
|
|
|
- for(Return* r = c->returns; r != nullptr; r = r->next) {
|
|
|
|
|
- codeRewriteI32(c, (size_t)r->address, popVars);
|
|
|
|
|
- }
|
|
|
|
|
- cleanReturns(c);
|
|
|
|
|
|
|
+ codePushInstructionI32(c, PUSH_INT32, 0);
|
|
|
|
|
+ codePushInstructionI32(c, RETURN_VALUE, popVars);
|
|
|
|
|
+ rewriteReturns(c, popVars);
|
|
|
codeRewriteI32(c, stackVarsLoc, popVars - vars);
|
|
codeRewriteI32(c, stackVarsLoc, popVars - vars);
|
|
|
|
|
|
|
|
while(c->variables != resetVar) {
|
|
while(c->variables != resetVar) {
|
|
@@ -447,28 +428,23 @@ static void compileFunction(Context* c) {
|
|
|
c->variables = next;
|
|
c->variables = next;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- codeRewriteI32(c, pos, (i32)codeGetWritePosition(c));
|
|
|
|
|
|
|
+ codeRewriteI32(c, functionEnd, (i32)codeGetWritePosition(c));
|
|
|
c->inFunction = false;
|
|
c->inFunction = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void compileCallFunction(Context* c, Token t) {
|
|
static void compileCallFunction(Context* c, Token t) {
|
|
|
// used to store return address and variable index
|
|
// used to store return address and variable index
|
|
|
- codePushInstruction(c, PUSH_INT32);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
- codePushInstruction(c, PUSH_INT32);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
|
|
+ codePushInstructionI32(c, PUSH_INT32, 0);
|
|
|
|
|
+ codePushInstructionI32(c, PUSH_INT32, 0);
|
|
|
|
|
|
|
|
consumeToken(c, TT_OPEN_ROUND_BRACKET);
|
|
consumeToken(c, TT_OPEN_ROUND_BRACKET);
|
|
|
i32 offset = 0;
|
|
i32 offset = 0;
|
|
|
- while(true) {
|
|
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_CLOSE_ROUND_BRACKET) {
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ while(!peekToken(c, TT_CLOSE_ROUND_BRACKET)) {
|
|
|
|
|
+ if(offset > 0) {
|
|
|
|
|
+ consumeToken(c, TT_COMMA);
|
|
|
}
|
|
}
|
|
|
offset++;
|
|
offset++;
|
|
|
compileExpression(c);
|
|
compileExpression(c);
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_COMMA) {
|
|
|
|
|
- consumeToken(c, TT_COMMA);
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
consumeToken(c, TT_CLOSE_ROUND_BRACKET);
|
|
consumeToken(c, TT_CLOSE_ROUND_BRACKET);
|
|
|
|
|
|
|
@@ -479,61 +455,56 @@ static void compileCallFunction(Context* c, Token t) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void compileReturn(Context* c) {
|
|
static void compileReturn(Context* c) {
|
|
|
- if(tokenizerPeek(c->tokenizer).type == TT_NEWLINE) {
|
|
|
|
|
|
|
+ if(peekToken(c, TT_NEWLINE)) {
|
|
|
consumeNewline(c);
|
|
consumeNewline(c);
|
|
|
- codePushInstruction(c, PUSH_INT32);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
|
|
+ codePushInstructionI32(c, PUSH_INT32, 0);
|
|
|
} else {
|
|
} else {
|
|
|
compileExpression(c);
|
|
compileExpression(c);
|
|
|
}
|
|
}
|
|
|
- codePushInstruction(c, RETURN_VALUE);
|
|
|
|
|
- i32 address = (i32)codeGetWritePosition(c);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
|
|
+ i32 address = (i32)codePushInstructionI32(c, RETURN_VALUE, 0);
|
|
|
addReturn(c, address, true);
|
|
addReturn(c, address, true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void compileLineLiteral(Context* c, Token token) {
|
|
|
|
|
+ const char* s = token.stringValue;
|
|
|
|
|
+ if(strcmp(s, "print") == 0) {
|
|
|
|
|
+ while(!peekToken(c, TT_NEWLINE)) {
|
|
|
|
|
+ compileExpression(c);
|
|
|
|
|
+ codePushInstruction(c, PRINT);
|
|
|
|
|
+ }
|
|
|
|
|
+ consumeNewline(c);
|
|
|
|
|
+ codePushInstruction(c, PRINT_NEWLINE);
|
|
|
|
|
+ } else if(peekToken(c, TT_ASSIGN)) {
|
|
|
|
|
+ compileSetVariable(c, s, false);
|
|
|
|
|
+ } else if(peekToken(c, TT_OPEN_ROUND_BRACKET)) {
|
|
|
|
|
+ compileCallFunction(c, token);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ THROW_ERROR("Unexpected literal(%s)", s);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void compileLine(Context* c, Token token) {
|
|
static void compileLine(Context* c, Token token) {
|
|
|
if(token.type == TT_NEWLINE) {
|
|
if(token.type == TT_NEWLINE) {
|
|
|
c->line++;
|
|
c->line++;
|
|
|
- return;
|
|
|
|
|
} else if(token.type == TT_IF) {
|
|
} else if(token.type == TT_IF) {
|
|
|
compileIf(c);
|
|
compileIf(c);
|
|
|
- return;
|
|
|
|
|
} else if(token.type == TT_FUNCTION) {
|
|
} else if(token.type == TT_FUNCTION) {
|
|
|
compileFunction(c);
|
|
compileFunction(c);
|
|
|
- return;
|
|
|
|
|
} else if(token.type == TT_RETURN) {
|
|
} else if(token.type == TT_RETURN) {
|
|
|
compileReturn(c);
|
|
compileReturn(c);
|
|
|
- return;
|
|
|
|
|
} else if(token.type == TT_DOLLAR) {
|
|
} else if(token.type == TT_DOLLAR) {
|
|
|
token = consumeToken(c, TT_LITERAL);
|
|
token = consumeToken(c, TT_LITERAL);
|
|
|
compileSetVariable(c, token.stringValue, true);
|
|
compileSetVariable(c, token.stringValue, true);
|
|
|
- return;
|
|
|
|
|
} else if(token.type != TT_LITERAL) {
|
|
} else if(token.type != TT_LITERAL) {
|
|
|
unexpectedToken(c, token, __LINE__);
|
|
unexpectedToken(c, token, __LINE__);
|
|
|
- }
|
|
|
|
|
- const char* s = token.stringValue;
|
|
|
|
|
- if(strcmp(s, "print") == 0) {
|
|
|
|
|
- while(tokenizerPeek(c->tokenizer).type != TT_NEWLINE) {
|
|
|
|
|
- compileExpression(c);
|
|
|
|
|
- codePushInstruction(c, PRINT);
|
|
|
|
|
- }
|
|
|
|
|
- consumeNewline(c);
|
|
|
|
|
- codePushInstruction(c, PRINT_NEWLINE);
|
|
|
|
|
- } else if(tokenizerPeek(c->tokenizer).type == TT_ASSIGN) {
|
|
|
|
|
- compileSetVariable(c, s, false);
|
|
|
|
|
- } else if(tokenizerPeek(c->tokenizer).type == TT_OPEN_ROUND_BRACKET) {
|
|
|
|
|
- compileCallFunction(c, token);
|
|
|
|
|
} else {
|
|
} else {
|
|
|
- THROW_ERROR("Unexpected literal(%s)", s);
|
|
|
|
|
|
|
+ compileLineLiteral(c, token);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void parseTokens(Context* c) {
|
|
static void parseTokens(Context* c) {
|
|
|
codeReset(c->code);
|
|
codeReset(c->code);
|
|
|
- codePushInstruction(c, PUSH_STACK_VARIABLES);
|
|
|
|
|
- size_t stackVarsLoc = codeGetWritePosition(c);
|
|
|
|
|
- codePushI32(c, 0);
|
|
|
|
|
|
|
+ size_t stackVarsLoc = codePushInstructionI32(c, PUSH_STACK_VARIABLES, 0);
|
|
|
|
|
|
|
|
while(true) {
|
|
while(true) {
|
|
|
Token token = tokenizerNext(c->tokenizer);
|
|
Token token = tokenizerNext(c->tokenizer);
|