Kajetan Johannes Hammerle 3 gadi atpakaļ
vecāks
revīzija
f4cdb6bf01
9 mainītis faili ar 163 papildinājumiem un 105 dzēšanām
  1. 36 0
      ByteCode.c
  2. 19 0
      ByteCode.h
  3. 90 88
      Compiler.c
  4. 2 2
      Compiler.h
  5. 7 7
      Script.c
  6. 3 3
      Script.h
  7. 3 4
      Test.c
  8. 1 0
      Tokenizer.h
  9. 2 1
      meson.build

+ 36 - 0
ByteCode.c

@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ByteCode.h"
+
+ByteCode* bcInit() {
+    ByteCode* bc = malloc(sizeof(ByteCode));
+    bc->capacity = 16;
+    bc->length = 0;
+    bc->code = malloc(bc->capacity);
+    return bc;
+}
+
+void bcDelete(ByteCode* bc) {
+    free(bc->code);
+    free(bc);
+}
+
+int bcReserveBytes(ByteCode* bc, int length) {
+    while(bc->length + length > bc->capacity) {
+        bc->capacity *= 2;
+        bc->code = realloc(bc->code, bc->capacity);
+    }
+    int p = bc->length;
+    bc->length += length;
+    return p;
+}
+
+void bcSetBytes(ByteCode* bc, int p, const void* data, int length) {
+    memcpy(bc->code + p, data, length);
+}
+
+void bcAddBytes(ByteCode* bc, const void* data, int length) {
+    bcSetBytes(bc, bcReserveBytes(bc, length), data, length);
+}

+ 19 - 0
ByteCode.h

@@ -0,0 +1,19 @@
+#ifndef BYTECODE_H
+#define BYTECODE_H
+
+#include "Operation.h"
+
+typedef struct ByteCode {
+    int capacity;
+    int length;
+    unsigned char* code;
+} ByteCode;
+
+ByteCode* bcInit();
+void bcDelete(ByteCode* bc);
+
+int bcReserveBytes(ByteCode* bc, int length);
+void bcSetBytes(ByteCode* bc, int p, const void* data, int length);
+void bcAddBytes(ByteCode* bc, const void* data, int length);
+
+#endif

+ 90 - 88
Compiler.c

@@ -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() {

+ 2 - 2
Compiler.h

@@ -1,9 +1,9 @@
 #ifndef COMPILER_H
 #define COMPILER_H
 
-#include <stdbool.h>
+#include "ByteCode.h"
 
-unsigned char* cCompile(int* codeLength);
+ByteCode* cCompile();
 const char* cGetError();
 
 #endif

+ 7 - 7
Script.c

@@ -25,11 +25,11 @@ static bool sPrinter(Object* o) {
 static ObjectPrinter printer = sPrinter;
 
 static bool sRead(Script* sc, void* buffer, int length) {
-    if(sc->readIndex + length > sc->byteCodeLength) {
+    if(sc->readIndex + length > sc->code->length) {
         sError(sc, "cannot read expected %d bytes of data from bytecode on line %d", sc->line);
         return true;
     }
-    memcpy(buffer, sc->byteCode + sc->readIndex, length);
+    memcpy(buffer, sc->code->code + sc->readIndex, length);
     sc->readIndex += length;
     return false;
 }
@@ -238,14 +238,13 @@ static void sConsumeInstruction(Script* sc) {
 }
 
 static bool sHasData(Script* sc) {
-    return sc->readIndex < sc->byteCodeLength;
+    return sc->readIndex < sc->code->length;
 }
 
-Script* sInit(unsigned char* byteCode, int codeLength) {
+Script* sInit(ByteCode* code) {
     Script* sc = malloc(sizeof(Script));
     sc->error[0] = '\0';
-    sc->byteCode = byteCode;
-    sc->byteCodeLength = codeLength;
+    sc->code = code;
     sc->readIndex = 0;
     sc->stackIndex = 0;
     sc->line = 0;
@@ -253,7 +252,8 @@ Script* sInit(unsigned char* byteCode, int codeLength) {
 }
 
 void sDelete(Script* sc) {
-    free(sc->byteCode);
+    bcDelete(sc->code);
+    free(sc);
 }
 
 void sRun(Script* sc) {

+ 3 - 3
Script.h

@@ -3,6 +3,7 @@
 
 #include <stdbool.h>
 
+#include "ByteCode.h"
 #include "Object.h"
 
 #define SCRIPT_STACK_SIZE 50
@@ -10,15 +11,14 @@
 
 typedef struct Script {
     char error[SCRIPT_ERROR_SIZE];
-    unsigned char* byteCode;
-    int byteCodeLength;
+    ByteCode* code;
     int readIndex;
     Object stack[SCRIPT_STACK_SIZE];
     int stackIndex;
     int line;
 } Script;
 
-Script* sInit(unsigned char* byteCode, int codeLength);
+Script* sInit(ByteCode* code);
 void sDelete(Script* sc);
 
 void sRun(Script* sc);

+ 3 - 4
Test.c

@@ -99,14 +99,13 @@ static void tsCheckFile() {
         puts(tGetError());
         return;
     }
-    int codeLength;
-    unsigned char* code = cCompile(&codeLength);
-    if(code == NULL) {
+    ByteCode* bc = cCompile();
+    if(bc == NULL) {
         puts(path);
         puts(cGetError());
         return;
     }
-    Script* sc = sInit(code, codeLength);
+    Script* sc = sInit(bc);
     tsCheckScript(sc);
     sDelete(sc);
 }

+ 1 - 0
Tokenizer.h

@@ -2,6 +2,7 @@
 #define TOKENIZER_H
 
 #include <stdbool.h>
+#include <stdint.h>
 
 typedef enum Token {
     T_INT,

+ 2 - 1
meson.build

@@ -7,7 +7,8 @@ src = [
     'Utils.c', 
     'Script.c', 
     'Test.c', 
-    'StringIntMap.c'
+    'StringIntMap.c',
+    'ByteCode.c'
 ]
 
 executable('lonely_tiger',