More refactoring trying to get this cleaned up while trying to keep it easy(ish) to extend for later chapters. I'll never take namespaces for granted again...
This commit is contained in:
+105
-17
@@ -1,9 +1,15 @@
|
||||
#include "interpreter.h"
|
||||
#include "token.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
Object* Evaluate(Expr*);
|
||||
Object* CreateObject(void*, TokenType);
|
||||
void FreeObject(Object*);
|
||||
int IsTruthy(Object*);
|
||||
int IsEqual(Object*, Object*);
|
||||
int ConcatStringObject(Object*, const Object*);
|
||||
|
||||
const void* VisitLiteralExpression(Expr* expression) {
|
||||
return expression->expression.Literal->literal;
|
||||
@@ -13,9 +19,9 @@ void* VisitGroupingExpression(Expr* expression) {
|
||||
return Evaluate(expression);
|
||||
}
|
||||
|
||||
void* VisitBinaryExpression(Expr* expression) {
|
||||
void* left = Evaluate(expression->expression.Binary.left);
|
||||
void* right = Evaluate(expression->expression.Binary.right);
|
||||
Object* VisitBinaryExpression(Expr* expression) {
|
||||
Object* left = Evaluate(expression->expression.Binary.left);
|
||||
Object* right = Evaluate(expression->expression.Binary.right);
|
||||
|
||||
switch(expression->expression.Binary.op->type) {
|
||||
case Greater:
|
||||
@@ -27,30 +33,50 @@ void* VisitBinaryExpression(Expr* expression) {
|
||||
case Less_Equal:
|
||||
return left <= right;
|
||||
case Minus:
|
||||
return left - right;
|
||||
left->value.number -= right->value.number;
|
||||
FreeObject(right);
|
||||
return left;
|
||||
//return left - right;
|
||||
case Bang_Equal:
|
||||
return !IsEqual(left, right);
|
||||
case Equal_Equal:
|
||||
return IsEqual(left, right);
|
||||
case Slash:
|
||||
return *((double*)left) / *((double*)right);
|
||||
left->value.number /= right->value.number;
|
||||
FreeObject(right);
|
||||
return left;
|
||||
//return *((double*)left) / *((double*)right);
|
||||
case Star:
|
||||
return *((double*)left) * *((double*)right);
|
||||
left->value.number *= right->value.number;
|
||||
FreeObject(right);
|
||||
return left;
|
||||
//return *((double*)left) * *((double*)right);
|
||||
case Plus:
|
||||
if (((Token*)left)->type == Number && ((Token*)right)->type == Number) {
|
||||
return left + right;
|
||||
}
|
||||
if (left->instance == INS_DOUBLE && right->instance == INS_DOUBLE) {
|
||||
left->value.number += right->value.number;
|
||||
FreeObject(right);
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
if (left->instance == INS_STRING && right->instance == INS_STRING) {
|
||||
if (ConcatStringObject(left, right)) {
|
||||
FreeObject(right);
|
||||
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
if (((Token*)left)->type == String && ((Token*)right)->type == String) {
|
||||
return NULL; //String concat
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
FreeObject(left);
|
||||
FreeObject(right);
|
||||
// Unreachable
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* VisitUnaryExpression(Expr* expression) {
|
||||
Object* VisitUnaryExpression(Expr* expression) {
|
||||
void* right = Evaluate(expression);
|
||||
|
||||
switch (expression->type) {
|
||||
@@ -67,11 +93,75 @@ void* VisitUnaryExpression(Expr* expression) {
|
||||
}
|
||||
|
||||
Object* Evaluate(Expr* expression) {
|
||||
//accept
|
||||
//accept -> calls Visitor functions by type
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Object* CreateObject(void* value, TokenType type) {
|
||||
Object* object = calloc(1, sizeof(Object));
|
||||
|
||||
if (!object) {
|
||||
fprintf(stderr, "Failed to calloc object. %s.\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case NIL:
|
||||
object->instance = INS_NULL;
|
||||
break;
|
||||
case Number:
|
||||
object->instance = INS_DOUBLE;
|
||||
object->value.number = *((double*) value);
|
||||
break;
|
||||
case TRUE:
|
||||
case FALSE:
|
||||
object->instance = INS_BOOLEAN;
|
||||
object->value.boolean = *((int*) value);
|
||||
break;
|
||||
default:
|
||||
object->instance = INS_STRING;
|
||||
|
||||
if (value) {
|
||||
int length = strlen(value);
|
||||
object->value.string = calloc(length + 1, sizeof(char));
|
||||
|
||||
strncpy(object->value.string, value, length);
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void FreeObject(Object* object) {
|
||||
if (object->instance == INS_STRING) free(object->value.string);
|
||||
|
||||
free(object);
|
||||
}
|
||||
|
||||
int ConcatStringObject(Object* a, const Object* b) {
|
||||
if (!a || !b) return 0;
|
||||
if (a->instance != INS_STRING || b->instance != INS_STRING) return 0;
|
||||
|
||||
int a_length = strlen(a->value.string);
|
||||
int b_length = strlen(b->value.string);
|
||||
char* c;
|
||||
|
||||
c = realloc(a->value.string, a_length + b_length + 1);
|
||||
|
||||
if (!c) {
|
||||
fprintf(stderr, "Failed to realloc for object concat. %s.\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
a->value.string = c;
|
||||
|
||||
strncat(a->value.string, b->value.string, b_length);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int IsTruthy(Object* object) {
|
||||
|
||||
if (!object || object->instance == NIL) return 0;
|
||||
if (object->instance == TRUE) return 0;
|
||||
|
||||
@@ -87,9 +177,7 @@ int IsEqual(Object* a, Object* b) {
|
||||
}
|
||||
|
||||
if (a->instance == String && b->instance == String) {
|
||||
int result = strcmp(a->value.string, b->value.string);
|
||||
|
||||
return result == 0;
|
||||
return strcmp(a->value.string, b->value.string) == 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+9
-2
@@ -4,8 +4,15 @@
|
||||
#include "expr.h"
|
||||
#include "token.h"
|
||||
|
||||
typedef enum {
|
||||
INS_STRING,
|
||||
INS_DOUBLE,
|
||||
INS_BOOLEAN,
|
||||
INS_NULL
|
||||
} ObjectInstanceType;
|
||||
|
||||
typedef struct Object {
|
||||
TokenType instance;
|
||||
ObjectInstanceType instance;
|
||||
union {
|
||||
char* string;
|
||||
double number;
|
||||
@@ -15,6 +22,6 @@ typedef struct Object {
|
||||
|
||||
const void* VisitLiteralExpression(Expr*);
|
||||
void* VisitGroupingExpression(Expr*);
|
||||
void* VisitBinaryExpression(Expr*);
|
||||
Object* VisitBinaryExpression(Expr*);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user