Compare commits

...
2 Commits
5 changed files with 87 additions and 20 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);
}
+6 -4
View File
@@ -212,6 +212,8 @@ void ParseString(TokenList *list) {
return;
}
AdvanceScanner();
char* lexeme = calloc(current - start + 1, sizeof(char));
if (!lexeme) {
@@ -222,8 +224,6 @@ void ParseString(TokenList *list) {
snprintf(lexeme, current - start, "%s", &source_code[start]);
AddToTokenList(CreateToken(lexeme, lexeme, line, String), list);
AdvanceScanner(); // The closing ".
}
void ParseNumber(TokenList* list) {
@@ -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);