From b0729213045fb6b024c75068ed0949eb2371e22c Mon Sep 17 00:00:00 2001 From: Garritt McCune Date: Tue, 15 Mar 2022 20:45:06 +0000 Subject: [PATCH] Touched up the Scanner. Refactored the Interpreter some more, this time it's able to be run on simple expressions. String concatenation can be performed by the Interpreter however, numbers and Booleans are not being stored correctly in the Object structures. --- Makefile | 6 +++- interpreter.c | 84 +++++++++++++++++++++++++++++++++++++++++++-------- interpreter.h | 5 ++- lox.c | 2 ++ scanner.c | 6 ++-- 5 files changed, 85 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index c3a1252..8b2fab8 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,10 @@ $(SOURCE:.c=.o): $(SOURCE) $(CC) $^ -o obj/clox .PHONY: clean +.PHONY: test clean: - rm -r obj \ No newline at end of file + rm -r obj + +test: + ./obj/clox test.lox \ No newline at end of file diff --git a/interpreter.c b/interpreter.c index 9513cb1..1091732 100644 --- a/interpreter.c +++ b/interpreter.c @@ -1,4 +1,5 @@ #include "interpreter.h" +#include "expr.h" #include "token.h" #include #include @@ -6,23 +7,67 @@ #include Object* Evaluate(Expr*); -Object* CreateObject(void*, TokenType); -void FreeObject(Object*); +Object* CreateObject(const void*, TokenType); +Object* VisitLiteralExpression(Expr*); +Object* VisitGroupingExpression(Expr*); +Object* VisitBinaryExpression(Expr*); int IsTruthy(Object*); int IsEqual(Object*, Object*); int ConcatStringObject(Object*, const Object*); +void PrintObject(Object*); -const void* VisitLiteralExpression(Expr* expression) { - return expression->expression.Literal->literal; +void PrintObject(Object* o) { + switch(o->instance) { + case INS_BOOLEAN: + printf("BOOL: %d\n", o->value.boolean); + break; + case INS_DOUBLE: + printf("DOUBLE: %f\n", o->value.number); + break; + case INS_STRING: + printf("STRING: %s\n", o->value.string); + break; + default: + printf("NULL\n"); + } } -void* VisitGroupingExpression(Expr* expression) { - return Evaluate(expression); +void Interpret(Expr* exp) { + Object* c = Evaluate(exp); + + switch(c->instance) { + case INS_BOOLEAN: + printf("Bool %d\n", c->value.boolean); + break; + case INS_DOUBLE: + printf("Number %f\n", c->value.number); + break; + case INS_STRING: + printf("String '%s'\n", c->value.string); + break; + default: + printf("Default\n"); + } + printf("Freeing Object...\n"); + FreeObject(c); +} + +Object* VisitLiteralExpression(Expr* expr) { + printf("Literal: %p\n", (double *) expr->expression.Literal->literal); + return CreateObject(expr->expression.Literal->literal, expr->expression.Literal->type); +} + +//NOTE: We rely on this helper method which simply sends the expression back into +//the interpreter’s visitor implementation +Object* VisitGroupingExpression(Expr* expression) { + return Evaluate(expression->expression.Grouping.expression); } Object* VisitBinaryExpression(Expr* expression) { Object* left = Evaluate(expression->expression.Binary.left); Object* right = Evaluate(expression->expression.Binary.right); + PrintObject(left); + PrintObject(right); double computed_value; switch(expression->expression.Binary.op->type) { @@ -73,6 +118,7 @@ Object* VisitBinaryExpression(Expr* expression) { return left; //return *((double*)left) / *((double*)right); case Star: + printf("%f * %f = %f\n", left->value.number, right->value.number, left->value.number * right->value.number); left->value.number *= right->value.number; FreeObject(right); return left; @@ -107,7 +153,7 @@ Object* VisitBinaryExpression(Expr* expression) { } Object* VisitUnaryExpression(Expr* expression) { - Object* right = Evaluate(expression); + Object* right = Evaluate(expression->expression.Unary.right); Object* c; double computed_value; @@ -116,9 +162,6 @@ Object* VisitUnaryExpression(Expr* expression) { computed_value = -right->value.number; FreeObject(right); c = CreateObject(&computed_value, Number); - //right needs to be negated, but that kind of introduces a - //memory leak since we can't really change it, what with the - //whole "const void*" thing and all. return c; case Bang: computed_value = !IsTruthy(right); @@ -135,11 +178,27 @@ Object* VisitUnaryExpression(Expr* expression) { } Object* Evaluate(Expr* expression) { - //accept -> calls Visitor functions by type + switch (expression->type) { + case EXPRESSION: + fprintf(stderr, "EXPRESSION case seen for expression.\n"); + break; + case UNARY: + return VisitUnaryExpression(expression); + case GROUPING: + return VisitGroupingExpression(expression->expression.Grouping.expression); + case BINARY: + return VisitBinaryExpression(expression); + case LITERAL: + return VisitLiteralExpression(expression); + default: + fprintf(stderr, "Default case seen for expression.\n"); + break; + } + //return expr.accept(this); return NULL; } -Object* CreateObject(void* value, TokenType type) { +Object* CreateObject(const void* value, TokenType type) { Object* object = calloc(1, sizeof(Object)); if (!object) { @@ -152,6 +211,7 @@ Object* CreateObject(void* value, TokenType type) { object->instance = INS_NULL; break; case Number: + //printf("NUM: %p, %f\n", value, *(double*) value); object->instance = INS_DOUBLE; object->value.number = *(double*) value; break; diff --git a/interpreter.h b/interpreter.h index fbbfb46..07e2166 100644 --- a/interpreter.h +++ b/interpreter.h @@ -20,8 +20,7 @@ typedef struct Object { } value; } Object; -const void* VisitLiteralExpression(Expr*); -void* VisitGroupingExpression(Expr*); -Object* VisitBinaryExpression(Expr*); +void Interpret(Expr*); +void FreeObject(Object*); #endif \ No newline at end of file diff --git a/lox.c b/lox.c index 8ea9ed5..d1cf93a 100644 --- a/lox.c +++ b/lox.c @@ -1,6 +1,7 @@ #include "scanner.h" #include "parser.h" #include "expr.h" +#include "interpreter.h" #include #include #include @@ -43,6 +44,7 @@ void RunFile(const char* path) { Expr* tree = GenerateExpressionTree(tokens); PrintExpressionTree(tree); printf("\n"); + Interpret(tree); FreeExpressionTree(tree); DestroyTokenList(tokens); } diff --git a/scanner.c b/scanner.c index 34b0d6f..4dbf79d 100644 --- a/scanner.c +++ b/scanner.c @@ -235,14 +235,16 @@ void ParseNumber(TokenList* list) { while(isdigit(ScannerPeek())) AdvanceScanner(); } - char* lexeme = calloc(current - start + 2, sizeof(char)); + AdvanceScanner(); + + char* lexeme = calloc(current - start + 1, sizeof(char)); if (!lexeme) { fprintf(stderr, "Failed to calloc for number lexeme. %s\n", strerror(errno)); return; } - snprintf(lexeme, current - start + 1, "%s", &source_code[start]); + snprintf(lexeme, current - start, "%s", &source_code[start]); double value = atof(lexeme); //Will this reference become stale on return? AddToTokenList(CreateToken(lexeme, &value, line, Number), list);