Ver código fonte

simplified error handling by using longjumps

Kajetan Johannes Hammerle 4 anos atrás
pai
commit
4b9ce848c5
1 arquivos alterados com 105 adições e 149 exclusões
  1. 105 149
      Compiler.c

+ 105 - 149
Compiler.c

@@ -1,3 +1,4 @@
+#include <setjmp.h>
 #include <stdarg.h>
 #include <stdio.h>
 
@@ -11,6 +12,7 @@
 #define ERROR_LENGTH 256
 #define VARS 256
 
+static jmp_buf errorJump;
 static char error[ERROR_LENGTH] = {'\0'};
 
 static ByteCode* code;
@@ -26,6 +28,7 @@ static void cError(const char* format, ...) {
     va_start(args, format);
     vsnprintf(error, ERROR_LENGTH, format, args);
     va_end(args);
+    longjmp(errorJump, 0);
 }
 
 static int cAddVar(const char* var) {
@@ -63,6 +66,19 @@ static void cAddFloat(float f) {
     bcAddBytes(code, &f, sizeof(float));
 }
 
+static int cAddPush(int offset) {
+    cAddOperation(OP_PUSH);
+    int p = cReserveInt();
+    cAddInt(offset);
+    return p;
+}
+
+static void cAddPop(int p, int vars) {
+    cAddOperation(OP_POP);
+    cAddInt(vars);
+    cSetInt(p, vars);
+}
+
 static Token cReadTokenAndLine() {
     Token t = tReadToken();
     if(tReadInt16(&line)) {
@@ -71,13 +87,11 @@ static Token cReadTokenAndLine() {
     return T_END;
 }
 
-static bool cConsumeToken(Token wanted) {
+static void cConsumeToken(Token wanted) {
     Token t = cReadTokenAndLine();
-    if(wanted == t) {
-        return true;
+    if(wanted != t) {
+        cError("unexpected token on line %d: expected '%s' got '%s'", line, tGetTokenName(wanted), tGetTokenName(t));
     }
-    cError("unexpected token on line %d: expected '%s' got '%s'", line, tGetTokenName(wanted), tGetTokenName(t));
-    return false;
 }
 
 static bool cConsumeTokenIf(Token t) {
@@ -88,259 +102,197 @@ static bool cConsumeTokenIf(Token t) {
     return false;
 }
 
-static bool cExpression();
-
-static bool cConstantInt() {
+static void cConstantInt() {
     int value;
-    if(tReadInt(&value)) {
-        cAddOperation(OP_PUSH_INT);
-        cAddInt(value);
-        return true;
+    if(!tReadInt(&value)) {
+        cError("int token without an int on line %d", line);
     }
-    return false;
+    cAddOperation(OP_PUSH_INT);
+    cAddInt(value);
 }
 
-static bool cConstantFloat() {
+static void cConstantFloat() {
     float value;
-    if(tReadFloat(&value)) {
-        cAddOperation(OP_PUSH_FLOAT);
-        cAddFloat(value);
-        return true;
+    if(!tReadFloat(&value)) {
+        cError("float token without a float on line %d", line);
     }
-    return false;
+    cAddOperation(OP_PUSH_FLOAT);
+    cAddFloat(value);
 }
 
-static bool cGetVar() {
+static const char* cReadString() {
     const char* literal = tReadString();
     if(literal == NULL) {
         cError("literal without string on line %d", line);
-        return false;
     }
+    return literal;
+}
+
+static void cGetVar() {
     cAddOperation(OP_GET);
-    cAddInt(cAddVar(literal));
-    return true;
+    cAddInt(cAddVar(cReadString()));
 }
 
-static bool cPrimary() {
+static void cExpression();
+
+static void cPrimary() {
     Token t = cReadTokenAndLine();
     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;
+        case T_INT: cConstantInt(); break;
+        case T_FLOAT: cConstantFloat(); break;
+        case T_NULL: cAddOperation(OP_PUSH_NULL); break;
+        case T_TRUE: cAddOperation(OP_PUSH_TRUE); break;
+        case T_FALSE: cAddOperation(OP_PUSH_FALSE); break;
+        case T_OPEN_BRACKET:
+            cExpression();
+            cConsumeToken(T_CLOSE_BRACKET);
+            break;
+        case T_LITERAL: cGetVar(); break;
+        default: cUnexpectedToken(t); break;
     }
 }
 
-static bool cMul() {
-    if(!cPrimary()) {
-        return false;
-    }
+static void cMul() {
+    cPrimary();
     while(cConsumeTokenIf(T_MUL)) {
-        if(!cPrimary()) {
-            return false;
-        }
+        cPrimary();
         cAddOperation(OP_MUL);
     }
-    return true;
 }
 
-static bool cAdd() {
-    if(!cMul()) {
-        return false;
-    }
+static void cAdd() {
+    cMul();
     while(cConsumeTokenIf(T_ADD)) {
-        if(!cMul()) {
-            return false;
-        }
+        cMul();
         cAddOperation(OP_ADD);
     }
-    return true;
 }
 
-static bool cExpression() {
-    return cAdd();
+static void cExpression() {
+    cAdd();
 }
 
-static bool cSetVar(const char* literal) {
-    bool b = cExpression() && cConsumeToken(T_SEMICOLON);
+static void cSetVar(const char* literal) {
+    cExpression();
+    cConsumeToken(T_SEMICOLON);
     cAddOperation(OP_SET);
     cAddInt(cAddVar(literal));
-    return b;
 }
 
 static int cCallFunctionArguments() {
     int arguments = 0;
     while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
         arguments++;
-        if(!cExpression()) {
-            return -1;
-        } else if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) {
+        cExpression();
+        if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) {
             cUnexpectedToken(tPeekToken());
-            return -1;
         }
     }
     return arguments;
 }
 
-static bool cCallFunction(const char* literal) {
+static void cCallFunction(const char* literal) {
     cAddOperation(OP_PUSH_INT);
     cAddInt(0);
     int arguments = cCallFunctionArguments();
-    if(arguments == -1) {
-        return false;
-    }
     int address = fmSearchAddress(&functions, literal, arguments);
     if(address == -1) {
         cError("unknown function on line %d", line);
-        return false;
     }
     cAddOperation(OP_GOSUB);
     cAddInt(address);
     cAddInt(arguments);
-    return cConsumeToken(T_SEMICOLON);
+    cConsumeToken(T_SEMICOLON);
 }
 
-static bool cLiteral() {
-    const char* literal = tReadString();
-    if(literal == NULL) {
-        cError("literal without string on line %d", line);
-        return false;
-    }
+static void cLiteral() {
+    const char* literal = cReadString();
     Token t = cReadTokenAndLine();
-    if(t == T_SET) {
-        return cSetVar(literal);
-    } else if(t == T_OPEN_BRACKET) {
-        return cCallFunction(literal);
+    switch(t) {
+        case T_SET: cSetVar(literal); break;
+        case T_OPEN_BRACKET: cCallFunction(literal); break;
+        default: cUnexpectedToken(t);
     }
-    cUnexpectedToken(t);
-    return false;
 }
 
 static int cFunctionArguments() {
     int arguments = 0;
     while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
-        if(!cConsumeToken(T_LITERAL)) {
-            return -1;
-        }
+        cConsumeToken(T_LITERAL);
         arguments++;
-        const char* arg = tReadString();
-        if(arg == NULL) {
-            cError("function argument literal without string on line %d", line);
-            return -1;
-        }
-        cAddVar(arg);
+        cAddVar(cReadString());
         if(cConsumeTokenIf(T_COMMA) && tPeekToken() != T_LITERAL) {
             cUnexpectedToken(tPeekToken());
-            return -1;
         }
     }
     return arguments;
 }
 
-static bool cLine();
-
-static bool cFunctionInnerBody(int arguments) {
-    cAddOperation(OP_PUSH);
-    int pushIndex = cReserveInt();
-    cAddInt(arguments);
+static void cLine(Token t);
 
+static void cFunctionInnerBody(int arguments) {
+    int p = cAddPush(arguments);
     int oldLine = line;
     while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
-        if(cConsumeTokenIf(T_END)) {
+        Token t = cReadTokenAndLine();
+        if(t == T_END) {
             cError("unexpected end of file: function not closed on line %d", oldLine);
-            return false;
-        } else if(!cLine()) {
-            return false;
         }
+        cLine(t);
     }
-
-    cAddOperation(OP_POP);
-    cAddInt(vars[1].entries);
-    cSetInt(pushIndex, vars[1].entries);
-    return true;
+    cAddPop(p, vars[1].entries);
 }
 
-static bool cFunctionBody(const char* name, int arguments) {
-    if(!cConsumeToken(T_OPEN_CURVED_BRACKET)) {
-        return false;
-    }
+static void cFunctionBody(const char* name, int arguments) {
+    cConsumeToken(T_OPEN_CURVED_BRACKET);
     cAddOperation(OP_GOTO);
     int gotoIndex = cReserveInt();
 
     if(!fmAdd(&functions, name, arguments, code->length)) {
         cError("function registered twice on line %d", line);
-        return false;
-    } else if(!cFunctionInnerBody(arguments)) {
-        return false;
     }
+    cFunctionInnerBody(arguments);
 
     cAddOperation(OP_RETURN);
     cSetInt(gotoIndex, code->length);
-    return true;
 }
 
-static bool cFunction() {
+static void cFunction() {
     if(varIndex == 1) {
         cError("function inside function on line %d", line);
-        return false;
-    } else if(!cConsumeToken(T_LITERAL)) {
-        return false;
     }
-    const char* name = tReadString();
-    if(name == NULL) {
-        cError("function literal without a function name on line %d", line);
-        return false;
-    } else if(!cConsumeToken(T_OPEN_BRACKET)) {
-        return false;
-    }
-
+    cConsumeToken(T_LITERAL);
+    const char* name = cReadString();
+    cConsumeToken(T_OPEN_BRACKET);
     varIndex = 1;
     vars[1].entries = 0;
-    int arguments = cFunctionArguments();
-    if(arguments == -1 || !cFunctionBody(name, arguments)) {
-        return false;
-    }
+    cFunctionBody(name, cFunctionArguments());
     varIndex = 0;
-    return true;
 }
 
-static bool cPrint() {
-    bool b = cExpression() && cConsumeToken(T_SEMICOLON);
+static void cPrint() {
+    cExpression();
+    cConsumeToken(T_SEMICOLON);
     cAddOperation(OP_PRINT);
-    return b;
 }
 
-static bool cLine() {
-    Token t = cReadTokenAndLine();
-    if(t == T_END) {
-        return false;
-    }
+static void cLine(Token t) {
     cAddOperation(OP_LINE);
     cAddInt16(line);
-    if(t == T_PRINT) {
-        return cPrint();
-    } else if(t == T_LITERAL) {
-        return cLiteral();
-    } else if(t == T_FUNCTION) {
-        return cFunction();
+    switch(t) {
+        case T_PRINT: cPrint(); break;
+        case T_LITERAL: cLiteral(); break;
+        case T_FUNCTION: cFunction(); break;
+        default: cUnexpectedToken(t);
     }
-    cUnexpectedToken(t);
-    return false;
 }
 
 static void cForEachLine() {
-    cAddOperation(OP_PUSH);
-    int globalVars = cReserveInt();
-    cAddInt(0);
-    while(cLine()) {
+    Token t = cReadTokenAndLine();
+    while(t != T_END) {
+        cLine(t);
+        t = cReadTokenAndLine();
     }
-    cAddOperation(OP_POP);
-    cSetInt(globalVars, vars[varIndex].entries);
-    cAddInt(vars[varIndex].entries);
 }
 
 static void cAllocAndCompile() {
@@ -348,7 +300,11 @@ static void cAllocAndCompile() {
     simInit(vars);
     simInit(vars + 1);
     fmInit(&functions);
-    cForEachLine();
+    if(!setjmp(errorJump)) {
+        int p = cAddPush(0);
+        cForEachLine();
+        cAddPop(p, vars[varIndex].entries);
+    }
     fmDelete(&functions);
     simDelete(vars + 1);
     simDelete(vars);