|
@@ -1,7 +1,5 @@
|
|
|
#include <stdarg.h>
|
|
|
#include <stdio.h>
|
|
|
-#include <stdlib.h>
|
|
|
-#include <string.h>
|
|
|
|
|
|
#include "Compiler.h"
|
|
|
#include "Operation.h"
|
|
@@ -14,8 +12,8 @@
|
|
|
|
|
|
static char error[ERROR_LENGTH] = {'\0'};
|
|
|
|
|
|
-static unsigned char byteCode[MAX_BYTES];
|
|
|
-static int writeIndex = 0;
|
|
|
+static ByteCode* code;
|
|
|
+
|
|
|
static int16 line = 1;
|
|
|
|
|
|
static StringIntMap vars;
|
|
@@ -42,32 +40,29 @@ static void cUnexpectedToken(Token t) {
|
|
|
cError("unexpected token on line %d: %s", line, tGetTokenName(t));
|
|
|
}
|
|
|
|
|
|
-static void* cReserveBytes(int length) {
|
|
|
- if(writeIndex + length > MAX_BYTES) {
|
|
|
- cError("the compiler buffer is too small");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- unsigned char* p = byteCode + writeIndex;
|
|
|
- writeIndex += length;
|
|
|
- return p;
|
|
|
+static void cAddOperation(Operation token) {
|
|
|
+ unsigned char c = token;
|
|
|
+ bcAddBytes(code, &c, 1);
|
|
|
}
|
|
|
|
|
|
-static void cSetBytes(const void* data, void* dest, int length) {
|
|
|
- memcpy(dest, data, length);
|
|
|
+static int cReserveInt() {
|
|
|
+ return bcReserveBytes(code, sizeof(int));
|
|
|
}
|
|
|
|
|
|
-static bool cAddBytes(const void* data, int length) {
|
|
|
- void* p = cReserveBytes(length);
|
|
|
- if(p == NULL) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- cSetBytes(data, p, length);
|
|
|
- return true;
|
|
|
+static void cSetInt(int p, int i) {
|
|
|
+ bcSetBytes(code, p, &i, sizeof(int));
|
|
|
}
|
|
|
|
|
|
-static bool cAddOperation(Operation token) {
|
|
|
- unsigned char c = token;
|
|
|
- return cAddBytes(&c, 1);
|
|
|
+static void cAddInt(int i) {
|
|
|
+ bcAddBytes(code, &i, sizeof(int));
|
|
|
+}
|
|
|
+
|
|
|
+static void cAddInt16(int16 i) {
|
|
|
+ bcAddBytes(code, &i, sizeof(int16));
|
|
|
+}
|
|
|
+
|
|
|
+static void cAddFloat(float f) {
|
|
|
+ bcAddBytes(code, &f, sizeof(float));
|
|
|
}
|
|
|
|
|
|
static Token tReadTokenAndLine() {
|
|
@@ -97,42 +92,60 @@ static bool cConsumeTokenIf(Token t) {
|
|
|
|
|
|
static bool cExpression();
|
|
|
|
|
|
-static bool cPrimary() {
|
|
|
- if(cConsumeTokenIf(T_INT)) {
|
|
|
- int value;
|
|
|
- return tReadInt(&value) && cAddOperation(OP_PUSH_INT) && cAddBytes(&value, sizeof(int));
|
|
|
- } else if(cConsumeTokenIf(T_FLOAT)) {
|
|
|
- float value;
|
|
|
- return tReadFloat(&value) && cAddOperation(OP_PUSH_FLOAT) && cAddBytes(&value, sizeof(float));
|
|
|
- } else if(cConsumeTokenIf(T_NULL)) {
|
|
|
- return cAddOperation(OP_PUSH_NULL);
|
|
|
- } else if(cConsumeTokenIf(T_TRUE)) {
|
|
|
- return cAddOperation(OP_PUSH_TRUE);
|
|
|
- } else if(cConsumeTokenIf(T_FALSE)) {
|
|
|
- return cAddOperation(OP_PUSH_FALSE);
|
|
|
- } else if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
|
- return cExpression() && cConsumeToken(T_CLOSE_BRACKET);
|
|
|
- } else if(cConsumeTokenIf(T_LITERAL)) {
|
|
|
- const char* literal = tReadString();
|
|
|
- if(literal == NULL) {
|
|
|
- cError("literal without string on line %d", line);
|
|
|
- return false;
|
|
|
- }
|
|
|
- int varPointer = cAddVar(literal);
|
|
|
- return cAddOperation(OP_GET) && cAddBytes(&varPointer, sizeof(int));
|
|
|
+static bool cConstantInt() {
|
|
|
+ int value;
|
|
|
+ if(tReadInt(&value)) {
|
|
|
+ cAddOperation(OP_PUSH_INT);
|
|
|
+ cAddInt(value);
|
|
|
+ return true;
|
|
|
}
|
|
|
- cUnexpectedToken(tPeekToken());
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+static bool cConstantFloat() {
|
|
|
+ float value;
|
|
|
+ if(tReadFloat(&value)) {
|
|
|
+ cAddOperation(OP_PUSH_FLOAT);
|
|
|
+ cAddFloat(value);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static bool cGetVar() {
|
|
|
+ const char* literal = tReadString();
|
|
|
+ if(literal == NULL) {
|
|
|
+ cError("literal without string on line %d", line);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ cAddOperation(OP_GET);
|
|
|
+ cAddInt(cAddVar(literal));
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static bool cPrimary() {
|
|
|
+ Token t = tReadTokenAndLine();
|
|
|
+ switch(t) {
|
|
|
+ case T_INT: return cConstantInt();
|
|
|
+ case T_FLOAT: return cConstantFloat();
|
|
|
+ case T_NULL: cAddOperation(OP_PUSH_NULL); return true;
|
|
|
+ case T_TRUE: cAddOperation(OP_PUSH_TRUE); return true;
|
|
|
+ case T_FALSE: cAddOperation(OP_PUSH_FALSE); return true;
|
|
|
+ case T_OPEN_BRACKET: return cExpression() && cConsumeToken(T_CLOSE_BRACKET);
|
|
|
+ case T_LITERAL: return cGetVar();
|
|
|
+ default: cUnexpectedToken(t); return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static bool cMul() {
|
|
|
if(!cPrimary()) {
|
|
|
return false;
|
|
|
}
|
|
|
while(cConsumeTokenIf(T_MUL)) {
|
|
|
- if(!cPrimary() || !cAddOperation(OP_MUL)) {
|
|
|
+ if(!cPrimary()) {
|
|
|
return false;
|
|
|
}
|
|
|
+ cAddOperation(OP_MUL);
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
@@ -142,9 +155,10 @@ static bool cAdd() {
|
|
|
return false;
|
|
|
}
|
|
|
while(cConsumeTokenIf(T_ADD)) {
|
|
|
- if(!cMul() || !cAddOperation(OP_ADD)) {
|
|
|
+ if(!cMul()) {
|
|
|
return false;
|
|
|
}
|
|
|
+ cAddOperation(OP_ADD);
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
@@ -154,16 +168,17 @@ static bool cExpression() {
|
|
|
}
|
|
|
|
|
|
static bool cSetVar(const char* literal) {
|
|
|
- int varPointer = cAddVar(literal);
|
|
|
- return cExpression() && cAddOperation(OP_SET) && cAddBytes(&varPointer, sizeof(int)) && cConsumeToken(T_SEMICOLON);
|
|
|
+ bool b = cExpression() && cConsumeToken(T_SEMICOLON);
|
|
|
+ cAddOperation(OP_SET);
|
|
|
+ cAddInt(cAddVar(literal));
|
|
|
+ return b;
|
|
|
}
|
|
|
|
|
|
static bool cCallFunction(const char* literal) {
|
|
|
int index;
|
|
|
if(simSearch(&functions, literal, &index)) {
|
|
|
- if(!cAddOperation(OP_GOSUB) || !cAddBytes(&index, sizeof(int))) {
|
|
|
- return false;
|
|
|
- }
|
|
|
+ cAddOperation(OP_GOSUB);
|
|
|
+ cAddInt(index);
|
|
|
} else {
|
|
|
cError("unknown function on line %d", line);
|
|
|
return false;
|
|
@@ -201,13 +216,10 @@ static bool cFunction() {
|
|
|
if(!cConsumeToken(T_OPEN_BRACKET) || !cConsumeToken(T_CLOSE_BRACKET) || !cConsumeToken(T_OPEN_CURVED_BRACKET)) {
|
|
|
return false;
|
|
|
}
|
|
|
+ cAddOperation(OP_GOTO);
|
|
|
+ int p = cReserveInt();
|
|
|
|
|
|
- if(!cAddOperation(OP_GOTO)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- void* p = cReserveBytes(sizeof(int));
|
|
|
-
|
|
|
- int functionIndex = writeIndex;
|
|
|
+ int functionIndex = code->length;
|
|
|
if(!simAdd(&functions, name, &functionIndex)) {
|
|
|
cError("function registered twice on line %d", line);
|
|
|
return false;
|
|
@@ -221,25 +233,24 @@ static bool cFunction() {
|
|
|
}
|
|
|
cLine();
|
|
|
}
|
|
|
-
|
|
|
- if(!cAddOperation(OP_RETURN)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- cSetBytes(&writeIndex, p, sizeof(int));
|
|
|
+ cAddOperation(OP_RETURN);
|
|
|
+ cSetInt(p, code->length);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static bool cPrint() {
|
|
|
- return cExpression() && cConsumeToken(T_SEMICOLON) && cAddOperation(OP_PRINT);
|
|
|
+ bool b = cExpression() && cConsumeToken(T_SEMICOLON);
|
|
|
+ cAddOperation(OP_PRINT);
|
|
|
+ return b;
|
|
|
}
|
|
|
|
|
|
static bool cLine() {
|
|
|
Token t = tReadTokenAndLine();
|
|
|
if(t == T_END) {
|
|
|
return false;
|
|
|
- } else if(!cAddOperation(OP_LINE) || !cAddBytes(&line, sizeof(line))) {
|
|
|
- return false;
|
|
|
}
|
|
|
+ cAddOperation(OP_LINE);
|
|
|
+ cAddInt16(line);
|
|
|
if(t == T_PRINT) {
|
|
|
return cPrint();
|
|
|
} else if(t == T_LITERAL) {
|
|
@@ -252,25 +263,17 @@ static bool cLine() {
|
|
|
}
|
|
|
|
|
|
static void cForEachLine() {
|
|
|
- writeIndex = 0;
|
|
|
varIndex = 0;
|
|
|
- if(!cAddOperation(OP_PUSH)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- void* globalVars = cReserveBytes(sizeof(int));
|
|
|
- if(globalVars == NULL) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ cAddOperation(OP_PUSH);
|
|
|
+ int globalVars = cReserveInt();
|
|
|
while(cLine()) {
|
|
|
}
|
|
|
- if(!cAddOperation(OP_POP)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- cSetBytes(&varIndex, globalVars, sizeof(int));
|
|
|
- cAddBytes(&varIndex, sizeof(int));
|
|
|
+ cAddOperation(OP_POP);
|
|
|
+ cSetInt(globalVars, varIndex);
|
|
|
+ cAddInt(varIndex);
|
|
|
}
|
|
|
|
|
|
-void cAllocAndCompile() {
|
|
|
+static void cAllocAndCompile() {
|
|
|
simInit(&vars);
|
|
|
simInit(&functions);
|
|
|
cForEachLine();
|
|
@@ -278,16 +281,15 @@ void cAllocAndCompile() {
|
|
|
simDelete(&vars);
|
|
|
}
|
|
|
|
|
|
-unsigned char* cCompile(int* codeLength) {
|
|
|
+ByteCode* cCompile() {
|
|
|
error[0] = '\0';
|
|
|
+ code = bcInit();
|
|
|
cAllocAndCompile();
|
|
|
if(error[0] != '\0') {
|
|
|
+ bcDelete(code);
|
|
|
return NULL;
|
|
|
}
|
|
|
- unsigned char* bytes = malloc(writeIndex);
|
|
|
- memcpy(bytes, byteCode, writeIndex);
|
|
|
- *codeLength = writeIndex;
|
|
|
- return bytes;
|
|
|
+ return code;
|
|
|
}
|
|
|
|
|
|
const char* cGetError() {
|