Compare commits
2
Commits
1ded68ddee
...
78e07778b1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78e07778b1 | ||
|
|
d4dd459389 |
@@ -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
@@ -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 interpreter’s 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
@@ -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
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,6 +212,8 @@ void ParseString(TokenList *list) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdvanceScanner();
|
||||||
|
|
||||||
char* lexeme = calloc(current - start + 1, sizeof(char));
|
char* lexeme = calloc(current - start + 1, sizeof(char));
|
||||||
|
|
||||||
if (!lexeme) {
|
if (!lexeme) {
|
||||||
@@ -222,8 +224,6 @@ void ParseString(TokenList *list) {
|
|||||||
snprintf(lexeme, current - start, "%s", &source_code[start]);
|
snprintf(lexeme, current - start, "%s", &source_code[start]);
|
||||||
|
|
||||||
AddToTokenList(CreateToken(lexeme, lexeme, line, String), list);
|
AddToTokenList(CreateToken(lexeme, lexeme, line, String), list);
|
||||||
|
|
||||||
AdvanceScanner(); // The closing ".
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseNumber(TokenList* list) {
|
void ParseNumber(TokenList* list) {
|
||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user