Browse Source

source file line for runtime errors

Kajetan Johannes Hammerle 4 years ago
parent
commit
b694007673
3 changed files with 22 additions and 14 deletions
  1. 1 1
      Compiler.c
  2. 18 12
      Script.c
  3. 3 1
      Script.h

+ 1 - 1
Compiler.c

@@ -35,7 +35,7 @@ static bool cAddBytes(const void* data, int length) {
 
 static bool cAddOperation(Operation token) {
     unsigned char c = token;
-    return cAddBytes(&c, 1);
+    return cAddBytes(&c, 1) && cAddBytes(&line, sizeof(int));
 }
 
 static Token tReadTokenAndLine() {

+ 18 - 12
Script.c

@@ -1,3 +1,4 @@
+#include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,11 +7,12 @@
 #include "Operation.h"
 #include "Script.h"
 
-static const char* MISSING_INT_CONSTANT = "cannot read an int from the bytecode";
-static const char* NOT_AN_INT = "object is not an int";
-static const char* NOT_PRINTABLE = "cannot print given object";
-static const char* STACK_OVERFLOW = "stack overflow";
-static const char* STACK_UNDERFLOW = "stack underflow";
+static void sError(Script* sc, const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    vsnprintf(sc->error, SCRIPT_ERROR_SIZE, format, args);
+    va_end(args);
+}
 
 static bool sPrinter(Object* o) {
     if(o->type == OT_INT) {
@@ -35,13 +37,16 @@ static Operation sReadOperation(Script* sc) {
     unsigned char c;
     if(sRead(sc, &c, 1)) {
         return OP_NOTHING;
+    } else if(sRead(sc, &sc->line, sizeof(int))) {
+        // operation without line
+        return OP_NOTHING;
     }
     return c;
 }
 
 static void sPush(Script* sc, Object* o) {
     if(sc->stackIndex >= SCRIPT_STACK_SIZE) {
-        sc->error = STACK_OVERFLOW;
+        sError(sc, "stack overflow on line %d", sc->line);
         return;
     }
     sc->stack[sc->stackIndex++] = *o;
@@ -49,7 +54,7 @@ static void sPush(Script* sc, Object* o) {
 
 static bool sPop(Script* sc, Object* o) {
     if(sc->stackIndex <= 0) {
-        sc->error = STACK_UNDERFLOW;
+        sError(sc, "stack underflow on line %d", sc->line);
         return true;
     }
     *o = sc->stack[--sc->stackIndex];
@@ -59,7 +64,7 @@ static bool sPop(Script* sc, Object* o) {
 static void sPushInt(Script* sc) {
     int value = 0;
     if(sRead(sc, &value, sizeof(int))) {
-        sc->error = MISSING_INT_CONSTANT;
+        sError(sc, "cannot read an int from the bytecode on line %d", sc->line);
         return;
     }
     Object o = {.type = OT_INT, .data.intValue = value};
@@ -81,7 +86,7 @@ static void sIntBinary(Script* sc, int (*f)(int, int)) {
         return;
     }
     if(a.type != OT_INT || b.type != OT_INT) {
-        sc->error = NOT_AN_INT;
+        sError(sc, "object is not an int on line %d", sc->line);
         return;
     }
     Object o = {.type = OT_INT, .data.intValue = f(a.data.intValue, b.data.intValue)};
@@ -102,7 +107,7 @@ static void sPrint(Script* sc) {
         return;
     }
     if(printer(&o)) {
-        sc->error = NOT_PRINTABLE;
+        sError(sc, "cannot print given object on line %d", sc->line);
     }
 }
 
@@ -123,11 +128,12 @@ static bool sHasData(Script* sc) {
 
 Script* sInit(unsigned char* byteCode, int codeLength) {
     Script* sc = malloc(sizeof(Script));
-    sc->error = NULL;
+    sc->error[0] = '\0';
     sc->byteCode = byteCode;
     sc->byteCodeLength = codeLength;
     sc->readIndex = 0;
     sc->stackIndex = 0;
+    sc->line = 0;
     return sc;
 }
 
@@ -138,7 +144,7 @@ void sDelete(Script* sc) {
 void sRun(Script* sc) {
     while(sHasData(sc)) {
         sConsumeInstruction(sc);
-        if(sc->error != NULL) {
+        if(sc->error[0] != '\0') {
             puts(sc->error);
             return;
         }

+ 3 - 1
Script.h

@@ -6,14 +6,16 @@
 #include "Object.h"
 
 #define SCRIPT_STACK_SIZE 50
+#define SCRIPT_ERROR_SIZE 256
 
 typedef struct Script {
-    const char* error;
+    char error[SCRIPT_ERROR_SIZE];
     unsigned char* byteCode;
     int byteCodeLength;
     int readIndex;
     Object stack[SCRIPT_STACK_SIZE];
     int stackIndex;
+    int line;
 } Script;
 
 Script* sInit(unsigned char* byteCode, int codeLength);