Skip to content

Commit

Permalink
Merge pull request #1 from giancarlopro/fix-stack
Browse files Browse the repository at this point in the history
fix stack to allow closures and fix print to return values
  • Loading branch information
giancarlopro authored Sep 16, 2023
2 parents 91b255f + 89d07b9 commit 936d507
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 66 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/run_rinha_samples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ name: Docker Build and Run
on:
push:
branches:
- main # or whichever branch you want this to run on
- main
pull_request:
branches:
- main

jobs:
build_and_run:
Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ ifndef CFLAGS
LDFLAGS=-L/vcpkg/installed/x64-linux/lib
endif

interpreter: src/stack.c src/error.c src/interpreter.c src/alloc.c src/main.c
gcc $(CFLAGS) $(LDFLAGS) -o build/interpreter src/stack.c src/error.c src/interpreter.c src/alloc.c src/main.c -ljson-c
interpreter: src/output.c src/stack.c src/error.c src/interpreter.c src/alloc.c src/main.c
gcc $(CFLAGS) $(LDFLAGS) -o build/interpreter src/output.c src/stack.c src/error.c src/interpreter.c src/alloc.c src/main.c -ljson-c

test: src/stack.c src/error.c src/interpreter.c src/alloc.c tests/test_interpreter.c
gcc $(CFLAGS) $(LDFLAGS) -g -o build/test_interpreter src/stack.c src/error.c src/interpreter.c src/alloc.c tests/test_interpreter.c -ljson-c
test: src/output.c src/stack.c src/error.c src/interpreter.c src/alloc.c tests/test_interpreter.c
gcc $(CFLAGS) $(LDFLAGS) -g -o build/test_interpreter src/output.c src/stack.c src/error.c src/interpreter.c src/alloc.c tests/test_interpreter.c -ljson-c

all: interpreter test
default: interpreter
97 changes: 51 additions & 46 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <string.h>

stack_t *stack = NULL;
stack_t *current_stack = NULL;

term_t *parse_expression(json_object *expression) {
if (expression == NULL) {
Expand Down Expand Up @@ -104,34 +103,34 @@ result_t *print(term_t *root) {
result_t *res = eval(root);

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

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

return make_result_t(NULL, "Void");
return res;
}

char *as_str(result_t *result) {
if (match(result->type, "Int")) {
char *data = malloc(20);
char *data = malloc(100);
sprintf(data, "%d", *(int *)result->value);
return data;
} else if (match(result->type, "Str")) {
Expand Down Expand Up @@ -263,11 +262,12 @@ result_t *eval_binary(binary_t *binary) {
}
}

/** debug only function */
void print_stack_variables() {
int stack_size = stack_len(stack);

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

while (variables != NULL) {
printf("[%d] Variable -> %s = %d\n", stack_size, variables->key,
Expand All @@ -277,8 +277,8 @@ void print_stack_variables() {
}
}

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

while (functions != NULL) {
printf("[%d] Function -> %s\n", stack_size, functions->key);
Expand All @@ -288,69 +288,74 @@ void print_stack_variables() {
}
}

void set_current_stack() {
current_stack = stack;

while (current_stack->next != NULL) {
current_stack = current_stack->next;
}

// print_stack_variables();
}

void add_stack() {
stack_t *new_stack = make_stack_t();

stack = stack_add(stack, new_stack);

set_current_stack();
}

void pop_stack() {
stack_t *current = stack;
stack_t *previous = NULL;

while (current->next != NULL) {
previous = current;
current = current->next;
}

previous->next = NULL;

set_current_stack();
stack = stack->parent;
stack->next = NULL;
}

void push_variable(const char *key, result_t *value) {
current_stack->variables =
result_map_add(current_stack->variables, make_result_map_t(key, value));
stack->variables =
result_map_add(stack->variables, make_result_map_t(key, value));
}

void push_function(const char *key, term_t *value) {
if (stack == NULL) {
stack = make_stack_t();
}

stack->functions =
term_map_add(stack->functions, make_term_map_t(key, value));
stack_t *root = stack;

while (root->parent != NULL) {
root = root->parent;
}

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

void clean() {
free_stack_t(stack);
stack = NULL;
current_stack = NULL;
}

function_t *lookup_function(const char *name) {
return (function_t *)lookup_term(stack->functions, name);
stack_t *root = stack;

while (root->parent != NULL) {
root = root->parent;
}

return (function_t *)lookup_term(root->functions, name);
}

result_t *lookup_variable(const char *name) {
stack_t *root = stack;
result_t *result = NULL;

do {
result = lookup_result(root->variables, name);

if (result != NULL) {
return result;
}

root = root->parent;
} while (root != NULL);

return NULL;
}

result_t *eval(term_t *root) {
if (stack == NULL) {
stack = make_stack_t();
}

set_current_stack();

if (match(root->kind, "Print")) {
return print((term_t *)root->value);
} else if (match(root->kind, "Str") || match(root->kind, "Int") ||
Expand Down Expand Up @@ -414,7 +419,7 @@ result_t *eval(term_t *root) {
} else if (match(root->kind, "Var")) {
var_t *var = (var_t *)root;

result_t *result = lookup_result(current_stack->variables, var->text);
result_t *result = lookup_variable(var->text);

if (result == NULL) {
runtime_error("Unknown variable %s", var->text);
Expand Down
5 changes: 5 additions & 0 deletions src/interpreter.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <json-c/json.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -168,6 +169,7 @@ typedef struct term_map_t {

typedef struct stack_t {
struct stack_t *next;
struct stack_t *parent;
result_map_t *variables;
term_map_t *functions;
} stack_t;
Expand All @@ -185,3 +187,6 @@ stack_t *stack_add(stack_t *stack, stack_t *value);
result_map_t *result_map_add(result_map_t *map, result_map_t *value);
result_map_t *result_map_replace(result_map_t *map, result_map_t *value);
term_map_t *term_map_add(term_map_t *map, term_map_t *value);

void printf_c(const char *fmt, ...);
void set_interpreter_stdout(FILE *stdout);
18 changes: 18 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "interpreter.h"

FILE *program_stdout = NULL;

void printf_c(const char *fmt, ...) {
if (program_stdout == NULL) {
program_stdout = stdout;
}

va_list args;
va_start(args, fmt);

vfprintf(program_stdout, fmt, args);

va_end(args);
}

void set_interpreter_stdout(FILE *stdout) { program_stdout = stdout; }
22 changes: 8 additions & 14 deletions src/stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void free_term_map_t(term_map_t *term_map) {
stack_t *make_stack_t() {
stack_t *stack = malloc(sizeof(stack_t));

stack->next = NULL;
stack->parent = NULL;
stack->variables = NULL;
stack->functions = NULL;

Expand All @@ -55,8 +55,8 @@ stack_t *make_stack_t() {
void free_stack_t(stack_t *stack) {
if (stack == NULL) return;

if (stack->next != NULL) {
free_stack_t(stack->next);
if (stack->parent != NULL) {
free_stack_t(stack->parent);
}

free_result_map_t(stack->variables);
Expand Down Expand Up @@ -85,19 +85,13 @@ result_t *lookup_result(result_map_t *map, const char *key) {
}

stack_t *stack_add(stack_t *stack, stack_t *value) {
if (stack == NULL) {
return value;
}

stack_t *current = stack;

while (current->next != NULL) {
current = current->next;
}
if (stack == NULL) return value;
if (value == NULL) return stack;

current->next = value;
value->parent = stack;
stack->next = value;

return stack;
return value;
}

result_map_t *result_map_add(result_map_t *map, result_map_t *value) {
Expand Down
39 changes: 38 additions & 1 deletion tests/test_interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,40 @@ static char* test_eval_let_call_function_no_params() {
term_t* term = parse_expression(expression);
result_t* res = eval(term);

mu_assert("error, res->type != Int", match(res->type, "Void"));
mu_assert("error, res->type != Int", match(res->type, "Int"));
mu_assert("error, res->value != 10", (*(int*)res->value) == 10);

return 0;
}

static char* test_closure_works() {
function_t* function = make_function_t(NULL, (term_t*)make_var_t("x"));

let_t* let = make_let_t(
make_parameter_t("x"), (term_t*)make_int_t(1),
(term_t*)make_let_t(
make_parameter_t("func"), (term_t*)function,
(term_t*)make_call_t((term_t*)make_var_t("func"), NULL)));

result_t* res = eval((term_t*)let);

mu_assert("error, res->type != Int", match(res->type, "Int"));
mu_assert("error, res->value != 1", (*(int*)res->value) == 1);

return 0;
}

static char* test_print_returns_value() {
const char* data =
"{\"kind\": \"Print\", \"value\": {\"kind\": \"Int\", \"value\": 1}}";

json_object* root = json_tokener_parse(data);

term_t* term = parse_expression(root);
result_t* res = eval(term);

mu_assert("error, res->type != Int", match(res->type, "Int"));
mu_assert("error, res->value != 1", (*(int*)res->value) == 1);

return 0;
}
Expand Down Expand Up @@ -805,10 +838,14 @@ static char* all_tests() {
mu_run_test(test_parse_function);
mu_run_test(test_parse_call);
mu_run_test(test_eval_let_call_function_no_params);
mu_run_test(test_closure_works);
mu_run_test(test_print_returns_value);
return 0;
}

int main(int argc, char** argv) {
set_interpreter_stdout(fopen("/dev/null", "w"));

char* result = all_tests();
if (result != 0) {
printf("%s\n", result);
Expand Down

0 comments on commit 936d507

Please sign in to comment.