Browse Source

Refactoring

Kajetan Johannes Hammerle 6 days ago
parent
commit
1a24286cde
2 changed files with 148 additions and 201 deletions
  1. 112 141
      src/Compiler.c
  2. 36 60
      src/Tokenizer.c

+ 112 - 141
src/Compiler.c

@@ -78,6 +78,13 @@ static size_t codeGetWritePosition(const Context* c) {
     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) {
     size_t oldPos = codeGetWritePosition(c);
     c->code->code.writeIndex = pos;
@@ -182,33 +189,24 @@ static void addReturn(Context* c, i32 address, bool hasArgument) {
     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) {
-    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) {
-    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);
 }
 
@@ -226,8 +224,20 @@ static Token consumeToken(Context* c, TokenType type) {
     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) {
-    if(tokenizerPeek(c->tokenizer).type == TT_INVALID) {
+    if(peekToken(c, TT_INVALID)) {
         return;
     }
     consumeToken(c, TT_NEWLINE);
@@ -236,8 +246,7 @@ static void consumeNewline(Context* c) {
 
 static void compileReadVariable(Context* c, Token token, bool 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);
@@ -248,10 +257,9 @@ static void compileConstant(Context* c) {
         codePushInstruction(c, PUSH_CONSTANT_STRING);
         codePushConstantString(c, token.stringValue);
     } 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) {
-        if(tokenizerPeek(c->tokenizer).type == TT_OPEN_ROUND_BRACKET) {
+        if(peekToken(c, TT_OPEN_ROUND_BRACKET)) {
             compileCallFunction(c, token);
         } else {
             compileReadVariable(c, token, false);
@@ -265,8 +273,7 @@ static void compileConstant(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);
         codePushInstruction(c, NOT);
     } else {
@@ -277,13 +284,10 @@ static void compileUnary(Context* c) {
 static void compileMul(Context* c) {
     compileUnary(c);
     while(true) {
-        Token t = tokenizerPeek(c->tokenizer);
-        if(t.type == TT_MULTIPLY) {
-            tokenizerNext(c->tokenizer);
+        if(consumeTokenIf(c, TT_MULTIPLY)) {
             compileUnary(c);
             codePushInstruction(c, MUL);
-        } else if(t.type == TT_DIVIDE) {
-            tokenizerNext(c->tokenizer);
+        } else if(consumeTokenIf(c, TT_DIVIDE)) {
             compileUnary(c);
             codePushInstruction(c, DIV);
         } else {
@@ -295,13 +299,10 @@ static void compileMul(Context* c) {
 static void compileAdd(Context* c) {
     compileMul(c);
     while(true) {
-        Token t = tokenizerPeek(c->tokenizer);
-        if(t.type == TT_ADD) {
-            tokenizerNext(c->tokenizer);
+        if(consumeTokenIf(c, TT_ADD)) {
             compileMul(c);
             codePushInstruction(c, ADD);
-        } else if(t.type == TT_SUBTRACT) {
-            tokenizerNext(c->tokenizer);
+        } else if(consumeTokenIf(c, TT_SUBTRACT)) {
             compileMul(c);
             codePushInstruction(c, SUB);
         } else {
@@ -313,29 +314,22 @@ static void compileAdd(Context* c) {
 static void compileCompare(Context* c) {
     compileAdd(c);
     while(true) {
-        Token t = tokenizerPeek(c->tokenizer);
-        if(t.type == TT_EQUAL) {
-            tokenizerNext(c->tokenizer);
+        if(consumeTokenIf(c, TT_EQUAL)) {
             compileAdd(c);
             codePushInstruction(c, EQUAL);
-        } else if(t.type == TT_NOT_EQUAL) {
-            tokenizerNext(c->tokenizer);
+        } else if(consumeTokenIf(c, TT_NOT_EQUAL)) {
             compileAdd(c);
             codePushInstruction(c, NOT_EQUAL);
-        } else if(t.type == TT_GREATER) {
-            tokenizerNext(c->tokenizer);
+        } else if(consumeTokenIf(c, TT_GREATER)) {
             compileAdd(c);
             codePushInstruction(c, GREATER);
-        } else if(t.type == TT_SMALLER) {
-            tokenizerNext(c->tokenizer);
+        } else if(consumeTokenIf(c, TT_SMALLER)) {
             compileAdd(c);
             codePushInstruction(c, SMALLER);
-        } else if(t.type == TT_GREATER_OR_EQUAL) {
-            tokenizerNext(c->tokenizer);
+        } else if(consumeTokenIf(c, TT_GREATER_OR_EQUAL)) {
             compileAdd(c);
             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);
             codePushInstruction(c, SMALLER_OR_EQUAL);
         } else {
@@ -347,13 +341,10 @@ static void compileCompare(Context* c) {
 static void compileLogical(Context* c) {
     compileCompare(c);
     while(true) {
-        Token t = tokenizerPeek(c->tokenizer);
-        if(t.type == TT_AND) {
-            tokenizerNext(c->tokenizer);
+        if(consumeTokenIf(c, TT_AND)) {
             compileCompare(c);
             codePushInstruction(c, AND);
-        } else if(t.type == TT_OR) {
-            tokenizerNext(c->tokenizer);
+        } else if(consumeTokenIf(c, TT_OR)) {
             compileCompare(c);
             codePushInstruction(c, OR);
         } else {
@@ -370,11 +361,9 @@ static void compileLine(Context* c, Token token);
 
 static void compileIf(Context* 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);
-    while(tokenizerPeek(c->tokenizer).type != TT_END) {
+    while(!peekToken(c, TT_END)) {
         compileLine(c, tokenizerNext(c->tokenizer));
     }
     consumeToken(c, TT_END);
@@ -385,9 +374,29 @@ static void compileIf(Context* c) {
 static void compileSetVariable(Context* c, const char* name, bool forceGlobal) {
     consumeToken(c, TT_ASSIGN);
     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) {
@@ -395,50 +404,22 @@ static void compileFunction(Context* c) {
         THROW_ERROR("Functions in functions are not allowed");
     }
     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);
     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;
-    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);
-    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));
     }
     consumeToken(c, TT_END);
     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);
 
     while(c->variables != resetVar) {
@@ -447,28 +428,23 @@ static void compileFunction(Context* c) {
         c->variables = next;
     }
 
-    codeRewriteI32(c, pos, (i32)codeGetWritePosition(c));
+    codeRewriteI32(c, functionEnd, (i32)codeGetWritePosition(c));
     c->inFunction = false;
 }
 
 static void compileCallFunction(Context* c, Token t) {
     // 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);
     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++;
         compileExpression(c);
-        if(tokenizerPeek(c->tokenizer).type == TT_COMMA) {
-            consumeToken(c, TT_COMMA);
-        }
     }
     consumeToken(c, TT_CLOSE_ROUND_BRACKET);
 
@@ -479,61 +455,56 @@ static void compileCallFunction(Context* c, Token t) {
 }
 
 static void compileReturn(Context* c) {
-    if(tokenizerPeek(c->tokenizer).type == TT_NEWLINE) {
+    if(peekToken(c, TT_NEWLINE)) {
         consumeNewline(c);
-        codePushInstruction(c, PUSH_INT32);
-        codePushI32(c, 0);
+        codePushInstructionI32(c, PUSH_INT32, 0);
     } else {
         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);
 }
 
+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) {
     if(token.type == TT_NEWLINE) {
         c->line++;
-        return;
     } else if(token.type == TT_IF) {
         compileIf(c);
-        return;
     } else if(token.type == TT_FUNCTION) {
         compileFunction(c);
-        return;
     } else if(token.type == TT_RETURN) {
         compileReturn(c);
-        return;
     } else if(token.type == TT_DOLLAR) {
         token = consumeToken(c, TT_LITERAL);
         compileSetVariable(c, token.stringValue, true);
-        return;
     } else if(token.type != TT_LITERAL) {
         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 {
-        THROW_ERROR("Unexpected literal(%s)", s);
+        compileLineLiteral(c, token);
     }
 }
 
 static void parseTokens(Context* c) {
     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) {
         Token token = tokenizerNext(c->tokenizer);

+ 36 - 60
src/Tokenizer.c

@@ -132,6 +132,22 @@ static const char* tokenizerAddString(TState* t, const char* s) {
     return s;
 }
 
+#define SIMPLE_TOKEN(ch, token) \
+    else if(c == ch) {          \
+        tAddToken(t, token);    \
+        s++;                    \
+    }
+#define SIMPLE_TOKEN2(ch, ch2, token, token2) \
+    else if(c == ch) {                        \
+        s++;                                  \
+        if(*s == ch2) {                       \
+            s++;                              \
+            tAddToken(t, token2);             \
+        } else {                              \
+            tAddToken(t, token);              \
+        }                                     \
+    }
+
 static void tParseLineString(TState* t, const char* s) {
     while(true) {
         char c = *s;
@@ -146,71 +162,31 @@ static void tParseLineString(TState* t, const char* s) {
             break;
         } else if(c == ' ') {
             s++;
-        } else if(c == ',') {
-            tAddToken(t, TT_COMMA);
-            s++;
-        } else if(c == '$') {
-            tAddToken(t, TT_DOLLAR);
-            s++;
-        } else if(c == '+') {
-            tAddToken(t, TT_ADD);
-            s++;
-        } else if(c == '-') {
-            tAddToken(t, TT_SUBTRACT);
-            s++;
-        } else if(c == '*') {
-            tAddToken(t, TT_MULTIPLY);
-            s++;
-        } else if(c == '/') {
-            tAddToken(t, TT_DIVIDE);
-            s++;
-        } else if(c == '=') {
-            s++;
-            if(*s == '=') {
-                s++;
-                tAddToken(t, TT_EQUAL);
-            } else {
-                tAddToken(t, TT_ASSIGN);
-            }
-        } else if(c == '!') {
-            s++;
-            if(*s == '=') {
-                s++;
-                tAddToken(t, TT_NOT_EQUAL);
-            } else {
-                tAddToken(t, TT_NOT);
-            }
-        } else if(c == '>') {
-            s++;
-            if(*s == '=') {
-                s++;
-                tAddToken(t, TT_GREATER_OR_EQUAL);
-            } else {
-                tAddToken(t, TT_GREATER);
-            }
-        } else if(c == '<') {
-            s++;
-            if(*s == '=') {
-                s++;
-                tAddToken(t, TT_SMALLER_OR_EQUAL);
-            } else {
-                tAddToken(t, TT_SMALLER);
-            }
-        } else if(c == '(') {
-            tAddToken(t, TT_OPEN_ROUND_BRACKET);
-            s++;
-        } else if(c == ')') {
-            tAddToken(t, TT_CLOSE_ROUND_BRACKET);
-            s++;
-        } else if(c == '&' && s[1] == '&') {
+        }
+        SIMPLE_TOKEN(',', TT_COMMA)
+        SIMPLE_TOKEN('$', TT_DOLLAR)
+        SIMPLE_TOKEN('+', TT_ADD)
+        SIMPLE_TOKEN('-', TT_SUBTRACT)
+        SIMPLE_TOKEN('*', TT_MULTIPLY)
+        SIMPLE_TOKEN('/', TT_DIVIDE)
+        SIMPLE_TOKEN2('=', '=', TT_ASSIGN, TT_EQUAL)
+        SIMPLE_TOKEN2('!', '=', TT_NOT, TT_NOT_EQUAL)
+        SIMPLE_TOKEN2('>', '=', TT_GREATER, TT_GREATER_OR_EQUAL)
+        SIMPLE_TOKEN2('<', '=', TT_SMALLER, TT_SMALLER_OR_EQUAL)
+        SIMPLE_TOKEN('(', TT_OPEN_ROUND_BRACKET)
+        SIMPLE_TOKEN(')', TT_CLOSE_ROUND_BRACKET)
+        else if(c == '&' && s[1] == '&') {
             s += 2;
             tAddToken(t, TT_AND);
-        } else if(c == '|' && s[1] == '|') {
+        }
+        else if(c == '|' && s[1] == '|') {
             s += 2;
             tAddToken(t, TT_OR);
-        } else if(c == '\0') {
+        }
+        else if(c == '\0') {
             break;
-        } else {
+        }
+        else {
             tInvalidToken(t, c);
         }
     }