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
+5 -1
View File
@@ -8,6 +8,10 @@ $(SOURCE:.c=.o): $(SOURCE)
$(CC) $^ -o obj/clox
.PHONY: clean
.PHONY: test
clean:
rm -r obj
rm -r obj
test:
./obj/clox test.lox
+72 -12
View File
@@ -1,4 +1,5 @@
#include "interpreter.h"
#include "expr.h"
#include "token.h"
#include <errno.h>
#include <stdio.h>
@@ -6,23 +7,67 @@
#include <string.h>
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 interpreters 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;
+2 -3
View File
@@ -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
+2
View File
@@ -1,6 +1,7 @@
#include "scanner.h"
#include "parser.h"
#include "expr.h"
#include "interpreter.h"
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
@@ -43,6 +44,7 @@ void RunFile(const char* path) {
Expr* tree = GenerateExpressionTree(tokens);
PrintExpressionTree(tree);
printf("\n");
Interpret(tree);
FreeExpressionTree(tree);
DestroyTokenList(tokens);
}
+4 -2
View File
@@ -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);