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.

This commit is contained in:
2022-03-15 20:50:08 +00:00
parent d4dd459389
commit b072921304
5 changed files with 85 additions and 18 deletions
+4
View File
@@ -8,6 +8,10 @@ $(SOURCE:.c=.o): $(SOURCE)
$(CC) $^ -o obj/clox $(CC) $^ -o obj/clox
.PHONY: clean .PHONY: clean
.PHONY: test
clean: clean:
rm -r obj rm -r obj
test:
./obj/clox test.lox
+72 -12
View File
@@ -1,4 +1,5 @@
#include "interpreter.h" #include "interpreter.h"
#include "expr.h"
#include "token.h" #include "token.h"
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@@ -6,23 +7,67 @@
#include <string.h> #include <string.h>
Object* Evaluate(Expr*); Object* Evaluate(Expr*);
Object* CreateObject(void*, TokenType); Object* CreateObject(const void*, TokenType);
void FreeObject(Object*); Object* VisitLiteralExpression(Expr*);
Object* VisitGroupingExpression(Expr*);
Object* VisitBinaryExpression(Expr*);
int IsTruthy(Object*); int IsTruthy(Object*);
int IsEqual(Object*, Object*); int IsEqual(Object*, Object*);
int ConcatStringObject(Object*, const Object*); int ConcatStringObject(Object*, const Object*);
void PrintObject(Object*);
const void* VisitLiteralExpression(Expr* expression) { void PrintObject(Object* o) {
return expression->expression.Literal->literal; 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) { void Interpret(Expr* exp) {
return Evaluate(expression); 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 interpreters visitor implementation
Object* VisitGroupingExpression(Expr* expression) {
return Evaluate(expression->expression.Grouping.expression);
} }
Object* VisitBinaryExpression(Expr* expression) { Object* VisitBinaryExpression(Expr* expression) {
Object* left = Evaluate(expression->expression.Binary.left); Object* left = Evaluate(expression->expression.Binary.left);
Object* right = Evaluate(expression->expression.Binary.right); Object* right = Evaluate(expression->expression.Binary.right);
PrintObject(left);
PrintObject(right);
double computed_value; double computed_value;
switch(expression->expression.Binary.op->type) { switch(expression->expression.Binary.op->type) {
@@ -73,6 +118,7 @@ Object* VisitBinaryExpression(Expr* expression) {
return left; return left;
//return *((double*)left) / *((double*)right); //return *((double*)left) / *((double*)right);
case Star: 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; left->value.number *= right->value.number;
FreeObject(right); FreeObject(right);
return left; return left;
@@ -107,7 +153,7 @@ Object* VisitBinaryExpression(Expr* expression) {
} }
Object* VisitUnaryExpression(Expr* expression) { Object* VisitUnaryExpression(Expr* expression) {
Object* right = Evaluate(expression); Object* right = Evaluate(expression->expression.Unary.right);
Object* c; Object* c;
double computed_value; double computed_value;
@@ -116,9 +162,6 @@ Object* VisitUnaryExpression(Expr* expression) {
computed_value = -right->value.number; computed_value = -right->value.number;
FreeObject(right); FreeObject(right);
c = CreateObject(&computed_value, Number); 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; return c;
case Bang: case Bang:
computed_value = !IsTruthy(right); computed_value = !IsTruthy(right);
@@ -135,11 +178,27 @@ Object* VisitUnaryExpression(Expr* expression) {
} }
Object* Evaluate(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; return NULL;
} }
Object* CreateObject(void* value, TokenType type) { Object* CreateObject(const void* value, TokenType type) {
Object* object = calloc(1, sizeof(Object)); Object* object = calloc(1, sizeof(Object));
if (!object) { if (!object) {
@@ -152,6 +211,7 @@ Object* CreateObject(void* value, TokenType type) {
object->instance = INS_NULL; object->instance = INS_NULL;
break; break;
case Number: case Number:
//printf("NUM: %p, %f\n", value, *(double*) value);
object->instance = INS_DOUBLE; object->instance = INS_DOUBLE;
object->value.number = *(double*) value; object->value.number = *(double*) value;
break; break;
+2 -3
View File
@@ -20,8 +20,7 @@ typedef struct Object {
} value; } value;
} Object; } Object;
const void* VisitLiteralExpression(Expr*); void Interpret(Expr*);
void* VisitGroupingExpression(Expr*); void FreeObject(Object*);
Object* VisitBinaryExpression(Expr*);
#endif #endif
+2
View File
@@ -1,6 +1,7 @@
#include "scanner.h" #include "scanner.h"
#include "parser.h" #include "parser.h"
#include "expr.h" #include "expr.h"
#include "interpreter.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sysexits.h> #include <sysexits.h>
@@ -43,6 +44,7 @@ void RunFile(const char* path) {
Expr* tree = GenerateExpressionTree(tokens); Expr* tree = GenerateExpressionTree(tokens);
PrintExpressionTree(tree); PrintExpressionTree(tree);
printf("\n"); printf("\n");
Interpret(tree);
FreeExpressionTree(tree); FreeExpressionTree(tree);
DestroyTokenList(tokens); DestroyTokenList(tokens);
} }
+4 -2
View File
@@ -235,14 +235,16 @@ void ParseNumber(TokenList* list) {
while(isdigit(ScannerPeek())) AdvanceScanner(); while(isdigit(ScannerPeek())) AdvanceScanner();
} }
char* lexeme = calloc(current - start + 2, sizeof(char)); AdvanceScanner();
char* lexeme = calloc(current - start + 1, sizeof(char));
if (!lexeme) { if (!lexeme) {
fprintf(stderr, "Failed to calloc for number lexeme. %s\n", strerror(errno)); fprintf(stderr, "Failed to calloc for number lexeme. %s\n", strerror(errno));
return; 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? double value = atof(lexeme); //Will this reference become stale on return?
AddToTokenList(CreateToken(lexeme, &value, line, Number), list); AddToTokenList(CreateToken(lexeme, &value, line, Number), list);