| @@ -2,4 +2,5 @@ | |||||
| /*.exe | /*.exe | ||||
| /*.ilk | /*.ilk | ||||
| /*.pdb | /*.pdb | ||||
| /.vs/ | |||||
| /.vs/ | |||||
| /vs/ | |||||
| @@ -1,7 +1,33 @@ | |||||
| @echo off | @echo off | ||||
| clang main.c -g -o lisp.exe --std=c99 || exit /b 1 | |||||
| pushd %~dp0 | |||||
| echo. | |||||
| echo --- Output Start --- | |||||
| lisp test.lsp | |||||
| echo --- Output End --- | |||||
| set exeName=lisp.exe | |||||
| set binDir=bin | |||||
| mkdir quickbuild | |||||
| pushd quickbuild | |||||
| cl^ | |||||
| ../src/main.c^ | |||||
| /Fe%exeName% /W3 /TC^ | |||||
| /nologo /EHsc /Z7^ | |||||
| /link /incremental /debug:fastlink | |||||
| if %errorlevel% == 0 ( | |||||
| echo. | |||||
| if not exist ..\%binDir% mkdir ..\%binDir% | |||||
| move %exeName% ..\%binDir%\ > NUL | |||||
| pushd ..\%binDir% | |||||
| echo ---------- Output start ---------- | |||||
| %exeName% | |||||
| echo ---------- Output end ---------- | |||||
| del %exeName% /S /Q > NUL | |||||
| popd | |||||
| ) else ( | |||||
| echo. | |||||
| echo Fucki'n 'ell | |||||
| ) | |||||
| popd | |||||
| rd quickbuild /S /Q | |||||
| popd | |||||
| @@ -1,6 +1,9 @@ | |||||
| clang main.c -g -o lisp --std=c99 || exit 1 | |||||
| mkdir quickbuild | |||||
| clang src/main.c -g -o ./quickbuild/lisp --std=c99 || exit 1 | |||||
| echo "" | echo "" | ||||
| echo "--- Output Start ---" | echo "--- Output Start ---" | ||||
| ./lisp test.lsp | |||||
| ./quickbuild/lisp | |||||
| echo "--- Output End ---" | echo "--- Output End ---" | ||||
| rm -rf quickbuild | |||||
| @@ -50,3 +50,4 @@ Ast_Node* built_in_divide(Ast_Node* operands) { | |||||
| } | } | ||||
| return create_ast_node_number(quotient); | return create_ast_node_number(quotient); | ||||
| } | } | ||||
| @@ -38,6 +38,6 @@ char* Error_Type_to_string(Error_Type type) { | |||||
| case Error_Type_Wrong_Number_Of_Arguments: return "Wrong number of arguments"; | case Error_Type_Wrong_Number_Of_Arguments: return "Wrong number of arguments"; | ||||
| case Error_Type_Type_Missmatch: return "Type Missmatch"; | case Error_Type_Type_Missmatch: return "Type Missmatch"; | ||||
| case Error_Type_Not_Yet_Implemented: return "Not yet implemented"; | case Error_Type_Not_Yet_Implemented: return "Not yet implemented"; | ||||
| case Error_Type_Unknown_Error: return "Unknown Error"; | |||||
| default: return "Unknown Error"; | |||||
| } | } | ||||
| } | } | ||||
| @@ -8,7 +8,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env); | |||||
| int is_truthy (Ast_Node* expression, Environment* env); | int is_truthy (Ast_Node* expression, Environment* env); | ||||
| int list_length(Ast_Node* node) { | int list_length(Ast_Node* node) { | ||||
| if (node->type != Ast_Node_Type_Nil) | |||||
| if (node->type == Ast_Node_Type_Nil) | |||||
| return 0; | return 0; | ||||
| if (node->type != Ast_Node_Type_Pair) { | if (node->type != Ast_Node_Type_Pair) { | ||||
| @@ -16,12 +16,16 @@ int list_length(Ast_Node* node) { | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int len = 1; | |||||
| while (1) { | |||||
| break; | |||||
| int len = 0; | |||||
| while (node->type == Ast_Node_Type_Pair) { | |||||
| ++len; | |||||
| node = node->value.pair->rest; | |||||
| if (node->type == Ast_Node_Type_Nil) | |||||
| return len; | |||||
| } | } | ||||
| return len; | |||||
| create_error(Error_Type_Ill_Formed_List, node); | |||||
| return 0; | |||||
| } | } | ||||
| void eval_operands(Ast_Node* operands, Environment* env) { | void eval_operands(Ast_Node* operands, Environment* env) { | ||||
| @@ -36,8 +40,8 @@ void eval_operands(Ast_Node* operands, Environment* env) { | |||||
| } | } | ||||
| Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | ||||
| #define report_error(_type) \ | |||||
| create_error(_type, node); \ | |||||
| #define report_error(_type) \ | |||||
| create_error(_type, node); \ | |||||
| return NULL | return NULL | ||||
| Ast_Node* ret = new(Ast_Node); | Ast_Node* ret = new(Ast_Node); | ||||
| @@ -73,8 +77,10 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||||
| eval_operands(operands, env); | eval_operands(operands, env); | ||||
| return built_in_divide(operands); | return built_in_divide(operands); | ||||
| } else if (string_equal("if", operator_name)) { | } else if (string_equal("if", operator_name)) { | ||||
| if (list_length(operands) != 3) { | |||||
| report_error(Error_Type_Wrong_Number_Of_Arguments); | |||||
| int operands_length = list_length(operands); | |||||
| if (operands_length != 2 && operands_length != 3) { | |||||
| create_error(Error_Type_Wrong_Number_Of_Arguments, operands); | |||||
| return NULL; | |||||
| } | } | ||||
| Ast_Node* condition = operands->value.pair->first; | Ast_Node* condition = operands->value.pair->first; | ||||
| @@ -83,12 +89,13 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||||
| if (is_truthy(condition, env)) | if (is_truthy(condition, env)) | ||||
| return eval_expr(then_part->value.pair->first, env); | return eval_expr(then_part->value.pair->first, env); | ||||
| else | |||||
| else if (operands_length == 3) | |||||
| return eval_expr(else_part->value.pair->first, env); | return eval_expr(else_part->value.pair->first, env); | ||||
| /* } else if (string_equal("not", operator_name)) { */ | |||||
| else return create_ast_node_nil(); | |||||
| /* } else if (string_equal("not", operator_name)) { */ | |||||
| /* } else if (string_equal("and", operator_name)) { */ | |||||
| /* } else if (string_equal("or", operator_name)) { */ | |||||
| /* } else if (string_equal("and", operator_name)) { */ | |||||
| /* } else if (string_equal("or", operator_name)) { */ | |||||
| } else { | } else { | ||||
| report_error(Error_Type_Not_Yet_Implemented); | report_error(Error_Type_Not_Yet_Implemented); | ||||
| } | } | ||||
| @@ -24,7 +24,7 @@ void log_message(Log_Level type, char* message) { | |||||
| case Log_Level_Warning: prefix = "WARNING"; break; | case Log_Level_Warning: prefix = "WARNING"; break; | ||||
| case Log_Level_Info: prefix = "INFO"; break; | case Log_Level_Info: prefix = "INFO"; break; | ||||
| case Log_Level_Debug: prefix = "DEBUG"; break; | case Log_Level_Debug: prefix = "DEBUG"; break; | ||||
| case Log_Level_None: return; | |||||
| default: return; | |||||
| } | } | ||||
| printf("%s: %s\n",prefix, message); | printf("%s: %s\n",prefix, message); | ||||
| } | } | ||||
| @@ -47,6 +47,7 @@ char* Ast_Node_Type_to_string(Ast_Node_Type type) { | |||||
| case(Ast_Node_Type_Built_In_Function): return "built-in function"; | case(Ast_Node_Type_Built_In_Function): return "built-in function"; | ||||
| case(Ast_Node_Type_Pair): return "pair"; | case(Ast_Node_Type_Pair): return "pair"; | ||||
| } | } | ||||
| return "unknown"; | |||||
| } | } | ||||
| void print(Ast_Node* node) { | void print(Ast_Node* node) { | ||||
| @@ -28,13 +28,13 @@ | |||||
| #define assert_equal_int(variable, value) \ | #define assert_equal_int(variable, value) \ | ||||
| if (variable != value) { \ | if (variable != value) { \ | ||||
| print_assert_equal_fail(variable, value, int, "%d"); \ | |||||
| print_assert_equal_fail(variable, value, size_t, "%zd"); \ | |||||
| return fail; \ | return fail; \ | ||||
| } | } | ||||
| #define assert_not_equal_int(variable, value) \ | #define assert_not_equal_int(variable, value) \ | ||||
| if (variable == value) { \ | if (variable == value) { \ | ||||
| print_assert_not_equal_fail(variable, value, int, "%d"); \ | |||||
| print_assert_not_equal_fail(variable, value, size_t, "%zd"); \ | |||||
| return fail; \ | return fail; \ | ||||
| } | } | ||||
| @@ -60,7 +60,7 @@ | |||||
| #define invoke_test(name) \ | #define invoke_test(name) \ | ||||
| printf("" #name ":"); \ | printf("" #name ":"); \ | ||||
| if (name() == pass) { \ | if (name() == pass) { \ | ||||
| for(int i = strlen(#name); i < 70; ++i) \ | |||||
| for(size_t i = strlen(#name); i < 70; ++i) \ | |||||
| printf((i%3==1)? "." : " "); \ | printf((i%3==1)? "." : " "); \ | ||||
| printf("%spassed%s\n", console_green, console_normal); \ | printf("%spassed%s\n", console_green, console_normal); \ | ||||
| } \ | } \ | ||||