Kajetan Johannes Hammerle 2 недель назад
Родитель
Сommit
7de6c8a93f
10 измененных файлов с 226 добавлено и 194 удалено
  1. 15 0
      src/Buffer.c
  2. 3 0
      src/Buffer.h
  3. 34 69
      src/Code.c
  4. 27 21
      src/Code.h
  5. 20 13
      src/CodeRunner.c
  6. 80 69
      src/Compiler.c
  7. 2 1
      src/Compiler.h
  8. 10 4
      src/Main.c
  9. 8 8
      src/Memory.c
  10. 27 9
      src/Tokenizer.c

+ 15 - 0
src/Buffer.c

@@ -64,6 +64,21 @@ BUFFER_READ_WRITE_IMPL(U16, u16)
 BUFFER_READ_WRITE_IMPL(U32, u32)
 BUFFER_READ_WRITE_IMPL(U64, u64)
 
+bool bufferWriteString(Buffer* b, const char* s) {
+    size_t l = strlen(s) + 1;
+    return bufferWrite(b, &l, sizeof(l)) || bufferWrite(b, s, l);
+}
+
+const char* bufferReadString(Buffer* b) {
+    size_t l = 0;
+    if(bufferRead(b, &l, sizeof(l)) || b->readIndex + l > b->writeIndex) {
+        return nullptr;
+    }
+    const char* s = (char*)(b->data + b->readIndex);
+    b->readIndex += l;
+    return s;
+}
+
 bool bufferIsEmpty(const Buffer* b) {
     return b->readIndex >= b->writeIndex;
 }

+ 3 - 0
src/Buffer.h

@@ -29,6 +29,9 @@ BUFFER_READ_WRITE(U16, u16);
 BUFFER_READ_WRITE(U32, u32);
 BUFFER_READ_WRITE(U64, u64);
 
+[[nodiscard]] bool bufferWriteString(Buffer* b, const char* s);
+const char* bufferReadString(Buffer* b);
+
 bool bufferIsEmpty(const Buffer* b);
 
 size_t bufferGetReadIndex(const Buffer* b);

+ 34 - 69
src/Code.c

@@ -1,100 +1,65 @@
 #include "Code.h"
 
-#include <assert.h>
-#include <string.h>
-
-#include "Constants.h"
-
-static u8 code[MAX_CODE];
-static size_t codeIndex = 0;
-static size_t codeExecutionIndex = 0;
-
-void codeReset() {
-    codeIndex = 0;
-    codeExecutionIndex = 0;
-}
-
-static bool codePushU8(u8 u) {
-    if(codeIndex >= MAX_CODE) {
-        return true;
-    }
-    code[codeIndex++] = u;
-    return false;
+void codeInit(Code* c) {
+    *c = (Code){};
+    bufferInit(&c->code);
 }
 
-static bool codePush(const void* p, size_t n) {
-    if(codeIndex + n >= MAX_CODE) {
-        return true;
-    }
-    memcpy(code + codeIndex, p, n);
-    codeIndex += n;
-    return false;
+void codeDestroy(Code* c) {
+    bufferDestroy(&c->code);
+    *c = (Code){};
 }
 
-bool codePushInstruction(Instruction i) {
-    return codePushU8(i);
+void codeReset(Code* c) {
+    bufferReset(&c->code);
 }
 
-bool codePushI64(i64 i) {
-    return codePush(&i, sizeof(i));
+bool codePushInstruction(Code* c, Instruction i) {
+    return bufferWriteU8(&c->code, i);
 }
 
-bool codePushSize(size_t i) {
-    return codePush(&i, sizeof(i));
+bool codePushI64(Code* c, i64 i) {
+    return bufferWriteI64(&c->code, i);
 }
 
-bool codePushConstantString(const char* c) {
-    size_t n = strlen(c) + 1;
-    return codePushSize(n) || codePush(c, n);
+bool codePushSize(Code* c, size_t i) {
+    return bufferWrite(&c->code, &i, sizeof(i));
 }
 
-Instruction codeReadInstruction() {
-    return codeExecutionIndex < codeIndex ? code[codeExecutionIndex++] : STOP;
+bool codePushConstantString(Code* c, const char* s) {
+    return bufferWriteString(&c->code, s);
 }
 
-static void codeRead(void* p, size_t n) {
-    if(codeExecutionIndex + n <= codeIndex) {
-        memcpy(p, code + codeExecutionIndex, n);
-        codeExecutionIndex += n;
-    }
+Instruction codeReadInstruction(Code* c) {
+    Instruction i = STOP;
+    (void)bufferReadU8(&c->code, &i);
+    return i;
 }
 
-i64 codeReadI64() {
-    i64 i = 0;
-    codeRead(&i, sizeof(i));
-    return i;
+bool codeReadI64(Code* c, i64* i) {
+    return bufferReadI64(&c->code, i);
 }
 
-size_t codeReadSize() {
-    size_t i = 0;
-    codeRead(&i, sizeof(i));
-    return i;
+bool codeReadSize(Code* c, size_t* s) {
+    return bufferRead(&c->code, s, sizeof(size_t));
 }
 
-const char* codeReadConstantString() {
-    size_t n = codeReadSize();
-    if(codeExecutionIndex + n <= codeIndex &&
-       code[codeExecutionIndex + n - 1] == '\0') {
-        const char* s = (char*)(code + codeExecutionIndex);
-        codeExecutionIndex += n;
-        return s;
-    }
-    return "";
+const char* codeReadConstantString(Code* c) {
+    return bufferReadString(&c->code);
 }
 
-size_t codeGetWritePosition() {
-    return codeIndex;
+size_t codeGetWritePosition(const Code* c) {
+    return bufferGetWriteIndex(&c->code);
 }
 
-void codeSetWritePosition(size_t pos) {
-    codeIndex = pos;
+void codeSetWritePosition(Code* c, size_t pos) {
+    bufferSetWriteIndex(&c->code, pos);
 }
 
-size_t codeGetPosition() {
-    return codeExecutionIndex;
+size_t codeGetPosition(const Code* c) {
+    return bufferGetReadIndex(&c->code);
 }
 
-void codeSetPosition(size_t pos) {
-    assert(pos < codeIndex);
-    codeExecutionIndex = pos;
+void codeSetPosition(Code* c, size_t pos) {
+    bufferSetReadIndex(&c->code, pos);
 }

+ 27 - 21
src/Code.h

@@ -2,6 +2,7 @@
 #define BASIC_CODE_H
 
 #include "Buffer.h"
+#include "Error.h"
 #include "Types.h"
 
 typedef enum : u8 {
@@ -14,26 +15,31 @@ typedef enum : u8 {
     STOP
 } Instruction;
 
-// typedef struct {
-//     Buffer code;
-// } Code;
-
-void codeReset();
-void codeRun();
-
-[[nodiscard]] bool codePushInstruction(Instruction i);
-[[nodiscard]] bool codePushI64(i64 i);
-[[nodiscard]] bool codePushSize(size_t i);
-[[nodiscard]] bool codePushConstantString(const char* c);
-
-Instruction codeReadInstruction();
-i64 codeReadI64();
-size_t codeReadSize();
-const char* codeReadConstantString();
-
-size_t codeGetWritePosition();
-void codeSetWritePosition(size_t pos);
-size_t codeGetPosition();
-void codeSetPosition(size_t pos);
+typedef struct {
+    Buffer code;
+    Error error;
+} Code;
+
+void codeInit(Code* code);
+void codeDestroy(Code* code);
+void codeReset(Code* code);
+
+void codeRun(Code* code);
+bool codeHasRunError(const Code* code);
+const char* codeGetRunError(const Code* code);
+
+[[nodiscard]] bool codePushInstruction(Code* code, Instruction i);
+[[nodiscard]] bool codePushI64(Code* code, i64 i);
+[[nodiscard]] bool codePushSize(Code* code, size_t i);
+[[nodiscard]] bool codePushConstantString(Code* code, const char* c);
+size_t codeGetWritePosition(const Code* code);
+void codeSetWritePosition(Code* code, size_t pos);
+
+[[nodiscard]] Instruction codeReadInstruction(Code* code);
+[[nodiscard]] bool codeReadI64(Code* code, i64* i);
+[[nodiscard]] bool codeReadSize(Code* code, size_t* s);
+[[nodiscard]] const char* codeReadConstantString(Code* code);
+size_t codeGetPosition(const Code* code);
+void codeSetPosition(Code* code, size_t pos);
 
 #endif

+ 20 - 13
src/CodeRunner.c

@@ -14,12 +14,16 @@ static bool iAdd() {
     return pushValue(INT_VALUE(a.intValue + b.intValue));
 }
 
-static bool iPushConstantString() {
-    return pushValue(CSTRING_VALUE(codeReadConstantString()));
+static bool iPushConstantString(Code* c) {
+    return pushValue(CSTRING_VALUE(codeReadConstantString(c)));
 }
 
-static bool iPushInt() {
-    return pushValue(INT_VALUE(codeReadI64()));
+static bool iPushInt(Code* c) {
+    i64 i = 0;
+    if(codeReadI64(c, &i)) {
+        return true;
+    }
+    return pushValue(INT_VALUE(i));
 }
 
 static bool iPrint() {
@@ -36,28 +40,31 @@ static bool iPrintNewline() {
     return false;
 }
 
-static bool iJumpIf() {
+static bool iJumpIf(Code* c) {
     POP_VALUE(a);
-    size_t jumpPos = codeReadSize();
+    size_t jumpPos = 0;
+    if(codeReadSize(c, &jumpPos)) {
+        return true;
+    }
     if(a.intValue == 0) {
-        codeSetPosition(jumpPos);
+        codeSetPosition(c, jumpPos);
     }
     return false;
 }
 
-static bool execute(Instruction command) {
+static bool execute(Code* c, Instruction command) {
     switch(command) {
         case ADD: return iAdd();
-        case PUSH_CONSTANT_STRING: return iPushConstantString();
-        case PUSH_INT64: return iPushInt();
+        case PUSH_CONSTANT_STRING: return iPushConstantString(c);
+        case PUSH_INT64: return iPushInt(c);
         case PRINT: return iPrint();
         case PRINT_NEWLINE: return iPrintNewline();
-        case JUMP_ON_0: return iJumpIf();
+        case JUMP_ON_0: return iJumpIf(c);
         case STOP: return true;
     }
     return false;
 }
 
-void codeRun() {
-    while(!execute(codeReadInstruction())) {}
+void codeRun(Code* c) {
+    while(!execute(c, codeReadInstruction(c))) {}
 }

+ 80 - 69
src/Compiler.c

@@ -7,132 +7,143 @@
 
 #include "Code.h"
 
-static Error error = {};
-static int line = 0;
-static jmp_buf jumpPosition = {};
-
-#define THROW_ERROR(format, ...)                             \
-    snprintf(                                                \
-        error.text, sizeof(error.text), "Line %d | " format, \
-        line __VA_OPT__(, ) __VA_ARGS__);                    \
-    longjmp(jumpPosition, 1)
-
-#define CODE(command)                     \
-    do {                                  \
-        if(command) {                     \
-            THROW_ERROR("Code overflow"); \
-        }                                 \
+typedef struct {
+    Tokenizer* tokenizer;
+    Code* code;
+    Error error;
+    int line;
+    jmp_buf jump;
+} Context;
+
+#define THROW_ERROR(format, ...)                                   \
+    snprintf(                                                      \
+        c->error.text, sizeof(c->error.text), "Line %d | " format, \
+        c->line __VA_OPT__(, ) __VA_ARGS__);                       \
+    longjmp(c->jump, 1)
+
+#define CODE(command)                                \
+    do {                                             \
+        if(command) {                                \
+            THROW_ERROR("Too less memory for code"); \
+        }                                            \
     } while(false)
 
-[[noreturn]] static void unexpectedToken(Token token) {
+[[noreturn]] static void unexpectedToken(Context* c, Token token) {
     char buffer[128];
     tokenizerPrintToken(&token, buffer, sizeof(buffer));
     THROW_ERROR("Unexpected %s token", buffer);
 }
 
-static Token consumeToken(Tokenizer* t, TokenType type) {
-    Token actual = tokenizerNext(t);
+static Token consumeToken(Context* c, TokenType type) {
+    Token actual = tokenizerNext(c->tokenizer);
     if(actual.type != type) {
-        unexpectedToken(actual);
+        unexpectedToken(c, actual);
     }
     return actual;
 }
 
-static void consumeLiteral(Tokenizer* t, const char* name) {
-    Token token = consumeToken(t, LITERAL);
+static Token consumeNewline(Context* c) {
+    Token t = consumeToken(c, NEWLINE);
+    c->line++;
+    return t;
+}
+
+static void consumeLiteral(Context* c, const char* name) {
+    Token token = consumeToken(c, LITERAL);
     const char* actual = token.stringValue;
     if(strcmp(actual, name) != 0) {
         THROW_ERROR("Unexpected literal(%s)", actual);
     }
 }
 
-static void compileConstant(Tokenizer* t) {
-    Token token = tokenizerNext(t);
+static void compileConstant(Context* c) {
+    Token token = tokenizerNext(c->tokenizer);
     if(token.type == STRING) {
-        CODE(codePushInstruction(PUSH_CONSTANT_STRING));
-        CODE(codePushConstantString(token.stringValue));
+        CODE(codePushInstruction(c->code, PUSH_CONSTANT_STRING));
+        CODE(codePushConstantString(c->code, token.stringValue));
     } else if(token.type == INT64) {
-        CODE(codePushInstruction(PUSH_INT64));
-        CODE(codePushI64(token.intValue));
+        CODE(codePushInstruction(c->code, PUSH_INT64));
+        CODE(codePushI64(c->code, token.intValue));
     } else {
-        unexpectedToken(token);
+        unexpectedToken(c, token);
     }
 }
 
-static void compileAdd(Tokenizer* t) {
-    compileConstant(t);
-    while(tokenizerPeek(t).type == PLUS) {
-        tokenizerNext(t);
-        compileConstant(t);
-        CODE(codePushInstruction(ADD));
+static void compileAdd(Context* c) {
+    compileConstant(c);
+    while(tokenizerPeek(c->tokenizer).type == PLUS) {
+        tokenizerNext(c->tokenizer);
+        compileConstant(c);
+        CODE(codePushInstruction(c->code, ADD));
     }
 }
 
-static void compileExpression(Tokenizer* t) {
-    compileAdd(t);
+static void compileExpression(Context* c) {
+    compileAdd(c);
 }
 
-static void compileLine(Tokenizer* t, Token token);
+static void compileLine(Context* c, Token token);
 
-static void compileIf(Tokenizer* t) {
-    compileExpression(t);
-    CODE(codePushInstruction(JUMP_ON_0));
-    size_t posIndex = codeGetWritePosition();
-    CODE(codePushSize(0));
-    consumeLiteral(t, "then");
-    consumeToken(t, NEWLINE);
+static void compileIf(Context* c) {
+    compileExpression(c);
+    CODE(codePushInstruction(c->code, JUMP_ON_0));
+    size_t posIndex = codeGetWritePosition(c->code);
+    CODE(codePushSize(c->code, 0));
+    consumeLiteral(c, "then");
+    consumeNewline(c);
     while(true) {
-        Token token = tokenizerPeek(t);
+        Token token = tokenizerPeek(c->tokenizer);
         if(token.type == LITERAL && strcmp(token.stringValue, "endif") == 0) {
             break;
         }
-        compileLine(t, tokenizerNext(t));
+        compileLine(c, tokenizerNext(c->tokenizer));
     }
-    consumeLiteral(t, "endif");
-    consumeToken(t, NEWLINE);
-    size_t endIndex = codeGetWritePosition();
-    codeSetWritePosition(posIndex);
-    CODE(codePushSize(endIndex));
-    codeSetWritePosition(endIndex);
+    consumeLiteral(c, "endif");
+    consumeNewline(c);
+    size_t endIndex = codeGetWritePosition(c->code);
+    codeSetWritePosition(c->code, posIndex);
+    CODE(codePushSize(c->code, endIndex));
+    codeSetWritePosition(c->code, endIndex);
 }
 
-static void compileLine(Tokenizer* t, Token token) {
+static void compileLine(Context* c, Token token) {
     if(token.type == NEWLINE) {
+        c->line++;
         return;
     }
     if(token.type != LITERAL) {
-        unexpectedToken(token);
+        unexpectedToken(c, token);
     }
     const char* s = token.stringValue;
     if(strcmp(s, "print") == 0) {
-        while(tokenizerPeek(t).type != NEWLINE) {
-            compileExpression(t);
-            CODE(codePushInstruction(PRINT));
+        while(tokenizerPeek(c->tokenizer).type != NEWLINE) {
+            compileExpression(c);
+            CODE(codePushInstruction(c->code, PRINT));
         }
-        tokenizerNext(t);
-        CODE(codePushInstruction(PRINT_NEWLINE));
+        consumeNewline(c);
+        CODE(codePushInstruction(c->code, PRINT_NEWLINE));
     } else if(strcmp(s, "if") == 0) {
-        compileIf(t);
+        compileIf(c);
     } else {
         THROW_ERROR("Unexpected literal(%s)", s);
     }
 }
 
-static void parseTokens(Tokenizer* t) {
-    codeReset();
+static void parseTokens(Context* c) {
+    codeReset(c->code);
     while(true) {
-        Token token = tokenizerNext(t);
+        Token token = tokenizerNext(c->tokenizer);
         if(token.type == END) {
             break;
         }
-        compileLine(t, token);
+        compileLine(c, token);
     }
 }
 
-Error compileFile(Tokenizer* t) {
-    error.text[0] = '\0';
-    if(!setjmp(jumpPosition)) {
-        parseTokens(t);
+Error compileFile(Tokenizer* t, Code* code) {
+    Context c = {.tokenizer = t, .code = code, .line = 1};
+    if(!setjmp(c.jump)) {
+        parseTokens(&c);
     }
-    return error;
+    return c.error;
 }

+ 2 - 1
src/Compiler.h

@@ -1,9 +1,10 @@
 #ifndef BASIC_COMPILER_H
 #define BASIC_COMPILER_H
 
+#include "Code.h"
 #include "Error.h"
 #include "Tokenizer.h"
 
-Error compileFile(Tokenizer* t);
+Error compileFile(Tokenizer* t, Code* code);
 
 #endif

+ 10 - 4
src/Main.c

@@ -7,12 +7,17 @@
 #include "Tokenizer.h"
 
 static void compileAndRun(Tokenizer* t) {
-    Error e = compileFile(t);
+    Code code;
+    codeInit(&code);
+
+    Error e = compileFile(t, &code);
     if(hasError(&e)) {
         puts(e.text);
-        return;
+    } else {
+        codeRun(&code);
     }
-    codeRun();
+
+    codeDestroy(&code);
 }
 
 int main(int argCount, const char** args) {
@@ -20,7 +25,7 @@ int main(int argCount, const char** args) {
         return 0;
     }
 
-    static char heap[1024];
+    static char heap[2000];
     memoryInit(heap, sizeof(heap));
     // memoryDump();
 
@@ -43,6 +48,7 @@ int main(int argCount, const char** args) {
 
     Tokenizer t;
     Error e = tokenizerInit(&t, args[1]);
+    memoryDump();
     if(hasError(&e)) {
         puts(e.text);
     } else {

+ 8 - 8
src/Memory.c

@@ -107,16 +107,16 @@ void memoryFree(void* p) {
 }
 
 void memoryDump() {
-    for(size_t i = 0; i < maxUnits * sizeof(Slot); i++) {
-        printf("%02x", (unsigned)((char*)memory)[i] & 0xFF);
-        if((i + 1) % 30 == 0) {
-            putchar('\n');
-        }
-    }
-    putchar('\n');
+    // for(size_t i = 0; i < maxUnits * sizeof(Slot); i++) {
+    //     fprintf(stderr, "%02x", (unsigned)((char*)memory)[i] & 0xFF);
+    //     if((i + 1) % 30 == 0) {
+    //         fputc('\n', stderr);
+    //     }
+    // }
+    // fputc('\n', stderr);
     Slot* current = memoryNextSlot(slots);
     while(current != nullptr) {
-        printf("Free slot %u\n", current->units);
+        fprintf(stderr, "Free slot %u\n", current->units);
         current = memoryNextSlot(current);
     }
 }

+ 27 - 9
src/Tokenizer.c

@@ -22,7 +22,7 @@ typedef struct {
     longjmp(t->jump, 1)
 
 [[noreturn]] static void tTooMuchTokens(TState* t) {
-    THROW_ERROR("Line has too much tokens");
+    THROW_ERROR("Too less memory for tokens");
 }
 
 [[noreturn]] static void tInvalidToken(TState* t, char c) {
@@ -39,6 +39,12 @@ static void tAddToken(TState* t, TokenType type) {
     }
 }
 
+static void tAddSize(TState* t, size_t s) {
+    if(bufferWrite(&t->tokenizer->buffer, &s, sizeof(s))) {
+        tTooMuchTokens(t);
+    }
+}
+
 static void tAddChar(TState* t, char c) {
     if(bufferWriteI8(&t->tokenizer->buffer, c)) {
         tTooMuchTokens(t);
@@ -63,10 +69,14 @@ static bool isTokenEnd(char c) {
 
 static const char* tokenizerAddLiteral(TState* t, const char* s) {
     tAddToken(t, LITERAL);
+    size_t l = bufferGetWriteIndex(&t->tokenizer->buffer);
+    tAddSize(t, 0);
+    size_t total = 1;
     tAddChar(t, *s);
     while(true) {
         char c = *(++s);
         if(isAlphaNumeric(c)) {
+            total++;
             tAddChar(t, c);
         } else if(isTokenEnd(c)) {
             break;
@@ -74,7 +84,12 @@ static const char* tokenizerAddLiteral(TState* t, const char* s) {
             tInvalidToken(t, c);
         }
     }
+    total++;
     tAddChar(t, '\0');
+    size_t o = bufferGetWriteIndex(&t->tokenizer->buffer);
+    bufferSetWriteIndex(&t->tokenizer->buffer, l);
+    tAddSize(t, total);
+    bufferSetWriteIndex(&t->tokenizer->buffer, o);
     return s;
 }
 
@@ -110,6 +125,9 @@ static const char* tokenizerAddNumber(TState* t, const char* s) {
 
 static const char* tokenizerAddString(TState* t, const char* s) {
     tAddToken(t, STRING);
+    size_t l = bufferGetWriteIndex(&t->tokenizer->buffer);
+    tAddSize(t, 0);
+    size_t total = 0;
     while(true) {
         char c = *(++s);
         if(c == '\0') {
@@ -119,8 +137,14 @@ static const char* tokenizerAddString(TState* t, const char* s) {
             break;
         }
         tAddChar(t, c);
+        total++;
     }
     tAddChar(t, '\0');
+    total++;
+    size_t o = bufferGetWriteIndex(&t->tokenizer->buffer);
+    bufferSetWriteIndex(&t->tokenizer->buffer, l);
+    tAddSize(t, total);
+    bufferSetWriteIndex(&t->tokenizer->buffer, o);
     return s;
 }
 
@@ -165,14 +189,8 @@ static void tParseLines(TState* t) {
 }
 
 static const char* tReadString(Tokenizer* t) {
-    const char* c = (char*)(t->buffer.data + t->buffer.readIndex);
-    i8 i = 1;
-    while(i != 0) {
-        if(bufferReadI8(&t->buffer, &i)) {
-            assert(false);
-            return "";
-        }
-    }
+    const char* c = bufferReadString(&t->buffer);
+    assert(c != nullptr);
     return c;
 }