|
@@ -9,6 +9,7 @@
|
|
|
|
|
|
#define MAX_BYTES (1024 * 1024)
|
|
|
#define ERROR_LENGTH 256
|
|
|
+#define VARS 256
|
|
|
|
|
|
static char error[ERROR_LENGTH] = {'\0'};
|
|
|
|
|
@@ -16,6 +17,9 @@ static unsigned char byteCode[MAX_BYTES];
|
|
|
static int writeIndex = 0;
|
|
|
static int16 line = 1;
|
|
|
|
|
|
+static const char* vars[VARS];
|
|
|
+static int varIndex = 0;
|
|
|
+
|
|
|
static void cError(const char* format, ...) {
|
|
|
va_list args;
|
|
|
va_start(args, format);
|
|
@@ -23,17 +27,45 @@ static void cError(const char* format, ...) {
|
|
|
va_end(args);
|
|
|
}
|
|
|
|
|
|
+static int cAddVar(const char* var) {
|
|
|
+ for(int i = 0; i < varIndex; i++) {
|
|
|
+ if(strcmp(var, vars[i]) == 0) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(varIndex >= VARS) {
|
|
|
+ cError("variable buffer is too small");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ int index = varIndex;
|
|
|
+ vars[varIndex++] = var;
|
|
|
+ return index;
|
|
|
+}
|
|
|
+
|
|
|
static void cUnexpectedToken(Token t) {
|
|
|
cError("unexpected token on line %d: %s", line, tGetTokenName(t));
|
|
|
}
|
|
|
|
|
|
-static bool cAddBytes(const void* data, int length) {
|
|
|
+static void* cReserveBytes(int length) {
|
|
|
if(writeIndex + length > MAX_BYTES) {
|
|
|
cError("the compiler buffer is too small");
|
|
|
- return false;
|
|
|
+ return NULL;
|
|
|
}
|
|
|
- memcpy(byteCode + writeIndex, data, length);
|
|
|
+ unsigned char* p = byteCode + writeIndex;
|
|
|
writeIndex += length;
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+static void cSetBytes(const void* data, void* dest, int length) {
|
|
|
+ memcpy(dest, data, length);
|
|
|
+}
|
|
|
+
|
|
|
+static bool cAddBytes(const void* data, int length) {
|
|
|
+ void* p = cReserveBytes(length);
|
|
|
+ if(p == NULL) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ cSetBytes(data, p, length);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -84,6 +116,17 @@ static bool cPrimary() {
|
|
|
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);
|
|
|
+ if(varPointer == -1) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return cAddOperation(OP_GET) && cAddBytes(&varPointer, sizeof(int));
|
|
|
}
|
|
|
cUnexpectedToken(tPeekToken());
|
|
|
return false;
|
|
@@ -117,6 +160,24 @@ static bool cExpression() {
|
|
|
return cAdd();
|
|
|
}
|
|
|
|
|
|
+static bool cLiteral() {
|
|
|
+ const char* literal = tReadString();
|
|
|
+ if(literal == NULL) {
|
|
|
+ cError("literal without string on line %d", line);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ Token t = tReadTokenAndLine();
|
|
|
+ if(t != T_SET) {
|
|
|
+ cUnexpectedToken(t);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ int varPointer = cAddVar(literal);
|
|
|
+ if(varPointer == -1) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return cExpression() && cAddOperation(OP_SET) && cAddBytes(&varPointer, sizeof(int)) && cConsumeToken(T_SEMICOLON);
|
|
|
+}
|
|
|
+
|
|
|
static bool cPrint() {
|
|
|
return cExpression() && cConsumeToken(T_SEMICOLON) && cAddOperation(OP_PRINT);
|
|
|
}
|
|
@@ -130,16 +191,35 @@ static bool cLine() {
|
|
|
}
|
|
|
if(t == T_PRINT) {
|
|
|
return cPrint();
|
|
|
+ } else if(t == T_LITERAL) {
|
|
|
+ return cLiteral();
|
|
|
}
|
|
|
cUnexpectedToken(t);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-unsigned char* cCompile(int* codeLength) {
|
|
|
+static void cForEachLine() {
|
|
|
writeIndex = 0;
|
|
|
- error[0] = '\0';
|
|
|
+ varIndex = 0;
|
|
|
+ if(!cAddOperation(OP_PUSH)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ void* globalVars = cReserveBytes(sizeof(int));
|
|
|
+ if(globalVars == NULL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
while(cLine()) {
|
|
|
}
|
|
|
+ if(!cAddOperation(OP_POP)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ cSetBytes(&varIndex, globalVars, sizeof(int));
|
|
|
+ cAddBytes(&varIndex, sizeof(int));
|
|
|
+}
|
|
|
+
|
|
|
+unsigned char* cCompile(int* codeLength) {
|
|
|
+ error[0] = '\0';
|
|
|
+ cForEachLine();
|
|
|
if(error[0] != '\0') {
|
|
|
return NULL;
|
|
|
}
|