Browse Source

null type, refactoring

Kajetan Johannes Hammerle 3 years ago
parent
commit
67b23135d8
9 changed files with 49 additions and 56 deletions
  1. 4 1
      Compiler.c
  2. 1 1
      Object.h
  3. 1 1
      Operation.h
  4. 6 0
      Script.c
  5. 12 52
      Test.c
  6. 20 0
      Tokenizer.c
  7. 3 1
      Tokenizer.h
  8. 1 0
      tests/types/null
  9. 1 0
      tests/types/null.out

+ 4 - 1
Compiler.c

@@ -64,9 +64,11 @@ static bool cConsumeTokenIf(Token t) {
 }
 
 static bool cConstant() {
-    if(cConsumeToken(T_INT)) {
+    if(cConsumeTokenIf(T_INT)) {
         int value;
         return tReadInt(&value) && cAddOperation(OP_PUSH_INT) && cAddBytes(&value, sizeof(int));
+    } else if(cConsumeTokenIf(T_NULL)) {
+        return cAddOperation(OP_PUSH_NULL);
     }
     return false;
 }
@@ -112,6 +114,7 @@ static bool cLine() {
 
 unsigned char* cCompile(int* codeLength) {
     writeIndex = 0;
+    error[0] = '\0';
     while(cLine()) {
     }
     if(error[0] != '\0') {

+ 1 - 1
Object.h

@@ -1,7 +1,7 @@
 #ifndef OBJECT_H
 #define OBJECT_H
 
-typedef enum ObjectType { OT_INT } ObjectType;
+typedef enum ObjectType { OT_INT, OT_NULL } ObjectType;
 
 typedef struct Object {
     ObjectType type;

+ 1 - 1
Operation.h

@@ -1,6 +1,6 @@
 #ifndef OPERATION_H
 #define OPERATION_H
 
-typedef enum Operation { OP_NOTHING, OP_PUSH_INT, OP_ADD, OP_MUL, OP_PRINT } Operation;
+typedef enum Operation { OP_NOTHING, OP_PUSH_INT, OP_PUSH_NULL, OP_ADD, OP_MUL, OP_PRINT } Operation;
 
 #endif

+ 6 - 0
Script.c

@@ -66,6 +66,11 @@ static void sPushInt(Script* sc) {
     sPush(sc, &o);
 }
 
+static void sPushNull(Script* sc) {
+    Object o = {.type = OT_NULL};
+    sPush(sc, &o);
+}
+
 void sAdd(Script* sc) {
     Object a;
     if(sPop(sc, &a)) {
@@ -114,6 +119,7 @@ static void sConsumeInstruction(Script* sc) {
     switch(sReadOperation(sc)) {
         case OP_NOTHING: break;
         case OP_PUSH_INT: sPushInt(sc); break;
+        case OP_PUSH_NULL: sPushNull(sc); break;
         case OP_ADD: sAdd(sc); break;
         case OP_MUL: sMul(sc); break;
         case OP_PRINT: sPrint(sc); break;

+ 12 - 52
Test.c

@@ -1,5 +1,6 @@
 #include <dirent.h>
 #include <errno.h>
+#include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -18,21 +19,24 @@ static int pathIndex = 0;
 static char testBuffer[TEST_BUFFER_LENGTH];
 static int testBufferIndex = 0;
 
-static void tsAddBufferIndex(int length) {
-    testBufferIndex += length;
+static void tsPrintToBuffer(const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    int leftBytes = TEST_BUFFER_LENGTH - testBufferIndex;
+    testBufferIndex += vsnprintf(testBuffer + testBufferIndex, leftBytes, format, args);
     if(testBufferIndex > TEST_BUFFER_LENGTH) {
         testBufferIndex = TEST_BUFFER_LENGTH;
     }
+    va_end(args);
 }
 
 static bool tsPrinter(Object* o) {
     if(testBufferIndex >= TEST_BUFFER_LENGTH) {
         return true;
     }
-    if(o->type == OT_INT) {
-        int leftBytes = TEST_BUFFER_LENGTH - testBufferIndex;
-        tsAddBufferIndex(snprintf(testBuffer + testBufferIndex, leftBytes, "%d\n", o->data.intValue));
-        return false;
+    switch(o->type) {
+        case OT_INT: tsPrintToBuffer("%d\n", o->data.intValue); return false;
+        case OT_NULL: tsPrintToBuffer("null\n"); return false;
     }
     return true;
 }
@@ -89,12 +93,14 @@ static void tsCheckScript(Script* sc) {
 static void tsCheckFile() {
     allTests++;
     if(tTokenize(path)) {
+        puts(path);
         puts(tGetError());
         return;
     }
     int codeLength;
     unsigned char* code = cCompile(&codeLength);
     if(code == NULL) {
+        puts(path);
         puts(cGetError());
         return;
     }
@@ -130,52 +136,6 @@ static void tsScanDirectory() {
     }
 }
 
-/*static String readLine(std::ifstream& f) {
-    String s;
-    while(true) {
-        char c = f.get();
-        if(!f.good() || c == '\n') {
-            break;
-        }
-        s += c;
-    }
-    return s;
-}
-
-static bool testTokenizer(const String& input, const String& output) {
-    tests++;
-    std::ifstream oStream;
-    oStream.open(output);
-    if(!oStream.good()) {
-        std::cout << "cannot open file '" << output << "'\n";
-        return true;
-    }
-    TokenStream tokenStream;
-    if(Tokenizer::tokenize(tokenStream, input)) {
-        return true;
-    }
-    while(true) {
-        String expected = readLine(oStream);
-        if(expected.getLength() == 0) {
-            break;
-        } else if(!tokenStream.hasToken()) {
-            std::cout << "error in '" << input << "\n'out of tokens\n";
-            return false;
-        }
-        String buffer = tokenStream.nextTokenString();
-        if(strchr(buffer, '\n') != nullptr) {
-            expected += '\n';
-            expected += readLine(oStream);
-        }
-        if(strcmp(buffer, expected) != 0) {
-            std::cout << "error in '" << input << "\n'" << buffer << "' should be '" << expected << "'\n";
-            return false;
-        }
-    }
-    done++;
-    return false;
-}*/
-
 void tsStart(const char* path) {
     sSetPrinter(tsPrinter);
     doneTests = 0;

+ 20 - 0
Tokenizer.c

@@ -69,6 +69,8 @@ static bool tParseLiteral(int c) {
     buffer[index] = '\0';
     if(strcmp(buffer, "print") == 0) {
         return tAddToken(T_PRINT);
+    } else if(strcmp(buffer, "null") == 0) {
+        return tAddToken(T_NULL);
     }
     return true;
 }
@@ -153,6 +155,7 @@ bool tReadInt(int* i) {
 const char* tGetTokenName(Token token) {
     switch(token) {
         case T_INT: return "int";
+        case T_NULL: return "null";
         case T_ADD: return "+";
         case T_MUL: return "*";
         case T_PRINT: return "print";
@@ -160,4 +163,21 @@ const char* tGetTokenName(Token token) {
         case T_END: return "end";
     }
     return "Unknown";
+}
+
+void tPrint() {
+    puts("----------------");
+    while(true) {
+        Token t = tReadToken();
+        if(t == T_END) {
+            break;
+        }
+        int line;
+        tReadInt(&line);
+        printf("%d: %s\n", line, tGetTokenName(t));
+        if(t == T_INT) {
+            tReadInt(&line);
+        }
+    }
+    tResetReader();
 }

+ 3 - 1
Tokenizer.h

@@ -3,7 +3,7 @@
 
 #include <stdbool.h>
 
-typedef enum Token { T_INT, T_ADD, T_MUL, T_PRINT, T_SEMICOLON, T_END } Token;
+typedef enum Token { T_INT, T_NULL, T_ADD, T_MUL, T_PRINT, T_SEMICOLON, T_END } Token;
 
 bool tTokenize(const char* path);
 const char* tGetError();
@@ -15,4 +15,6 @@ bool tReadInt(int* i);
 
 const char* tGetTokenName(Token token);
 
+void tPrint();
+
 #endif

+ 1 - 0
tests/types/null

@@ -0,0 +1 @@
+print null;

+ 1 - 0
tests/types/null.out

@@ -0,0 +1 @@
+null