|
|
|
@@ -24,7 +24,7 @@ proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool { |
|
|
|
case Lisp_Object_Type::Number: |
|
|
|
return n1->value.number == n2->value.number; |
|
|
|
case Lisp_Object_Type::Pair: |
|
|
|
create_error(Error_Type::Not_Yet_Implemented, n1->sourceCodeLocation); |
|
|
|
create_not_yet_implemented_error(); |
|
|
|
return false; |
|
|
|
case Lisp_Object_Type::String: |
|
|
|
return string_equal(n1->value.string, n2->value.string); |
|
|
|
@@ -51,7 +51,7 @@ proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* { |
|
|
|
} |
|
|
|
return result; |
|
|
|
} else { |
|
|
|
create_error(Error_Type::File_Not_Found, nullptr); |
|
|
|
create_generic_error("The file '%s' was not found", file_name); |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -318,9 +318,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 2) { |
|
|
|
create_error(Error_Type::Wrong_Number_Of_Arguments, arguments->sourceCodeLocation); |
|
|
|
return nullptr; |
|
|
|
try { |
|
|
|
assert(arguments_length == 2); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
@@ -342,28 +341,19 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
defun("assert", cLambda { |
|
|
|
int arguments_length; |
|
|
|
|
|
|
|
try { |
|
|
|
arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
if (is_truthy(arguments->value.pair.first, env)) |
|
|
|
return Memory::t; |
|
|
|
|
|
|
|
report_error(Error_Type::Assertion_Error); |
|
|
|
create_generic_error("Userland assertion."); |
|
|
|
return nullptr; |
|
|
|
}); |
|
|
|
defun("define", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length < 2) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length >= 2); |
|
|
|
|
|
|
|
Lisp_Object* symbol = arguments->value.pair.first; |
|
|
|
Lisp_Object* value; |
|
|
|
@@ -390,9 +380,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
|
|
|
|
Lisp_Object* real_symbol = symbol->value.pair.first; |
|
|
|
|
|
|
|
try { |
|
|
|
assert_type(real_symbol, Lisp_Object_Type::Symbol); |
|
|
|
} |
|
|
|
try assert_type(real_symbol, Lisp_Object_Type::Symbol); |
|
|
|
|
|
|
|
Lisp_Object* fake_lambda = Memory::create_lisp_object_pair( |
|
|
|
symbol ->value.pair.rest, |
|
|
|
@@ -401,17 +389,12 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
value = parse_lambda_starting_from_args(fake_lambda, env); |
|
|
|
symbol = real_symbol; |
|
|
|
} else { |
|
|
|
if (arguments_length > 2) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
if (symbol->type != Lisp_Object_Type::Symbol) { |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
} |
|
|
|
try assert(arguments_length <= 2); |
|
|
|
try assert_type(symbol, Lisp_Object_Type::Symbol); |
|
|
|
|
|
|
|
value = arguments->value.pair.rest->value.pair.first; |
|
|
|
try { |
|
|
|
value = eval_expr(value, env); |
|
|
|
} |
|
|
|
|
|
|
|
try value = eval_expr(value, env); |
|
|
|
} |
|
|
|
|
|
|
|
define_symbol(symbol, value, env); |
|
|
|
@@ -454,17 +437,14 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
// return value; |
|
|
|
// }); |
|
|
|
defun("mutate", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 2) |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 2); |
|
|
|
|
|
|
|
if (evaluated_arguments->value.pair.first->type == Lisp_Object_Type::Nil || |
|
|
|
evaluated_arguments->value.pair.first->type == Lisp_Object_Type::T || |
|
|
|
evaluated_arguments->value.pair.first->type == Lisp_Object_Type::Keyword) |
|
|
|
{ |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
create_generic_error("You cannot mutate nil, t or keywords"); |
|
|
|
} |
|
|
|
|
|
|
|
Lisp_Object* target = evaluated_arguments->value.pair.first; |
|
|
|
@@ -474,55 +454,35 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return target; |
|
|
|
}); |
|
|
|
defun("if", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 2 && arguments_length != 3) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length == 2 || arguments_length == 3); |
|
|
|
|
|
|
|
Lisp_Object* condition = arguments->value.pair.first; |
|
|
|
Lisp_Object* then_part = arguments->value.pair.rest; |
|
|
|
Lisp_Object* else_part = then_part->value.pair.rest; |
|
|
|
|
|
|
|
bool truthy; |
|
|
|
try { |
|
|
|
truthy = is_truthy(condition, env); |
|
|
|
} |
|
|
|
try truthy = is_truthy(condition, env); |
|
|
|
|
|
|
|
Lisp_Object* result; |
|
|
|
|
|
|
|
if (truthy) |
|
|
|
try{ |
|
|
|
result = eval_expr(then_part->value.pair.first, env); |
|
|
|
} |
|
|
|
try result = eval_expr(then_part->value.pair.first, env); |
|
|
|
else if (arguments_length == 3) |
|
|
|
try { |
|
|
|
result = eval_expr(else_part->value.pair.first, env); |
|
|
|
} |
|
|
|
try result = eval_expr(else_part->value.pair.first, env); |
|
|
|
else return Memory::nil; |
|
|
|
|
|
|
|
return result; |
|
|
|
}); |
|
|
|
defun("quote", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
|
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
return arguments->value.pair.first; |
|
|
|
}); |
|
|
|
defun("quasiquote", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
// print(arguments); |
|
|
|
// printf("\n"); |
|
|
|
|
|
|
|
@@ -582,107 +542,77 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
defun("and", cLambda { |
|
|
|
bool result = true; |
|
|
|
while (arguments->type != Lisp_Object_Type::Nil) { |
|
|
|
if (arguments->type != Lisp_Object_Type::Pair) { |
|
|
|
report_error(Error_Type::Ill_Formed_List); |
|
|
|
} |
|
|
|
try { |
|
|
|
result &= is_truthy(arguments->value.pair.first, env); |
|
|
|
} |
|
|
|
arguments = arguments->value.pair.rest; |
|
|
|
try assert_type(arguments, Lisp_Object_Type::Pair); |
|
|
|
try result &= is_truthy(arguments->value.pair.first, env); |
|
|
|
|
|
|
|
arguments = arguments->value.pair.rest; |
|
|
|
if (!result) return Memory::nil; |
|
|
|
} |
|
|
|
|
|
|
|
return Memory::t; |
|
|
|
}); |
|
|
|
defun("or", cLambda { |
|
|
|
bool result = false; |
|
|
|
while (arguments->type != Lisp_Object_Type::Nil) { |
|
|
|
if (arguments->type != Lisp_Object_Type::Pair) { |
|
|
|
report_error(Error_Type::Ill_Formed_List); |
|
|
|
} |
|
|
|
try { |
|
|
|
result |= is_truthy(arguments->value.pair.first, env); |
|
|
|
} |
|
|
|
arguments = arguments->value.pair.rest; |
|
|
|
try assert_type(arguments, Lisp_Object_Type::Pair); |
|
|
|
try result |= is_truthy(arguments->value.pair.first, env); |
|
|
|
|
|
|
|
arguments = arguments->value.pair.rest; |
|
|
|
if (result) return Memory::t; |
|
|
|
} |
|
|
|
|
|
|
|
return Memory::nil; |
|
|
|
}); |
|
|
|
defun("not", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
bool truthy; |
|
|
|
try { |
|
|
|
truthy = is_truthy(arguments->value.pair.first, env); |
|
|
|
} |
|
|
|
if (truthy) |
|
|
|
return Memory::nil; |
|
|
|
return Memory::t; |
|
|
|
|
|
|
|
try truthy = is_truthy(arguments->value.pair.first, env); |
|
|
|
|
|
|
|
return (truthy) ? Memory::nil : Memory::t; |
|
|
|
}); |
|
|
|
defun("while", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length >= 2); |
|
|
|
|
|
|
|
if (arguments_length < 2) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
Lisp_Object* condition_part = arguments->value.pair.first; |
|
|
|
Lisp_Object* condition; |
|
|
|
Lisp_Object* then_part = arguments->value.pair.rest; |
|
|
|
Lisp_Object* result = Memory::nil; |
|
|
|
|
|
|
|
while (true) { |
|
|
|
try { |
|
|
|
condition = eval_expr(condition_part, env); |
|
|
|
} |
|
|
|
if (condition->type == Lisp_Object_Type::Nil) { |
|
|
|
try condition = eval_expr(condition_part, env); |
|
|
|
|
|
|
|
if (condition->type == Lisp_Object_Type::Nil) |
|
|
|
break; |
|
|
|
} |
|
|
|
try { |
|
|
|
result = eval_expr(then_part->value.pair.first, env); |
|
|
|
} |
|
|
|
|
|
|
|
try result = eval_expr(then_part->value.pair.first, env); |
|
|
|
} |
|
|
|
return result; |
|
|
|
|
|
|
|
}); |
|
|
|
defun("let", cLambda { |
|
|
|
// (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); |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length >= 1); |
|
|
|
|
|
|
|
Environment* let_env = Memory::create_child_environment(env); |
|
|
|
Lisp_Object* bindings = arguments->value.pair.first; |
|
|
|
while (true) { |
|
|
|
if (bindings->type == Lisp_Object_Type::Nil) { |
|
|
|
break; |
|
|
|
} else if (bindings->type != Lisp_Object_Type::Pair) { |
|
|
|
report_error(Error_Type::Ill_Formed_Arguments); |
|
|
|
} |
|
|
|
|
|
|
|
try assert_type(bindings, Lisp_Object_Type::Pair); |
|
|
|
|
|
|
|
Lisp_Object* sym = bindings->value.pair.first->value.pair.first; |
|
|
|
if(sym->type != Lisp_Object_Type::Symbol) { |
|
|
|
report_error(Error_Type::Ill_Formed_Arguments); |
|
|
|
} |
|
|
|
|
|
|
|
try assert_type(sym, Lisp_Object_Type::Symbol); |
|
|
|
|
|
|
|
Lisp_Object* rest_sym = bindings->value.pair.first->value.pair.rest; |
|
|
|
if (rest_sym->type != Lisp_Object_Type::Pair) { |
|
|
|
report_error(Error_Type::Ill_Formed_Arguments); |
|
|
|
} |
|
|
|
if (rest_sym->value.pair.rest->type != Lisp_Object_Type::Nil) { |
|
|
|
report_error(Error_Type::Ill_Formed_Arguments); |
|
|
|
} |
|
|
|
|
|
|
|
try assert_type(rest_sym, Lisp_Object_Type::Pair); |
|
|
|
try assert_type(rest_sym->value.pair.rest, Lisp_Object_Type::Nil); |
|
|
|
|
|
|
|
Lisp_Object* value = eval_expr(rest_sym->value.pair.first, env); |
|
|
|
|
|
|
|
@@ -697,9 +627,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
arguments = arguments->value.pair.rest; |
|
|
|
|
|
|
|
Lisp_Object* evaluated_arguments; |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, let_env, &arguments_length); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, let_env, &arguments_length); |
|
|
|
|
|
|
|
if (evaluated_arguments->type == Lisp_Object_Type::Nil) |
|
|
|
return evaluated_arguments; |
|
|
|
@@ -719,56 +647,35 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
* (lambda ()) |
|
|
|
* (lambda (x d) (+ 1 2) (- 1 2) (* 1 2)) |
|
|
|
*/ |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length == 0) |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
|
|
|
|
Lisp_Object* function = parse_lambda_starting_from_args(arguments, env); |
|
|
|
// parse lambda starting from arguments |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length != 0); |
|
|
|
|
|
|
|
Lisp_Object* function = parse_lambda_starting_from_args(arguments, env, false); |
|
|
|
|
|
|
|
return function; |
|
|
|
}); |
|
|
|
defun("special-lambda", cLambda { |
|
|
|
/* |
|
|
|
* (special-lambda ()) |
|
|
|
* (special-lambda (x d) (+ 1 2) (- 1 2) (* 1 2)) |
|
|
|
*/ |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length == 0) |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length != 0); |
|
|
|
|
|
|
|
Lisp_Object* function = parse_lambda_starting_from_args(arguments, env, true); |
|
|
|
// parse lambda starting from arguments |
|
|
|
|
|
|
|
|
|
|
|
return function; |
|
|
|
}); |
|
|
|
defun("eval", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
Lisp_Object* result; |
|
|
|
try { |
|
|
|
result = eval_expr(evaluated_arguments->value.pair.first, env); |
|
|
|
} |
|
|
|
|
|
|
|
try result = eval_expr(evaluated_arguments->value.pair.first, env); |
|
|
|
|
|
|
|
return result; |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
defun("prog", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
|
|
|
|
if (evaluated_arguments->type == Lisp_Object_Type::Nil) |
|
|
|
return evaluated_arguments; |
|
|
|
@@ -784,84 +691,60 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return evaluated_arguments->value.pair.first; |
|
|
|
}); |
|
|
|
defun("list", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
return evaluated_arguments; |
|
|
|
}); |
|
|
|
defun("pair", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 2) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
return Memory::create_lisp_object_pair(evaluated_arguments->value.pair.first, evaluated_arguments->value.pair.rest->value.pair.first); |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 2); |
|
|
|
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); |
|
|
|
} |
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
if (evaluated_arguments->value.pair.first->type == Lisp_Object_Type::Nil) |
|
|
|
return Memory::nil; |
|
|
|
if (evaluated_arguments->value.pair.first->type != Lisp_Object_Type::Pair) |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
|
|
|
|
try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Pair); |
|
|
|
|
|
|
|
return evaluated_arguments->value.pair.first->value.pair.first; |
|
|
|
}); |
|
|
|
defun("rest", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
if (evaluated_arguments->value.pair.first->type == Lisp_Object_Type::Nil) |
|
|
|
return Memory::nil; |
|
|
|
if (evaluated_arguments->value.pair.first->type != Lisp_Object_Type::Pair) |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
|
|
|
|
try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Pair); |
|
|
|
|
|
|
|
return evaluated_arguments->value.pair.first->value.pair.rest; |
|
|
|
}); |
|
|
|
defun("set-type", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 2) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 2); |
|
|
|
|
|
|
|
Lisp_Object* object = evaluated_arguments->value.pair.first; |
|
|
|
Lisp_Object* type = evaluated_arguments->value.pair.rest->value.pair.first; |
|
|
|
|
|
|
|
try { |
|
|
|
assert_type(type, Lisp_Object_Type::Keyword); |
|
|
|
} |
|
|
|
try assert_type(type, Lisp_Object_Type::Keyword); |
|
|
|
|
|
|
|
evaluated_arguments->value.pair.first->userType = type; |
|
|
|
return type; |
|
|
|
}); |
|
|
|
defun("delete-type", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
evaluated_arguments->value.pair.first->userType = nullptr; |
|
|
|
return Memory::t; |
|
|
|
return Memory::t; |
|
|
|
}); |
|
|
|
defun("type", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
if (evaluated_arguments->value.pair.first->userType) { |
|
|
|
return evaluated_arguments->value.pair.first->userType; |
|
|
|
@@ -891,13 +774,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return Memory::get_or_create_lisp_object_keyword("unknown"); |
|
|
|
}); |
|
|
|
defun("info", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
print(arguments->value.pair.first); |
|
|
|
|
|
|
|
@@ -971,15 +849,9 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return Memory::nil; |
|
|
|
}); |
|
|
|
defun("show", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
if (evaluated_arguments->value.pair.first->type != Lisp_Object_Type::Function) { |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Function); |
|
|
|
|
|
|
|
puts("body:\n"); |
|
|
|
print(evaluated_arguments->value.pair.first->value.function.body); |
|
|
|
@@ -988,24 +860,16 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return Memory::nil; |
|
|
|
}); |
|
|
|
defun("print", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
print(evaluated_arguments->value.pair.first); |
|
|
|
// printf("\n"); |
|
|
|
|
|
|
|
return Memory::nil; |
|
|
|
}); |
|
|
|
defun("read", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length > 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length <= 1); |
|
|
|
|
|
|
|
if (arguments_length == 1) { |
|
|
|
Lisp_Object* prompt = evaluated_arguments->value.pair.first; |
|
|
|
@@ -1014,25 +878,22 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
/* else */ |
|
|
|
print(evaluated_arguments->value.pair.first); |
|
|
|
} |
|
|
|
|
|
|
|
// TODO(Felix): make read_line return a String* |
|
|
|
char* line = read_line(); |
|
|
|
defer { |
|
|
|
free(line); |
|
|
|
}; |
|
|
|
String* strLine = Memory::create_string(line); |
|
|
|
free(line); |
|
|
|
return Memory::create_lisp_object_string(strLine); |
|
|
|
}); |
|
|
|
defun("exit", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length > 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length <= 1); |
|
|
|
|
|
|
|
if (arguments_length == 1) { |
|
|
|
Lisp_Object* error_code = evaluated_arguments->value.pair.first; |
|
|
|
if (error_code->type != Lisp_Object_Type::Number) |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
|
|
|
|
try assert_type(error_code, Lisp_Object_Type::Number); |
|
|
|
exit((int)error_code->value.number); |
|
|
|
} |
|
|
|
exit(0); |
|
|
|
@@ -1047,13 +908,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return Memory::nil; |
|
|
|
}); |
|
|
|
defun("try", cLambda { |
|
|
|
try { |
|
|
|
arguments_length = list_length(arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 2) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try arguments_length = list_length(arguments); |
|
|
|
try assert(arguments_length == 2); |
|
|
|
|
|
|
|
Lisp_Object* try_part = arguments->value.pair.first; |
|
|
|
Lisp_Object* catch_part = arguments->value.pair.rest->value.pair.first; |
|
|
|
@@ -1069,15 +925,9 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return result; |
|
|
|
}); |
|
|
|
defun("load", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 1) |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
|
|
|
|
if (evaluated_arguments->value.pair.first->type != Lisp_Object_Type::String) |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::String); |
|
|
|
|
|
|
|
Lisp_Object* result; |
|
|
|
try { |
|
|
|
@@ -1090,17 +940,15 @@ 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 evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
|
|
|
|
if (arguments_length != 1) |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
|
|
|
|
if (evaluated_arguments->value.pair.first->type == Lisp_Object_Type::Nil || |
|
|
|
evaluated_arguments->value.pair.first->type == Lisp_Object_Type::T || |
|
|
|
evaluated_arguments->value.pair.first->type == Lisp_Object_Type::Keyword) |
|
|
|
{ |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
create_generic_error("The values of 'nil', 't', and keywords can't be copied."); |
|
|
|
} |
|
|
|
|
|
|
|
Lisp_Object* target = Memory::create_lisp_object(); |
|
|
|
@@ -1110,87 +958,54 @@ proc load_built_ins_into_environment(Environment* env) -> void { |
|
|
|
return target; |
|
|
|
}); |
|
|
|
defun("error", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
if (arguments_length != 0) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
report_error(Error_Type::Unknown_Error); |
|
|
|
// TODO(Felix): make the error function useful |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 0); |
|
|
|
create_generic_error("Userlanderror"); |
|
|
|
return nullptr; |
|
|
|
}); |
|
|
|
defun("symbol->keyword", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Symbol); |
|
|
|
|
|
|
|
Lisp_Object* source = evaluated_arguments->value.pair.first; |
|
|
|
|
|
|
|
if (source->type != Lisp_Object_Type::Symbol) { |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
} |
|
|
|
|
|
|
|
return Memory::get_or_create_lisp_object_keyword(source->value.identifier); |
|
|
|
}); |
|
|
|
defun("string->symbol", cLambda { |
|
|
|
|
|
|
|
// TODO(Felix): do some sanity checks on the string. For |
|
|
|
// example, numbers are not valid symbols. |
|
|
|
|
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::String); |
|
|
|
|
|
|
|
Lisp_Object* source = evaluated_arguments->value.pair.first; |
|
|
|
|
|
|
|
if (source->type != Lisp_Object_Type::String) { |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
} |
|
|
|
|
|
|
|
return Memory::get_or_create_lisp_object_symbol(Memory::duplicate_string(source->value.string)); |
|
|
|
}); |
|
|
|
defun("symbol->string", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length == 1); |
|
|
|
try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Symbol); |
|
|
|
|
|
|
|
Lisp_Object* source = evaluated_arguments->value.pair.first; |
|
|
|
|
|
|
|
if (source->type != Lisp_Object_Type::Symbol) { |
|
|
|
report_error(Error_Type::Type_Missmatch); |
|
|
|
} |
|
|
|
return Memory::create_lisp_object_string(Memory::duplicate_string(source->value.identifier)); |
|
|
|
}); |
|
|
|
defun("concat-strings", cLambda { |
|
|
|
try { |
|
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
} |
|
|
|
|
|
|
|
if (arguments_length < 1) { |
|
|
|
report_error(Error_Type::Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
|
try assert(arguments_length >= 1); |
|
|
|
|
|
|
|
int resulting_string_len = 0; |
|
|
|
|
|
|
|
Lisp_Object* head = evaluated_arguments; |
|
|
|
|
|
|
|
while (head->type == Lisp_Object_Type::Pair) { |
|
|
|
try { |
|
|
|
assert_type(head->value.pair.first, Lisp_Object_Type::String); |
|
|
|
} |
|
|
|
resulting_string_len += head->value.pair.first->value.string->length; |
|
|
|
try assert_type(head->value.pair.first, Lisp_Object_Type::String); |
|
|
|
|
|
|
|
resulting_string_len += head->value.pair.first->value.string->length; |
|
|
|
head = head->value.pair.rest; |
|
|
|
} |
|
|
|
|
|
|
|
|