diff --git a/.dir-locals.el b/.dir-locals.el index e82376c..78bfb35 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -18,7 +18,7 @@ (font-lock-add-keywords 'c++-mode - '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\)\\>" . + '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\|try\\|try_void\\|without_logging\\)\\>" . font-lock-keyword-face))))))) (c++-mode . ((eval . (company-clang-set-prefix "slime.h")) diff --git a/src/built_ins.cpp b/src/built_ins.cpp index 2b695e1..511a4d4 100644 --- a/src/built_ins.cpp +++ b/src/built_ins.cpp @@ -37,7 +37,7 @@ proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* { try program = Parser::parse_program(file_name, file_content); for (int i = 0; i < program->next_index; ++i) { - try result = eval_expr(program->data[i], env); + try result = eval_expr(program->data[i], env); } return result; } else { @@ -114,9 +114,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { defun("=", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); if (arguments == Memory::nil) return Memory::t; @@ -133,16 +131,12 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun(">", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); double last_number = strtod("Inf", NULL); while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); if (arguments->value.pair.first->value.number >= last_number) return Memory::nil; @@ -155,16 +149,12 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun(">=", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); double last_number = strtod("Inf", NULL); while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); if (arguments->value.pair.first->value.number > last_number) return Memory::nil; @@ -184,9 +174,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { double last_number = strtod("-Inf", NULL); while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); if (arguments->value.pair.first->value.number <= last_number) return Memory::nil; @@ -199,16 +187,12 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("<=", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); double last_number = strtod("-Inf", NULL); while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); if (arguments->value.pair.first->value.number < last_number) return Memory::nil; @@ -221,15 +205,12 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("+", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); double sum = 0; while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + sum += arguments->value.pair.first->value.number; arguments = arguments->value.pair.rest; } @@ -238,20 +219,17 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("-", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } double difference = arguments->value.pair.first->value.number; + if (arguments_length == 1) + return Memory::create_lisp_object_number(-difference); + arguments = arguments->value.pair.rest; while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); difference -= arguments->value.pair.first->value.number; arguments = arguments->value.pair.rest; @@ -260,20 +238,14 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("*", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } double product = arguments->value.pair.first->value.number; arguments = arguments->value.pair.rest; while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); product *= arguments->value.pair.first->value.number; arguments = arguments->value.pair.rest; @@ -282,20 +254,14 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("/", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } + try arguments = eval_arguments(arguments, env, &arguments_length); + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } double quotient = arguments->value.pair.first->value.number; arguments = arguments->value.pair.rest; while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); quotient /= arguments->value.pair.first->value.number; arguments = arguments->value.pair.rest; @@ -304,25 +270,15 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("**", cLambda { int arguments_length; - try { - arguments = eval_arguments(arguments, env, &arguments_length); - } - - try { - assert(arguments_length == 2); - } - - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try arguments = eval_arguments(arguments, env, &arguments_length); + try assert_arguments_length(2, arguments_length); + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); double base = arguments->value.pair.first->value.number; arguments = arguments->value.pair.rest; - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - } + try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); double exponent = arguments->value.pair.first->value.number; @@ -343,7 +299,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { defun("define", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length >= 2); + try assert_arguments_length_greater_equal(2, arguments_length); Lisp_Object* symbol = arguments->value.pair.first; Lisp_Object* value; @@ -379,7 +335,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { value = parse_lambda_starting_from_args(fake_lambda, env); symbol = real_symbol; } else { - try assert(arguments_length <= 2); + try assert_arguments_length_less_equal(2, arguments_length); try assert_type(symbol, Lisp_Object_Type::Symbol); value = arguments->value.pair.rest->value.pair.first; @@ -428,13 +384,14 @@ proc load_built_ins_into_environment(Environment* env) -> void { // }); defun("mutate", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 2); + try assert_arguments_length(2, arguments_length); if (evaluated_arguments->value.pair.first == Memory::nil || evaluated_arguments->value.pair.first == Memory::t || - Memory::get_type(evaluated_arguments->value.pair.first) == Lisp_Object_Type::Keyword) + Memory::get_type(evaluated_arguments->value.pair.first) == Lisp_Object_Type::Keyword || + Memory::get_type(evaluated_arguments->value.pair.first) == Lisp_Object_Type::Symbol) { - create_generic_error("You cannot mutate nil, t or keywords"); + create_generic_error("You cannot mutate nil, t, keywords or symbols"); } Lisp_Object* target = evaluated_arguments->value.pair.first; @@ -445,7 +402,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("if", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length == 2 || arguments_length == 3); + try assert_arguments_length_greater_equal(2, arguments_length); + try assert_arguments_length_less_equal(3, arguments_length); Lisp_Object* condition = arguments->value.pair.first; Lisp_Object* then_part = arguments->value.pair.rest; @@ -466,12 +424,12 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("quote", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); return arguments->value.pair.first; }); defun("quasiquote", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); // print(arguments); // printf("\n"); @@ -553,7 +511,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("not", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); bool truthy; @@ -584,7 +542,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { defun("let", cLambda { // (let ((a 10)(b 20)) (body1) (body2)) try arguments_length = list_length(arguments); - try assert(arguments_length >= 1); + try assert_arguments_length_greater_equal(1, arguments_length); Environment* let_env = Memory::create_child_environment(env); Lisp_Object* bindings = arguments->value.pair.first; @@ -638,7 +596,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { * (lambda (x d) (+ 1 2) (- 1 2) (* 1 2)) */ try arguments_length = list_length(arguments); - try assert(arguments_length != 0); + try assert_arguments_length_greater_equal(1, arguments_length); Lisp_Object* function = parse_lambda_starting_from_args(arguments, env, false); @@ -646,7 +604,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("special-lambda", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length != 0); + try assert_arguments_length_greater_equal(1, arguments_length); Lisp_Object* function = parse_lambda_starting_from_args(arguments, env, true); @@ -654,7 +612,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("eval", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); Lisp_Object* result; @@ -686,14 +644,15 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("pair", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 2); + try assert_arguments_length(2, arguments_length); + return Memory::create_lisp_object_pair( evaluated_arguments->value.pair.first, evaluated_arguments->value.pair.rest->value.pair.first); }); defun("first", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); if (evaluated_arguments->value.pair.first == Memory::nil) return Memory::nil; @@ -704,7 +663,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("rest", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); if (evaluated_arguments->value.pair.first == Memory::nil) return Memory::nil; @@ -715,7 +674,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("set-type", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 2); + try assert_arguments_length(2, arguments_length); Lisp_Object* object = evaluated_arguments->value.pair.first; Lisp_Object* type = evaluated_arguments->value.pair.rest->value.pair.first; @@ -727,14 +686,14 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("delete-type", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); evaluated_arguments->value.pair.first->userType = nullptr; return Memory::t; }); defun("type", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); if (evaluated_arguments->value.pair.first->userType) { return evaluated_arguments->value.pair.first->userType; @@ -765,7 +724,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("info", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); print(arguments->value.pair.first); @@ -840,7 +799,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("show", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Function); puts("body:\n"); @@ -851,7 +810,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("print", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); print(evaluated_arguments->value.pair.first); @@ -859,13 +818,10 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("read", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length <= 1); + try assert_arguments_length_less_equal(1, arguments_length); if (arguments_length == 1) { Lisp_Object* prompt = evaluated_arguments->value.pair.first; - /* if (prompt->type == Lisp_Object_Type::String) */ - /* printf("%s", prompt->value.string->value); */ - /* else */ print(evaluated_arguments->value.pair.first); } @@ -879,7 +835,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("exit", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length <= 1); + try assert_arguments_length_less_equal(1, arguments_length); if (arguments_length == 1) { Lisp_Object* error_code = evaluated_arguments->value.pair.first; @@ -899,7 +855,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("try", cLambda { try arguments_length = list_length(arguments); - try assert(arguments_length == 2); + try assert_arguments_length(2, arguments_length); Lisp_Object* try_part = arguments->value.pair.first; Lisp_Object* catch_part = arguments->value.pair.rest->value.pair.first; @@ -908,21 +864,18 @@ proc load_built_ins_into_environment(Environment* env) -> void { result = eval_expr(try_part, env); if (Globals::error) { delete_error(); - try { - result = eval_expr(catch_part, env); - } + try result = eval_expr(catch_part, env); } return result; }); defun("load", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::String); Lisp_Object* result; - try { - result = built_in_load(evaluated_arguments->value.pair.first->value.string, env); - } + try result = built_in_load(evaluated_arguments->value.pair.first->value.string, env); + return result; }); @@ -931,7 +884,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { // TODO(Felix): if we are copying string nodes, then // shouldn't the string itself also get copied?? try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); if (evaluated_arguments->value.pair.first == Memory::nil || @@ -952,13 +905,13 @@ proc load_built_ins_into_environment(Environment* env) -> void { defun("error", cLambda { // TODO(Felix): make the error function useful try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 0); + try assert_arguments_length(0, arguments_length); create_generic_error("Userlanderror"); return nullptr; }); defun("symbol->keyword", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Symbol); Lisp_Object* source = evaluated_arguments->value.pair.first; @@ -970,7 +923,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { // example, numbers are not valid symbols. try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::String); Lisp_Object* source = evaluated_arguments->value.pair.first; @@ -979,7 +932,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("symbol->string", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length == 1); + try assert_arguments_length(1, arguments_length); try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Symbol); Lisp_Object* source = evaluated_arguments->value.pair.first; @@ -988,7 +941,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { }); defun("concat-strings", cLambda { try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); - try assert(arguments_length >= 1); + try assert_arguments_length_greater_equal(1, arguments_length); int resulting_string_len = 0; diff --git a/src/defines.cpp b/src/defines.cpp index fbd49e0..13d9e01 100644 --- a/src/defines.cpp +++ b/src/defines.cpp @@ -54,6 +54,25 @@ constexpr bool is_debug_build = false; } \ else label(body,__LINE__): + ; +#define without_logging \ + if (0) \ + label(finished,__LINE__): ; \ + else \ + for (Log_Level log_level_before = log_level;;) \ + for(log_level = Log_Level::None;;) \ + if (1) { \ + goto label(body,__LINE__); \ + } \ + else \ + while (1) \ + if (1) { \ + log_level = log_level_before; \ + goto label(finished,__LINE__); \ + } \ + else label(body,__LINE__): + + #define define_array_list(type, name) \ struct name##_Array_List { \ @@ -147,6 +166,17 @@ struct { "Wrong number of arguments: expected %d, got %d", \ expected, actual) +#define create_too_many_arguments_error(expected, actual) \ + __create_error("wrong-number-of-arguments", \ + "Wrong number of arguments: expected less or equal to %d, got %d", \ + expected, actual) + +#define create_too_few_arguments_error(expected, actual) \ + __create_error("wrong-number-of-arguments", \ + "Wrong number of arguments: expected greater or equal to %d, got %d", \ + expected, actual) + + #define assert_arguments_length(expected, actual) \ do { \ if (expected != actual) { \ @@ -154,22 +184,30 @@ struct { } \ } while(0) - -#define assert_type(_node, _type) \ +// TODO(Felix): Shouldn't it be expected > actual here +#define assert_arguments_length_less_equal(expected, actual) \ do { \ - if (Memory::get_type(_node) != _type) { \ - create_type_missmatch_error("symbol", Lisp_Object_Type_to_string(Memory::get_type(_node))); \ + if (expected < actual) { \ + create_too_many_arguments_error(expected, actual); \ } \ } while(0) -#define assert_arguments_length(expected, actual) \ +// TODO(Felix): Shouldn't it be expected < actual here +#define assert_arguments_length_greater_equal(expected, actual) \ + do { \ + if (expected > actual) { \ + create_too_few_arguments_error(expected, actual); \ + } \ + } while(0) + + +#define assert_type(_node, _type) \ do { \ - if (expexted != actual) { \ - create_wrong_number_of_arguments_error(expected, actual); \ + if (Memory::get_type(_node) != _type) { \ + create_type_missmatch_error("symbol", Lisp_Object_Type_to_string(Memory::get_type(_node))); \ } \ } while(0) - #define assert(condition) \ do { \ if (!(condition)) { \ diff --git a/src/testing.cpp b/src/testing.cpp index aaf7884..7197b45 100644 --- a/src/testing.cpp +++ b/src/testing.cpp @@ -426,7 +426,10 @@ proc test_built_in_type() -> testresult { // trying to set invalid user type char exp_string3[] = "(prog (set-type a \"wrong tpye\")(type a))"; expression = Parser::parse_single_expression(exp_string3); - result = eval_expr(expression, env); + + without_logging { + result = eval_expr(expression, env); + } assert_error(); delete_error(); @@ -498,12 +501,6 @@ proc test_file(const char* file) -> testresult { } proc run_all_tests() -> bool { - Log_Level log_level_before = log_level; - log_level = Log_Level::None; - defer { - log_level = log_level_before; - }; - Memory::init(4096 * 2, 4096 * 16); Parser::init(Memory::create_built_ins_environment());