diff --git a/include/lone/types.h b/include/lone/types.h index 6ed82fc2..6fadbdc5 100644 --- a/include/lone/types.h +++ b/include/lone/types.h @@ -149,7 +149,6 @@ struct lone_module { struct lone_function_flags { bool evaluate_arguments: 1; bool evaluate_result: 1; - bool variable_arguments: 1; }; struct lone_function { @@ -169,7 +168,7 @@ struct lone_primitive { struct lone_value *name; lone_primitive function; struct lone_value *closure; - struct lone_function_flags flags; /* primitives always accept variable arguments */ + struct lone_function_flags flags; }; struct lone_list { diff --git a/source/lone/lisp.c b/source/lone/lisp.c index bc2ea3b8..75a62cac 100644 --- a/source/lone/lisp.c +++ b/source/lone/lisp.c @@ -17,7 +17,7 @@ void lone_lisp_initialize(struct lone_lisp *lone, struct lone_bytes memory, size_t heap_size, void *stack, struct lone_bytes random) { - struct lone_function_flags flags = { .evaluate_arguments = 0, .evaluate_result = 0, .variable_arguments = 1 }; + struct lone_function_flags flags = { .evaluate_arguments = 0, .evaluate_result = 0 }; struct lone_value *import, *export; lone_memory_initialize(lone, memory, heap_size, stack); diff --git a/source/lone/lisp/evaluator.c b/source/lone/lisp/evaluator.c index 1f50d486..edb80233 100644 --- a/source/lone/lisp/evaluator.c +++ b/source/lone/lisp/evaluator.c @@ -120,20 +120,30 @@ static struct lone_value *lone_apply_function(struct lone_lisp *lone, struct lon { struct lone_value *new_environment = lone_table_create(lone, 16, function->function.environment), *names = function->function.arguments, *code = function->function.code, - *value = lone_nil(lone); + *value = lone_nil(lone), *current_name; /* evaluate each argument if function is configured to do so */ if (function->function.flags.evaluate_arguments) { arguments = lone_evaluate_all(lone, module, environment, arguments); } - if (function->function.flags.variable_arguments) { - if (lone_is_nil(names) || !lone_is_nil(lone_list_rest(names))) { - /* must have exactly one argument: the list of arguments */ - linux_exit(-1); - } + while (1) { + current_name = lone_list_first(names); + + if (!lone_is_nil(names) && lone_is_list(current_name)) { + /* variadic argument passing: (lambda ((arguments))) (lambda (x y (rest))) */ + + if (lone_is_nil(current_name)) { + /* no name given: (lambda (x y ())) */ linux_exit(-1); + } else if (!lone_is_nil(lone_list_rest(current_name))) { + /* too many names given: (lambda (x y (rest extra))) */ linux_exit(-1); + } else { + /* valid, set name to the list of remaining arguments */ + lone_table_set(lone, new_environment, lone_list_first(current_name), arguments); + break; + } + + } else { + /* normal argument passing: (lambda (x y)) */ - lone_table_set(lone, new_environment, lone_list_first(names), arguments); - } else { - while (1) { if (lone_is_nil(names) != lone_is_nil(arguments)) { /* argument number mismatch: ((lambda (x) x) 10 20), ((lambda (x y) y) 10) */ linux_exit(-1); } else if (lone_is_nil(names) && lone_is_nil(arguments)) { @@ -142,8 +152,7 @@ static struct lone_value *lone_apply_function(struct lone_lisp *lone, struct lon } /* valid binding, set name in environment and move on */ - - lone_table_set(lone, new_environment, lone_list_first(names), lone_list_first(arguments)); + lone_table_set(lone, new_environment, current_name, lone_list_first(arguments)); names = lone_list_rest(names); arguments = lone_list_rest(arguments); diff --git a/source/lone/modules/intrinsic/linux.c b/source/lone/modules/intrinsic/linux.c index 5133ec47..9543afd2 100644 --- a/source/lone/modules/intrinsic/linux.c +++ b/source/lone/modules/intrinsic/linux.c @@ -296,7 +296,7 @@ void lone_module_linux_initialize(struct lone_lisp *lone, int argc, char **argv, *count, *arguments, *environment, *auxiliary_vector, *primitive; - struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false, .variable_arguments = true }; + struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false }; primitive = lone_primitive_create(lone, "linux_system_call", lone_primitive_linux_system_call, linux_system_call_table, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "system-call"), primitive); diff --git a/source/lone/modules/intrinsic/list.c b/source/lone/modules/intrinsic/list.c index c4a74c66..85e10f83 100644 --- a/source/lone/modules/intrinsic/list.c +++ b/source/lone/modules/intrinsic/list.c @@ -18,7 +18,7 @@ void lone_module_list_initialize(struct lone_lisp *lone) *module = lone_module_for_name(lone, name), *primitive; - struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false, .variable_arguments = true }; + struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false }; primitive = lone_primitive_create(lone, "construct", lone_primitive_list_construct, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "construct"), primitive); diff --git a/source/lone/modules/intrinsic/lone.c b/source/lone/modules/intrinsic/lone.c index 43997e55..68c4882b 100644 --- a/source/lone/modules/intrinsic/lone.c +++ b/source/lone/modules/intrinsic/lone.c @@ -22,7 +22,7 @@ void lone_module_lone_initialize(struct lone_lisp *lone) *module = lone_module_for_name(lone, name), *primitive; - struct lone_function_flags flags = { .evaluate_arguments = false, .evaluate_result = false, .variable_arguments = true }; + struct lone_function_flags flags = { .evaluate_arguments = false, .evaluate_result = false }; primitive = lone_primitive_create(lone, "begin", lone_primitive_lone_begin, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "begin"), primitive); @@ -54,10 +54,7 @@ void lone_module_lone_initialize(struct lone_lisp *lone) primitive = lone_primitive_create(lone, "lambda_bang", lone_primitive_lone_lambda_bang, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "lambda!"), primitive); - primitive = lone_primitive_create(lone, "lambda_star", lone_primitive_lone_lambda_star, module, flags); - lone_set_and_export(lone, module, lone_intern_c_string(lone, "lambda*"), primitive); - - flags = (struct lone_function_flags) { .evaluate_arguments = true, .evaluate_result = false, .variable_arguments = true }; + flags = (struct lone_function_flags) { .evaluate_arguments = true, .evaluate_result = false }; primitive = lone_primitive_create(lone, "print", lone_primitive_lone_print, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "print"), primitive); @@ -312,7 +309,6 @@ LONE_PRIMITIVE(lone_lambda) struct lone_function_flags flags = { .evaluate_arguments = 1, .evaluate_result = 0, - .variable_arguments = 0, }; return lone_primitive_lambda_with_flags(lone, environment, arguments, flags); @@ -323,18 +319,6 @@ LONE_PRIMITIVE(lone_lambda_bang) struct lone_function_flags flags = { .evaluate_arguments = 0, .evaluate_result = 0, - .variable_arguments = 0, - }; - - return lone_primitive_lambda_with_flags(lone, environment, arguments, flags); -} - -LONE_PRIMITIVE(lone_lambda_star) -{ - struct lone_function_flags flags = { - .evaluate_arguments = 1, - .evaluate_result = 0, - .variable_arguments = 1, }; return lone_primitive_lambda_with_flags(lone, environment, arguments, flags); diff --git a/source/lone/modules/intrinsic/math.c b/source/lone/modules/intrinsic/math.c index d4ff1e0c..984baf86 100644 --- a/source/lone/modules/intrinsic/math.c +++ b/source/lone/modules/intrinsic/math.c @@ -18,7 +18,7 @@ void lone_module_math_initialize(struct lone_lisp *lone) *module = lone_module_for_name(lone, name), *primitive; - struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false, .variable_arguments = true }; + struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false }; primitive = lone_primitive_create(lone, "add", lone_primitive_math_add, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "+"), primitive); diff --git a/source/lone/modules/intrinsic/table.c b/source/lone/modules/intrinsic/table.c index 0000c9c8..9973b20d 100644 --- a/source/lone/modules/intrinsic/table.c +++ b/source/lone/modules/intrinsic/table.c @@ -16,7 +16,7 @@ void lone_modules_intrinsic_table_initialize(struct lone_lisp *lone) *module = lone_module_for_name(lone, name), *primitive; - struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false, .variable_arguments = true }; + struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false }; primitive = lone_primitive_create(lone, "table_get", lone_primitive_table_get, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "get"), primitive); diff --git a/source/lone/modules/intrinsic/text.c b/source/lone/modules/intrinsic/text.c index 1d1ce61f..19fd93f0 100644 --- a/source/lone/modules/intrinsic/text.c +++ b/source/lone/modules/intrinsic/text.c @@ -16,7 +16,7 @@ void lone_module_text_initialize(struct lone_lisp *lone) *module = lone_module_for_name(lone, name), *primitive; - struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false, .variable_arguments = true }; + struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false }; primitive = lone_primitive_create(lone, "join", lone_primitive_text_join, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "join"), primitive); diff --git a/source/lone/modules/intrinsic/vector.c b/source/lone/modules/intrinsic/vector.c index 2673a65d..2d3fd31c 100644 --- a/source/lone/modules/intrinsic/vector.c +++ b/source/lone/modules/intrinsic/vector.c @@ -16,7 +16,7 @@ void lone_modules_intrinsic_vector_initialize(struct lone_lisp *lone) *module = lone_module_for_name(lone, name), *primitive; - struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false, .variable_arguments = true }; + struct lone_function_flags flags = { .evaluate_arguments = true, .evaluate_result = false }; primitive = lone_primitive_create(lone, "vector_get", lone_primitive_vector_get, module, flags); lone_set_and_export(lone, module, lone_intern_c_string(lone, "get"), primitive); diff --git a/source/lone/value/primitive.c b/source/lone/value/primitive.c index 8ac99e55..94b7f5bd 100644 --- a/source/lone/value/primitive.c +++ b/source/lone/value/primitive.c @@ -18,7 +18,6 @@ struct lone_value *lone_primitive_create( value->primitive.function = function; value->primitive.closure = closure; value->primitive.flags = flags; - value->primitive.flags.variable_arguments = 1; return value; } diff --git a/test/lone/lambda/*/input b/test/lone/lambda/*/input deleted file mode 100644 index e31b007d..00000000 --- a/test/lone/lambda/*/input +++ /dev/null @@ -1,11 +0,0 @@ -(import (lone lambda* set print)) - -(set star (lambda* (arguments) (print arguments))) - -(star) -(star 1) -(star 1 2) -(star 1 2 3) -(star 1 2 3 4) -(star 1 2 3 4 5) -(star 1 2 3 4 5 6) diff --git a/test/lone/lambda/variadic/0/input b/test/lone/lambda/variadic/0/input new file mode 100644 index 00000000..f2e56a38 --- /dev/null +++ b/test/lone/lambda/variadic/0/input @@ -0,0 +1,11 @@ +(import (lone lambda set print)) + +(set variadic (lambda ((arguments)) (print arguments))) + +(variadic) +(variadic 1) +(variadic 1 2) +(variadic 1 2 3) +(variadic 1 2 3 4) +(variadic 1 2 3 4 5) +(variadic 1 2 3 4 5 6) diff --git a/test/lone/lambda/*/output b/test/lone/lambda/variadic/0/output similarity index 100% rename from test/lone/lambda/*/output rename to test/lone/lambda/variadic/0/output diff --git a/test/lone/lambda/variadic/1/input b/test/lone/lambda/variadic/1/input new file mode 100644 index 00000000..df5053d1 --- /dev/null +++ b/test/lone/lambda/variadic/1/input @@ -0,0 +1,13 @@ +(import (lone lambda set print)) + +(set variadic + (lambda (x (arguments)) + (print x) + (print arguments))) + +(variadic 1) +(variadic 1 2) +(variadic 1 2 3) +(variadic 1 2 3 4) +(variadic 1 2 3 4 5) +(variadic 1 2 3 4 5 6) diff --git a/test/lone/lambda/variadic/1/output b/test/lone/lambda/variadic/1/output new file mode 100644 index 00000000..25d0a69d --- /dev/null +++ b/test/lone/lambda/variadic/1/output @@ -0,0 +1,12 @@ +1 +nil +1 +(2) +1 +(2 3) +1 +(2 3 4) +1 +(2 3 4 5) +1 +(2 3 4 5 6) diff --git a/test/lone/lambda/variadic/2/input b/test/lone/lambda/variadic/2/input new file mode 100644 index 00000000..88b313b8 --- /dev/null +++ b/test/lone/lambda/variadic/2/input @@ -0,0 +1,13 @@ +(import (lone lambda set print)) + +(set variadic + (lambda (x y (arguments)) + (print x) + (print y) + (print arguments))) + +(variadic 1 2) +(variadic 1 2 3) +(variadic 1 2 3 4) +(variadic 1 2 3 4 5) +(variadic 1 2 3 4 5 6) diff --git a/test/lone/lambda/variadic/2/output b/test/lone/lambda/variadic/2/output new file mode 100644 index 00000000..66ad2acd --- /dev/null +++ b/test/lone/lambda/variadic/2/output @@ -0,0 +1,15 @@ +1 +2 +nil +1 +2 +(3) +1 +2 +(3 4) +1 +2 +(3 4 5) +1 +2 +(3 4 5 6)