Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78e07778b1 | ||
|
|
d4dd459389 |
@@ -8,6 +8,10 @@ $(SOURCE:.c=.o): $(SOURCE)
|
||||
$(CC) $^ -o obj/clox
|
||||
|
||||
.PHONY: clean
|
||||
.PHONY: test
|
||||
|
||||
clean:
|
||||
rm -r obj
|
||||
|
||||
test:
|
||||
./obj/clox test.lox
|
||||
+72
-12
@@ -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 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;
|
||||
|
||||
+2
-3
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user