Macros actually working

This commit is contained in:
FelixBrendel
2018-10-27 15:57:45 +02:00
parent 65b97fe535
commit 5aa92062c3
15 changed files with 693 additions and 192 deletions
+39 -30
View File
@@ -125,6 +125,9 @@ typedef enum {
Built_In_Rest,
Built_In_Load,
Built_In_Define,
Built_In_Let,
Built_In_Macro_Define,
Built_In_Breakpoint,
Built_In_Mutate,
Built_In_Lambda,
Built_In_Macro,
@@ -147,6 +150,8 @@ char* Built_In_Name_to_string(Built_In_Name name) {
case Built_In_Addition: return "+";
case Built_In_And: return "and";
case Built_In_Define: return "define";
case Built_In_Macro_Define: return "macro-define";
case Built_In_Breakpoint: return "breakpoint";
case Built_In_Division: return "/";
case Built_In_Equal: return "=";
case Built_In_Eval: return "eval";
@@ -157,6 +162,7 @@ char* Built_In_Name_to_string(Built_In_Name name) {
case Built_In_If: return "if";
case Built_In_Info: return "info";
case Built_In_Lambda: return "lambda";
case Built_In_Let: return "let";
case Built_In_Less: return "<";
case Built_In_Less_Equal: return "<=";
case Built_In_List: return "list";
@@ -248,36 +254,39 @@ Ast_Node* create_ast_node_keyword(char* keyword) {
Ast_Node* create_ast_node_built_in_function(char* name) {
Built_In_Name type;
if (string_equal(name, "+")) type = Built_In_Addition;
else if (string_equal(name, "-")) type = Built_In_Subtraction;
else if (string_equal(name, "*")) type = Built_In_Multiplication;
else if (string_equal(name, "/")) type = Built_In_Division;
else if (string_equal(name, "=")) type = Built_In_Equal;
else if (string_equal(name, ">")) type = Built_In_Greater;
else if (string_equal(name, ">=")) type = Built_In_Greater_Equal;
else if (string_equal(name, "<")) type = Built_In_Less;
else if (string_equal(name, "<=")) type = Built_In_Less_Equal;
else if (string_equal(name, "if")) type = Built_In_If;
else if (string_equal(name, "and")) type = Built_In_And;
else if (string_equal(name, "or")) type = Built_In_Or;
else if (string_equal(name, "not")) type = Built_In_Not;
else if (string_equal(name, "pair")) type = Built_In_Pair;
else if (string_equal(name, "first")) type = Built_In_First;
else if (string_equal(name, "rest")) type = Built_In_Rest;
else if (string_equal(name, "load")) type = Built_In_Load;
else if (string_equal(name, "define")) type = Built_In_Define;
else if (string_equal(name, "mutate")) type = Built_In_Mutate;
else if (string_equal(name, "lambda")) type = Built_In_Lambda;
else if (string_equal(name, "macro")) type = Built_In_Macro;
else if (string_equal(name, "eval")) type = Built_In_Eval;
else if (string_equal(name, "quote")) type = Built_In_Quote;
else if (string_equal(name, "prog")) type = Built_In_Prog;
else if (string_equal(name, "list")) type = Built_In_List;
else if (string_equal(name, "print")) type = Built_In_Print;
else if (string_equal(name, "read")) type = Built_In_Read;
else if (string_equal(name, "info")) type = Built_In_Info;
else if (string_equal(name, "type")) type = Built_In_Type;
else if (string_equal(name, "exit")) type = Built_In_Exit;
if (string_equal(name, "+")) type = Built_In_Addition;
else if (string_equal(name, "-")) type = Built_In_Subtraction;
else if (string_equal(name, "*")) type = Built_In_Multiplication;
else if (string_equal(name, "/")) type = Built_In_Division;
else if (string_equal(name, "=")) type = Built_In_Equal;
else if (string_equal(name, ">")) type = Built_In_Greater;
else if (string_equal(name, ">=")) type = Built_In_Greater_Equal;
else if (string_equal(name, "<")) type = Built_In_Less;
else if (string_equal(name, "<=")) type = Built_In_Less_Equal;
else if (string_equal(name, "if")) type = Built_In_If;
else if (string_equal(name, "and")) type = Built_In_And;
else if (string_equal(name, "or")) type = Built_In_Or;
else if (string_equal(name, "not")) type = Built_In_Not;
else if (string_equal(name, "pair")) type = Built_In_Pair;
else if (string_equal(name, "first")) type = Built_In_First;
else if (string_equal(name, "rest")) type = Built_In_Rest;
else if (string_equal(name, "load")) type = Built_In_Load;
else if (string_equal(name, "let")) type = Built_In_Let;
else if (string_equal(name, "define")) type = Built_In_Define;
else if (string_equal(name, "macro-define")) type = Built_In_Macro_Define;
else if (string_equal(name, "breakpoint")) type = Built_In_Breakpoint;
else if (string_equal(name, "mutate")) type = Built_In_Mutate;
else if (string_equal(name, "lambda")) type = Built_In_Lambda;
else if (string_equal(name, "macro")) type = Built_In_Macro;
else if (string_equal(name, "eval")) type = Built_In_Eval;
else if (string_equal(name, "quote")) type = Built_In_Quote;
else if (string_equal(name, "prog")) type = Built_In_Prog;
else if (string_equal(name, "list")) type = Built_In_List;
else if (string_equal(name, "print")) type = Built_In_Print;
else if (string_equal(name, "read")) type = Built_In_Read;
else if (string_equal(name, "info")) type = Built_In_Info;
else if (string_equal(name, "type")) type = Built_In_Type;
else if (string_equal(name, "exit")) type = Built_In_Exit;
else return nullptr;
Ast_Node* node = new(Ast_Node);
+72
View File
@@ -56,6 +56,78 @@ Ast_Node* built_in_equals(Ast_Node* operands) {
return create_ast_node_number(1);
}
Ast_Node* built_in_greater(Ast_Node* operands) {
double last_number = strtod("Inf", NULL);
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
if (operands->value.pair->first->value.number->value >= last_number)
return create_ast_node_nil();
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}
return create_ast_node_number(1);
}
Ast_Node* built_in_greater_equal(Ast_Node* operands) {
double last_number = strtod("Inf", NULL);
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
if (operands->value.pair->first->value.number->value > last_number)
return create_ast_node_nil();
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}
return create_ast_node_number(1);
}
Ast_Node* built_in_less(Ast_Node* operands) {
double last_number = strtod("-Inf", NULL);
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
if (operands->value.pair->first->value.number->value <= last_number)
return create_ast_node_nil();
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}
return create_ast_node_number(1);
}
Ast_Node* built_in_less_equal(Ast_Node* operands) {
double last_number = strtod("-Inf", NULL);
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
if (operands->value.pair->first->value.number->value < last_number)
return create_ast_node_nil();
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}
return create_ast_node_number(1);
}
Ast_Node* built_in_add(Ast_Node* operands) {
double sum = 0;
while (operands->type == Ast_Node_Type_Pair) {
+123 -10
View File
@@ -1,6 +1,13 @@
typedef enum {
Environment_Type_Let,
Environment_Type_Lambda,
Environment_Type_Macro,
} Environment_Type;
struct Environment {
struct Environment* parent;
Environment_Type type;
int capacity;
int next_index;
// TODO(Felix): Use a hashmap here.
@@ -10,12 +17,12 @@ struct Environment {
typedef struct Environment Environment;
Environment* create_child_environment(Environment* parent) {
Environment* create_child_environment(Environment* parent, Environment_Type type) {
Environment* env = new(Environment);
int start_capacity = 16;
env->type = type;
env->parent = parent;
env->capacity = start_capacity;
env->next_index = 0;
@@ -25,11 +32,20 @@ Environment* create_child_environment(Environment* parent) {
return env;
}
Environment* create_empty_environment() {
return create_child_environment(nullptr);
Environment* create_empty_environment(Environment_Type type) {
return create_child_environment(nullptr, type);
}
void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
if (env->type == Environment_Type_Macro) {
// NOTE(Felix): we know we have a parent because every
// environment has a parent except the top level environment.
// However the top level environment is not a let-environment,
// so we would not land here
define_symbol(symbol, value, env->parent);
return;
}
// NOTE(Felix): right now we are simply adding the symol at the
// back of the list without checking if it already exists but are
// also searching for thesymbol from the back, so we will find the
@@ -47,19 +63,116 @@ void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
++env->next_index;
}
Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
void define_macro_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
if (!env->type == Environment_Type_Macro) {
create_error(Error_Type_Unknown_Error, symbol);
return;
}
env->type = Environment_Type_Lambda;
define_symbol(symbol, value, env);
env->type = Environment_Type_Macro;
}
void print_environment(Environment* env);
Ast_Node* lookup_symbol_in_this_envt(Symbol* sym, Environment* env) {
for (int i = env->next_index - 1; i >= 0; --i)
if (string_equal(env->keys[i], sym->identifier))
return env->values[i];
return nullptr;
}
if (env->parent)
return lookup_symbol(sym, env->parent);
Ast_Node* lookup_symbol_from_lambda_env(Symbol* sym, Environment* env) {
Ast_Node* result;
do {
if (env->type != Environment_Type_Lambda) {
result = lookup_symbol_in_this_envt(sym, env);
if (result) return result;
}
env = env->parent;
} while (env);
return nullptr;
}
Ast_Node* built_in = create_ast_node_built_in_function(sym->identifier);
if (built_in)
return built_in;
Ast_Node* lookup_symbol_from_let_or_macro_env(Symbol* sym, Environment* env) {
Ast_Node* result;
do {
result = lookup_symbol_in_this_envt(sym, env);
if (result) return result;
if (env->type == Environment_Type_Lambda)
break;
env = env->parent;
} while (env);
if (env) {
do {
if (env->type != Environment_Type_Lambda) {
result = lookup_symbol_in_this_envt(sym, env);
if (result) return result;
}
env = env->parent;
} while (env);
}
return nullptr;
}
Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
// first check current environment
Ast_Node* result;
result = lookup_symbol_in_this_envt(sym, env);
if (result)
return result;
if (env->parent) {
if (env->type == Environment_Type_Lambda) {
result = lookup_symbol_from_lambda_env(sym, env->parent);
} else {
result = lookup_symbol_from_let_or_macro_env(sym, env->parent);
}
if (result)
return result;
}
result = create_ast_node_built_in_function(sym->identifier);
if (result)
return result;
create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil());
printf("%s\n", sym->identifier);
return nullptr;
}
void print_indent(int indent) {
for (int i = 0; i < indent; ++i) {
printf(" ");
}
}
void print_environment_indent(Environment* env, int indent) {
for (int i = 0; i < env->next_index; ++i) {
print_indent(indent);
printf("%s -> ", env->keys[i]);
print(env->values[i]);
printf("\n");
}
if (env->parent) {
print_indent(indent);
printf("parent");
if (env->parent->type == Environment_Type_Lambda)
printf(" (lambda)");
else if (env->parent->type == Environment_Type_Macro)
printf(" (macro)");
else if (env->parent->type == Environment_Type_Let)
printf(" (let)");
printf(":\n");
print_environment_indent(env->parent, indent+4);
}
}
void print_environment(Environment* env) {
printf("\n=== Environment ===\n");
print_environment_indent(env, 0);
}
+1 -1
View File
@@ -31,7 +31,7 @@ void delete_error() {
void create_error(Error_Type type, Ast_Node* location) {
delete_error();
error = new(Error);
error->type = type;
error->location = location;
+121 -7
View File
@@ -1,7 +1,12 @@
Ast_Node* eval_expr(Ast_Node* node, Environment* env);
Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, Environment* parent) {
Environment* new_env = create_child_environment(parent);
// NOTE(Felix): if it is a macro, we will set it later, so we can
// use the default "define_symbol" method here instead of
// switching between "define_symbol" and "define_macro_symbol" all
// the time
Environment* new_env = create_child_environment(parent, Environment_Type_Lambda);
// positional arguments
for (int i = 0; i < function->positional_arguments->next_index; ++i) {
@@ -137,10 +142,16 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E
eval_time:
Ast_Node* result;
// don't have to check every time if it is macro environment or
// not
if (function->is_macro)
new_env->type = Environment_Type_Macro;
try {
result = eval_expr(function->body, new_env);
}
free(new_env);
return result;
}
@@ -354,7 +365,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
create_error(_type, node); \
return nullptr; \
}
if (error)
return nullptr;
@@ -392,6 +403,13 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
// check for special form
if (operator->type == Ast_Node_Type_Built_In_Function) {
switch (operator->value.built_in_function->type) {
case Built_In_Breakpoint: {
print_environment(env);
#ifdef _DEBUG
__debugbreak();
#endif
return create_ast_node_nil();
}
case Built_In_Macro:
case Built_In_Lambda: {
/*
@@ -420,6 +438,10 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
try {
parse_argument_list(arguments->value.pair->first, function);
}
} else {
function->positional_arguments = create_positional_argument_list(1);
function->keyword_arguments = create_keyword_argument_list(1);
function->rest_argument = nullptr;
}
arguments = arguments->value.pair->rest;
@@ -440,6 +462,63 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
ret->value.function = function;
return ret;
}
case Built_In_Let: {
// (let ((a 10)(b 20)) (body1) (body2))
try {
arguments_length = list_length(arguments);
}
if (arguments_length < 1)
report_error(Error_Type_Wrong_Number_Of_Arguments);
Environment* let_env = create_child_environment(env, Environment_Type_Let);
Ast_Node* bindings = arguments->value.pair->first;
while (true) {
if (bindings->type == Ast_Node_Type_Nil) {
break;
} else if (bindings->type != Ast_Node_Type_Pair) {
report_error(Error_Type_Ill_Formed_Arguments);
}
Ast_Node* sym = bindings->value.pair->first->value.pair->first;
if(sym->type != Ast_Node_Type_Symbol) {
report_error(Error_Type_Ill_Formed_Arguments);
}
Ast_Node* rest_sym = bindings->value.pair->first->value.pair->rest;
if (rest_sym->type != Ast_Node_Type_Pair) {
report_error(Error_Type_Ill_Formed_Arguments);
}
if (rest_sym->value.pair->rest->type != Ast_Node_Type_Nil) {
report_error(Error_Type_Ill_Formed_Arguments);
}
Ast_Node* value = rest_sym->value.pair->first;
define_symbol(sym, value, let_env);
bindings = bindings->value.pair->rest;
}
arguments = arguments->value.pair->rest;
Ast_Node* evaluated_arguments;
try {
evaluated_arguments = eval_arguments(arguments, let_env, &arguments_length);
}
if (evaluated_arguments->type == Ast_Node_Type_Nil)
return evaluated_arguments;
// skip to the last evaluated operand and return it,
// we use eval_arguments here instead of doing it
// manually, because we want to increase code reuse,
// but at the cost that we have to find the end of the
// list again
while (evaluated_arguments->value.pair->rest->type == Ast_Node_Type_Pair) {
evaluated_arguments = evaluated_arguments->value.pair->rest;
}
return evaluated_arguments->value.pair->first;
}
case Built_In_And: {
bool result = true;
while (arguments->type != Ast_Node_Type_Nil) {
@@ -522,6 +601,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}
return arguments->value.pair->first;
}
case Built_In_Macro_Define:
case Built_In_Define: {
try {
arguments_length = list_length(arguments);
@@ -531,15 +611,32 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}
Ast_Node* symbol = arguments->value.pair->first;
if (symbol->type != Ast_Node_Type_Symbol)
if (symbol->type == Ast_Node_Type_Pair) {
try {
symbol = eval_expr(symbol, env);
}
}
if (symbol->type != Ast_Node_Type_Symbol) {
report_error(Error_Type_Type_Missmatch);
}
Ast_Node* value = arguments->value.pair->rest->value.pair->first;
/* print(value); */
try {
value = eval_expr(value, env);
}
/* print(value); */
define_symbol(symbol, value, env);
if (operator->value.built_in_function->type == Built_In_Macro_Define) {
/* printf("Defining %s in the macro env to be ", symbol->value.symbol->identifier); */
/* print(value); */
define_macro_symbol(symbol, value, env);
}
else
define_symbol(symbol, value, env);
return value;
}
@@ -569,6 +666,18 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
case Built_In_Equal: {
return built_in_equals(evaluated_arguments);
}
case Built_In_Greater: {
return built_in_greater(evaluated_arguments);
}
case Built_In_Greater_Equal: {
return built_in_greater_equal(evaluated_arguments);
}
case Built_In_Less: {
return built_in_less(evaluated_arguments);
}
case Built_In_Less_Equal: {
return built_in_less_equal(evaluated_arguments);
}
case Built_In_Mutate: {
if (arguments_length != 2)
report_error(Error_Type_Wrong_Number_Of_Arguments);
@@ -685,7 +794,11 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
Ast_Node_Type type = evaluated_arguments->value.pair->first->type;
switch (type) {
case Ast_Node_Type_Built_In_Function: return create_ast_node_keyword("built-in-function");
case Ast_Node_Type_Function: return create_ast_node_keyword("dynamic-function");
case Ast_Node_Type_Function: {
if (evaluated_arguments->value.pair->first->value.function->is_macro)
return create_ast_node_keyword("dynamic-macro");
return create_ast_node_keyword("dynamic-function");
}
case Ast_Node_Type_Keyword: return create_ast_node_keyword("keyword");
case Ast_Node_Type_Nil: return create_ast_node_keyword("nil");
case Ast_Node_Type_Number: return create_ast_node_keyword("number");
@@ -715,8 +828,6 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}
// assume it's lambda function and evaluate the arguments
if (operator->type == Ast_Node_Type_Function) {
if (!operator->value.function->is_macro) {
try {
@@ -732,6 +843,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}
}
default: {
#ifdef _DEBUG
__debugbreak();
#endif
report_error(Error_Type_Not_A_Function);
}
}
+2 -1
View File
@@ -103,7 +103,8 @@ char* read_entire_file (char* filename) {
/* Read the entire file into memory. */
size_t newLen = fread(fileContent, sizeof(char), bufsize, fp);
/* fileContent[bufsize-5] = '\0'; */
fileContent[newLen] = '\0';
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
}
+4 -2
View File
@@ -68,8 +68,10 @@ void print(Ast_Node* node) {
printf(":%s", node->value.keyword->identifier);
} break;
case (Ast_Node_Type_Function): {
printf("[lambda]");
/* print(node->value.function->body); */
if (node->value.function->is_macro)
printf("[macro]");
else
printf("[lambda]");
} break;
case (Ast_Node_Type_Built_In_Function): {
printf("[built-in-function %s]", Built_In_Name_to_string(node->value.built_in_function->type));
+2 -2
View File
@@ -23,7 +23,7 @@ int interprete_file (char* file_content) {
log_error();
return 1;
}
Environment* env = create_empty_environment();
Environment* env = create_empty_environment(Environment_Type_Let);
built_in_load("pre.slime", env);
if (error) {
@@ -46,7 +46,7 @@ int interprete_file (char* file_content) {
int interprete_stdin () {
printf("Welcome to the lispy interpreter.\n");
char* line;
Environment* env = create_empty_environment();
Environment* env = create_empty_environment(Environment_Type_Let);
built_in_load("pre.slime", env);
if (error) {
+6 -2
View File
@@ -27,6 +27,7 @@ void eat_comment_line(char* text, int* index_in_text) {
do {
++(*index_in_text);
} while (text[(*index_in_text)] != '\n' &&
text[(*index_in_text)] != '\r' &&
text[(*index_in_text)] != '\0');
}
@@ -34,7 +35,8 @@ void eat_whitespace(char* text, int* index_in_text) {
// skip whitespaces
while (text[(*index_in_text)] == ' ' ||
text[(*index_in_text)] == '\t' ||
text[(*index_in_text)] == '\n') {
text[(*index_in_text)] == '\n' ||
text[(*index_in_text)] == '\r') {
++(*index_in_text);
}
}
@@ -55,6 +57,7 @@ char* read_atom(char* text, int* index_in_text) {
text[*index_in_text+atom_length] != '(' &&
text[*index_in_text+atom_length] != '\0' &&
text[*index_in_text+atom_length] != '\n' &&
text[*index_in_text+atom_length] != '\r' &&
text[*index_in_text+atom_length] != '\t')
{
++atom_length;
@@ -269,7 +272,8 @@ Ast_Node_Array_List* parse_program(char* text) {
case ';':
case ' ':
case '\t':
case '\n': {
case '\n':
case '\r': {
eat_until_code(text, &index_in_text);
} break;
default:
+13 -13
View File
@@ -83,7 +83,7 @@ testresult test_eval_operands() {
char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
Ast_Node* operands = parse_single_expression(operands_string);
int operands_length;
operands = eval_arguments(operands, create_empty_environment(), &operands_length);
operands = eval_arguments(operands, create_empty_environment(Environment_Type_Let), &operands_length);
assert_no_error(error);
assert_equal_int(list_length(operands), 4);
@@ -227,7 +227,7 @@ testresult test_parse_expression() {
testresult test_built_in_add() {
char exp_string[] = "(+ 10 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -240,7 +240,7 @@ testresult test_built_in_add() {
testresult test_built_in_substract() {
char exp_string[] = "(- 10 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -254,7 +254,7 @@ testresult test_built_in_substract() {
testresult test_built_in_multiply() {
char exp_string[] = "(* 10 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -268,7 +268,7 @@ testresult test_built_in_multiply() {
testresult test_built_in_divide() {
char exp_string[] = "(/ 20 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_null(error);
assert_not_null(result);
@@ -282,7 +282,7 @@ testresult test_built_in_divide() {
testresult test_built_in_if() {
char exp_string1[] = "(if 1 4 5)";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -291,7 +291,7 @@ testresult test_built_in_if() {
char exp_string2[] = "(if () 4 5)";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());
result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -304,7 +304,7 @@ testresult test_built_in_if() {
testresult test_built_in_and() {
char exp_string1[] = "(and 1 \"asd\" 4)";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -314,7 +314,7 @@ testresult test_built_in_and() {
// a false case
char exp_string2[] = "(and () \"asd\" 4)";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());
result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -326,7 +326,7 @@ testresult test_built_in_and() {
testresult test_built_in_or() {
char exp_string1[] = "(or \"asd\" nil)";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -336,7 +336,7 @@ testresult test_built_in_or() {
// a false case
char exp_string2[] = "(or () ())";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());
result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);
@@ -349,7 +349,7 @@ testresult test_built_in_or() {
testresult test_built_in_not() {
char exp_string1[] = "(not ())";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());
Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
// a true case
assert_no_error(error);
@@ -360,7 +360,7 @@ testresult test_built_in_not() {
// a false case
char exp_string2[] = "(not \"asd xD\")";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());
result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
assert_no_error(error);
assert_not_null(result);