Parcourir la source

used assert_arguments_length for better errors

master
FelixBrendel il y a 7 ans
Parent
révision
cfa2e4e769
4 fichiers modifiés avec 117 ajouts et 129 suppressions
  1. +1
    -1
      .dir-locals.el
  2. +66
    -113
      src/built_ins.cpp
  3. +46
    -8
      src/defines.cpp
  4. +4
    -7
      src/testing.cpp

+ 1
- 1
.dir-locals.el Voir le fichier

@@ -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"))


+ 66
- 113
src/built_ins.cpp Voir le fichier

@@ -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;



+ 46
- 8
src/defines.cpp Voir le fichier

@@ -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)) { \


+ 4
- 7
src/testing.cpp Voir le fichier

@@ -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());



Chargement…
Annuler
Enregistrer