diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 63c2286..29cb07e 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -75,7 +75,7 @@ typed_return = WS dec_type | ; function = "ext" WS "fun" WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" typed_return | "fun" WS func_identifier WS template_dec WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement | "fun" WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement ; lambda = "fun" WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement ; -opt_typed_parameter_list = typed_parameter_list | ; +opt_typed_parameter_list = typed_parameter_list | typed_parameter_list WS "," WS "..." | ; typed_parameter_list = typed_parameter_list WS "," WS typed_parameter | typed_parameter ; typed_parameter = identifier WS dec_type ; diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index 5d1c5d8..bc99945 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -285,8 +285,10 @@ obj adt_def (Object) { return name == other.name && self_type == other.self_type && options == other.options && option_funcs == other.option_funcs && regular_funcs == other.regular_funcs } } -fun ast_function_ptr(name: string, type: *type, parameters: vector<*ast_node>, is_extern: bool): *ast_node { - var to_ret.construct(name, type, parameters, is_extern): function +fun ast_function_ptr(name: string, type: *type, parameters: vector<*ast_node>, is_extern: bool): *ast_node + return ast_function_ptr(name, type, parameters, is_extern, false) +fun ast_function_ptr(name: string, type: *type, parameters: vector<*ast_node>, is_extern: bool, is_variadic: bool): *ast_node { + var to_ret.construct(name, type, parameters, is_extern, is_variadic): function var ptr = new() ptr->copy_construct(&ast_node::function(to_ret)) return ptr @@ -305,7 +307,8 @@ obj function (Object) { var body_statement: *ast_node var scope: map> var is_extern: bool - fun construct(name_in: string, type_in: *type, parameters_in: vector<*ast_node>, is_extern_in: bool): *function { + var is_variadic: bool + fun construct(name_in: string, type_in: *type, parameters_in: vector<*ast_node>, is_extern_in: bool, is_variadic_in: bool): *function { name.copy_construct(&name_in) parameters.copy_construct(¶meters_in) closed_variables.construct() @@ -313,6 +316,7 @@ obj function (Object) { type = type_in body_statement = null() is_extern = is_extern_in + is_variadic = is_variadic_in return this } fun copy_construct(old: *function) { @@ -323,6 +327,7 @@ obj function (Object) { closed_variables.copy_construct(&old->closed_variables) scope.copy_construct(&old->scope) is_extern = old->is_extern + is_variadic = old->is_variadic } fun destruct() { name.destruct() @@ -335,7 +340,7 @@ obj function (Object) { copy_construct(&other) } fun operator==(other: ref function): bool { - return name == name && type == other.type && parameters == other.parameters && body_statement == other.body_statement && closed_variables == other.closed_variables && is_extern == other.is_extern + return name == name && type == other.type && parameters == other.parameters && body_statement == other.body_statement && closed_variables == other.closed_variables && is_extern == other.is_extern && is_variadic == other.is_variadic } } fun ast_template_ptr(name: string, syntax_node: *tree, template_types: vector, template_type_replacements: map, is_function: bool): *ast_node { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index d8ec73a..7466720 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -236,8 +236,11 @@ obj ast_transformation (Object) { error(child, "parameter type none") parameters.add(ast_identifier_ptr(concat_symbol_tree(get_node("identifier", child)), param_type, null())) }) + var is_variadic = get_node("\"...\"", node) != null>() + if (is_variadic) + println(function_name + " IS VARIDIC") // figure out function type and make function_node - var function_node = ast_function_ptr(function_name, type_ptr(parameters.map(fun(parameter: *ast_node): *type return parameter->identifier.type;), return_type), parameters, get_node("\"ext\"", node) && true) + var function_node = ast_function_ptr(function_name, type_ptr(parameters.map(fun(parameter: *ast_node): *type return parameter->identifier.type;), return_type, 0, false, is_variadic), parameters, get_node("\"ext\"", node) != null>(), is_variadic) // fix up the enclosing_scope's parameters.for_each(fun(n: *ast_node) n->identifier.enclosing_scope = function_node;) // add to scope @@ -1223,14 +1226,19 @@ fun unify_type(template_type: *tree, param_type: *type, new_map: *map): bool { - var func_param_types = get_ast_type(node)->parameter_types + var func_type = get_ast_type(node) + var func_param_types = func_type->parameter_types var param_string = string() param_types.for_each(fun(t: *type) param_string += t->to_string() + ", ";) - if (func_param_types.size != param_types.size) { + if (!func_type->is_variadic && func_param_types.size != param_types.size) { /*println(string("type sizes don't match ") + param_types.size + " with needed " + param_string)*/ return false + } else if (param_types.size < func_param_types.size) { + return false } - for (var j = 0; j < param_types.size; j++;) { + // note we iterate over the func_param_types which will stop short if function is variadic + // just like we want + for (var j = 0; j < func_param_types.size; j++;) { // don't care about references if (!func_param_types[j]->equality(param_types[j], false)) { /*println(string("types don't match ") + func_param_types[j]->to_string() + " with needed " + param_types[j]->to_string())*/ diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 7c2fbaa..b670e97 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -226,6 +226,10 @@ obj c_generator (Object) { if (!parameter_type->is_ref && parameter_type->indirection == 0 && (parameter_type->is_adt() || (parameter_type->is_object() && has_method(parameter_type->type_def, "destruct", vector<*type>())))) defer_stack->top().second.push(ast_statement_ptr(make_method_call(parameter, "destruct", vector<*ast_node>()))) }) + if (backing.is_variadic) { + parameter_types += ", ..." + parameters += ", ..." + } return make_pair(type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameter_types + ");\n", type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ")") } @@ -858,7 +862,12 @@ obj c_generator (Object) { // parameters.for_each(fun(param: *ast_node) { for (var i = 0; i < parameters.size; i++;) { var param = parameters[i] - var in_function_param_type = func_type->parameter_types[i] + var in_function_param_type = null() + // grab type from param itself if we're out of param types (because variadic function) + if (i < func_type->parameter_types.size) + in_function_param_type = func_type->parameter_types[i] + else + in_function_param_type = get_ast_type(param)->clone_without_ref() if (call_string != "") call_string += ", " diff --git a/stdlib/io.krak b/stdlib/io.krak index e968bd2..df895ff 100644 --- a/stdlib/io.krak +++ b/stdlib/io.krak @@ -47,7 +47,7 @@ fun print(toPrint: double) { var int_str = new(how_much+2) snprintf(int_str, (how_much+1) cast ulong, "%f", toPrint) print(int_str) - delete(int_str) + /*delete(int_str)*/ } fun print(toPrint: T): void print(string::to_string(toPrint)) diff --git a/stdlib/type.krak b/stdlib/type.krak index b3a3f53..0e9bd1b 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -41,11 +41,12 @@ fun type_ptr(base: base_type, indirection: int): *type return type_ptr(base, ind fun type_ptr(base: base_type, indirection: int, is_ref: bool): *type { return new()->construct(base, indirection, is_ref) } -fun type_ptr(parameters: vector<*type>, return_type: *type): *type return type_ptr(parameters, return_type, 0, false); -fun type_ptr(parameters: vector<*type>, return_type: *type, indirection: int): *type return type_ptr(parameters, return_type, indirection, false) -fun type_ptr(parameters: vector<*type>, return_type: *type, indirection: int, is_ref: bool): *type { - return new()->construct(parameters, return_type, indirection, is_ref) -} +fun type_ptr(parameters: vector<*type>, return_type: *type): *type return type_ptr(parameters, return_type, 0, false, false); +fun type_ptr(parameters: vector<*type>, return_type: *type, indirection: int): *type return type_ptr(parameters, return_type, indirection, false, false) +fun type_ptr(parameters: vector<*type>, return_type: *type, indirection: int, is_ref: bool): *type + return new()->construct(parameters, return_type, indirection, is_ref, false) +fun type_ptr(parameters: vector<*type>, return_type: *type, indirection: int, is_ref: bool, is_variadic: bool): *type + return new()->construct(parameters, return_type, indirection, is_ref, is_variadic) fun type_ptr(traits: set): *type { return new()->construct(traits) @@ -54,6 +55,7 @@ fun type_ptr(traits: set): *type { obj type (Object) { var base: base_type var parameter_types: vector<*type> + var is_variadic: bool var return_type: *type var indirection: int var type_def: *ast_node @@ -67,6 +69,7 @@ obj type (Object) { type_def = null() traits.construct() is_ref = false + is_variadic = false return this } fun construct(traits_in: set): *type { @@ -77,6 +80,7 @@ obj type (Object) { type_def = null() traits.copy_construct(&traits_in) is_ref = false + is_variadic = false return this } fun construct(base_in: base_type, indirection_in: int, is_ref_in: bool): *type { @@ -87,6 +91,7 @@ obj type (Object) { type_def = null() traits.construct() is_ref = is_ref_in + is_variadic = false return this } fun construct(type_def_in: *ast_node, traits_in: set): *type { @@ -100,9 +105,10 @@ obj type (Object) { type_def = type_def_in traits.copy_construct(&traits_in) is_ref = false + is_variadic = false return this } - fun construct(parameter_types_in: vector<*type>, return_type_in: *type, indirection_in: int, is_ref_in: bool): *type { + fun construct(parameter_types_in: vector<*type>, return_type_in: *type, indirection_in: int, is_ref_in: bool, is_variadic_in: bool): *type { base.copy_construct(&base_type::function()) parameter_types.copy_construct(¶meter_types_in) return_type = return_type_in @@ -110,6 +116,7 @@ obj type (Object) { type_def = null() traits.construct() is_ref = is_ref_in + is_variadic = is_variadic_in return this } fun copy_construct(old: *type) { @@ -120,6 +127,7 @@ obj type (Object) { type_def = old->type_def traits.copy_construct(&old->traits) is_ref = old->is_ref + is_variadic = old->is_variadic } fun operator=(other: ref type) { destruct() @@ -134,7 +142,7 @@ obj type (Object) { fun operator==(other: ref type):bool return equality(other, true); fun equality(other: *type, care_about_ref: bool):bool return equality(*other, care_about_ref); fun equality(other: ref type, care_about_ref: bool):bool { - if (parameter_types.size != other.parameter_types.size) + if (parameter_types.size != other.parameter_types.size || is_variadic != other.is_variadic) return false for (var i = 0; i < parameter_types.size; i++;) if (!deref_equality(parameter_types[i], other.parameter_types[i])) @@ -156,6 +164,8 @@ obj type (Object) { var indr_string = string("") if (is_ref) indr_string += " ref " + if (is_variadic) + indr_string += " variadic " for (var i = 0; i < indirection; i++;) indr_string += "*" match (base) { base_type::none() return indr_string + string("none") + trait_string