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);