Skip to content

Commit

Permalink
fix: interpreter parsing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
giancarlopro committed Sep 10, 2023
1 parent 92552c6 commit a125754
Show file tree
Hide file tree
Showing 4 changed files with 499 additions and 71 deletions.
40 changes: 38 additions & 2 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ void free_var_t(var_t *var) {
free(var);
}

function_t *make_function_t(parameter_t **parameters, term_t *value) {
function_t *make_function_t(array_t *parameters, term_t *value) {
function_t *function = malloc(sizeof(function_t));

function->kind = "Function";
Expand All @@ -278,7 +278,7 @@ void free_function_t(function_t *function) {
free(function);
}

call_t *make_call_t(term_t *callee, term_t **arguments) {
call_t *make_call_t(term_t *callee, array_t *arguments) {
call_t *call = malloc(sizeof(call_t));

call->kind = "Call";
Expand All @@ -294,3 +294,39 @@ void free_call_t(call_t *call) {
free_term_t(call->callee);
free(call);
}

variable_t *make_variable_t(const char *key, result_t *value) {
variable_t *variable = malloc(sizeof(variable_t));

variable->key = key;
variable->value = value;

return variable;
}

void free_variable_t(variable_t *variable) {
if (variable == NULL) return;

free_result_t(variable->value);
free(variable);
}

array_t *make_array_t(size_t length, void **values) {
array_t *array = malloc(sizeof(array_t));

array->length = length;
array->values = values;

return array;
}

void free_array_t(array_t *array) {
if (array == NULL) return;

for (size_t i = 0; i < array->length; i++) {
if (array->values[i] != NULL) free(array->values[i]);
}

free(array->values);
free(array);
}
135 changes: 96 additions & 39 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ stack_t *stack = NULL;
stack_t *current_stack = NULL;

term_t *parse_expression(json_object *expression) {
if (expression == NULL) {
runtime_error("Syntax error");
}

const char *kind =
json_object_get_string(json_object_object_get(expression, "kind"));

Expand Down Expand Up @@ -44,8 +48,8 @@ term_t *parse_expression(json_object *expression) {
parse_expression(json_object_object_get(expression, "otherwise")));
} else if (match(kind, "Let")) {
return (term_t *)make_let_t(
make_parameter_t(json_object_get_string(
json_object_object_get(expression, "name"))),
make_parameter_t(json_object_get_string(json_object_object_get(
json_object_object_get(expression, "name"), "text"))),
parse_expression(json_object_object_get(expression, "value")),
parse_expression(json_object_object_get(expression, "next")));
} else if (match(kind, "Var")) {
Expand All @@ -55,31 +59,42 @@ term_t *parse_expression(json_object *expression) {
json_object *parameters =
json_object_object_get(expression, "parameters");

parameter_t **params = malloc(sizeof(parameter_t *) *
json_object_array_length(parameters));
size_t length = json_object_array_length(parameters);

for (int i = 0; i < json_object_array_length(parameters); i++) {
params[i] = make_parameter_t(json_object_get_string(
json_object_array_get_idx(parameters, i)));
parameter_t **params = NULL;
if (length > 0) {
params = malloc(sizeof(parameter_t *) * length);

for (int i = 0; i < length; i++) {
params[i] = make_parameter_t(
json_object_get_string(json_object_object_get(
json_object_array_get_idx(parameters, i), "text")));
}
}

return (term_t *)make_function_t(
params,
make_array_t(length, (void **)params),
parse_expression(json_object_object_get(expression, "value")));
} else if (match(kind, "Call")) {
json_object *arguments =
json_object_object_get(expression, "arguments");

term_t **args =
malloc(sizeof(term_t *) * json_object_array_length(arguments));
size_t length = json_object_array_length(arguments);

for (int i = 0; i < json_object_array_length(arguments); i++) {
args[i] = parse_expression(json_object_array_get_idx(arguments, i));
term_t **args = NULL;

if (length > 0) {
args = malloc(sizeof(term_t *) * length);

for (int i = 0; i < length; i++) {
args[i] =
parse_expression(json_object_array_get_idx(arguments, i));
}
}

return (term_t *)make_call_t(
parse_expression(json_object_object_get(expression, "callee")),
args);
make_array_t(length, (void **)args));
} else {
runtime_error("Unknown term kind: %s", kind);
}
Expand All @@ -88,25 +103,27 @@ term_t *parse_expression(json_object *expression) {
result_t *print(term_t *root) {
result_t *res = eval(root);

if (match(root->kind, "Str")) {
if (match(res->type, "Str")) {
printf("%s", (char *)res->value);
} else if (match(root->kind, "Int")) {
} else if (match(res->type, "Int")) {
printf("%d", *(int *)res->value);
} else if (match(root->kind, "Bool")) {
} else if (match(res->type, "Bool")) {
bool value = *(bool *)res->value;
if (value) {
printf("true");
} else {
printf("false");
}
} else if (match(root->kind, "Tuple")) {
} else if (match(res->type, "Tuple")) {
tuple_t *tuple = (tuple_t *)root;

printf("(");
print(tuple->first);
printf(", ");
print(tuple->second);
printf(")");
} else {
runtime_error("Print for kind %s not implemented", res->type);
}

return make_result_t(NULL, "Void");
Expand All @@ -119,6 +136,8 @@ char *as_str(result_t *result) {
return data;
} else if (match(result->type, "Str")) {
return (char *)result->value;
} else {
runtime_error("Cannot convert %s to string", result->type);
}
}

Expand Down Expand Up @@ -152,6 +171,8 @@ result_t *eval_binary(binary_t *binary) {
strcat(result, right_str);

return make_result_t((void *)result, "Str");
} else {
runtime_error("Cannot add %s and %s", left->type, right->type);
}
} else if (match(binary->op, "Sub")) {
int *buff = malloc(sizeof(int));
Expand Down Expand Up @@ -237,6 +258,33 @@ result_t *eval_binary(binary_t *binary) {
*buff = *(bool *)left->value || *(bool *)right->value;

return make_result_t((void *)buff, "Bool");
} else {
runtime_error("Unknown binary operator %s", binary->op);
}
}

void print_stack_variables() {
int stack_size = stack_len(stack);

if (current_stack->variables != NULL) {
result_map_t *variables = current_stack->variables;

while (variables != NULL) {
printf("[%d] Variable -> %s = %d\n", stack_size, variables->key,
*(int *)variables->value->value);

variables = variables->next;
}
}

if (current_stack->functions != NULL) {
term_map_t *functions = current_stack->functions;

while (functions != NULL) {
printf("[%d] Function -> %s\n", stack_size, functions->key);

functions = functions->next;
}
}
}

Expand All @@ -246,6 +294,8 @@ void set_current_stack() {
while (current_stack->next != NULL) {
current_stack = current_stack->next;
}

// print_stack_variables();
}

void add_stack() {
Expand Down Expand Up @@ -276,8 +326,12 @@ void push_variable(const char *key, result_t *value) {
}

void push_function(const char *key, term_t *value) {
current_stack->functions =
term_map_add(current_stack->functions, make_term_map_t(key, value));
if (stack == NULL) {
stack = make_stack_t();
}

stack->functions =
term_map_add(stack->functions, make_term_map_t(key, value));
}

void clean() {
Expand All @@ -287,20 +341,7 @@ void clean() {
}

function_t *lookup_function(const char *name) {
return (function_t *)lookup_term(current_stack->functions, name);
}

void print_stack_variables() {
if (current_stack->variables != NULL) {
result_map_t *variables = stack->variables;

while (variables != NULL) {
printf("Variable -> %s = %d\n", variables->key,
*(int *)variables->value->value);

variables = variables->next;
}
}
return (function_t *)lookup_term(stack->functions, name);
}

result_t *eval(term_t *root) {
Expand Down Expand Up @@ -349,7 +390,7 @@ result_t *eval(term_t *root) {

result_t *condition = eval(if_term->condition);

if (*(int *)condition->value) {
if (*(bool *)condition->value) {
return eval(if_term->then);
} else {
return eval(if_term->otherwise);
Expand Down Expand Up @@ -399,15 +440,31 @@ result_t *eval(term_t *root) {
runtime_error("Wrong number of arguments");
}

add_stack();
variable_t **variables = NULL;

if (call->arguments != NULL && function->parameters != NULL) {
for (int i = 0; i < len(call->arguments); i++) {
const char *parameter = function->parameters[i]->text;
size_t length = call->arguments->length;

variables = malloc(sizeof(variable_t *) * length);

parameter_t **parameters =
(parameter_t **)function->parameters->values;
term_t **arguments = (term_t **)call->arguments->values;

result_t *result = eval(call->arguments[i]);
for (int i = 0; i < length; i++) {
const char *parameter = parameters[i]->text;

result_t *result = eval(arguments[i]);

variables[i] = make_variable_t(parameter, result);
}
}

add_stack();

push_variable(parameter, result);
if (call->arguments != NULL) {
for (int i = 0; i < call->arguments->length; i++) {
push_variable(variables[i]->key, variables[i]->value);
}
}

Expand Down
22 changes: 18 additions & 4 deletions src/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
#define alloc(t) malloc(sizeof(t))
#define len(a) sizeof(a) / sizeof(a[0])

typedef struct {
size_t length;
void **values;
} array_t;

typedef struct {
void *value;
const char *type;
Expand Down Expand Up @@ -90,16 +95,21 @@ typedef struct {

typedef struct {
const char *kind;
parameter_t **parameters;
array_t *parameters;
term_t *value;
} function_t;

typedef struct {
const char *kind;
term_t *callee;
term_t **arguments;
array_t *arguments;
} call_t;

typedef struct {
const char *key;
result_t *value;
} variable_t;

result_t *make_result_t(void *value, const char *type);
print_t *make_print_t(term_t *value);
str_t *make_str_t(const char *value);
Expand All @@ -114,8 +124,10 @@ if_t *make_if_t(term_t *condition, term_t *then, term_t *otherwise);
parameter_t *make_parameter_t(const char *text);
let_t *make_let_t(parameter_t *name, term_t *value, term_t *next);
var_t *make_var_t(const char *text);
function_t *make_function_t(parameter_t **parameters, term_t *value);
call_t *make_call_t(term_t *callee, term_t **arguments);
function_t *make_function_t(array_t *parameters, term_t *value);
call_t *make_call_t(term_t *callee, array_t *arguments);
variable_t *make_variable_t(const char *key, result_t *value);
array_t *make_array_t(size_t length, void **values);
void free_term_t(term_t *term);
void free_result_t(result_t *result);
void free_print_t(print_t *print);
Expand All @@ -134,6 +146,8 @@ void free_var_t(var_t *var);
void free_function_t(function_t *function);
void free_call_t(call_t *call);
void clean();
void free_variable_t(variable_t *variable);
void free_array_t(array_t *array);

void runtime_error(const char *message, ...);

Expand Down
Loading

0 comments on commit a125754

Please sign in to comment.