Add support for variadic extern functions, as it turns out that you can't just specialize them with declarations. I.e., int a_func(int, ...) is different from int a_func(int, int) even if you only ever call a_func(1,2), etc. This commit is in preperation for moving to correcty variadic extern functions for the c stdlib (like printf, snprintf)
This commit is contained in:
@@ -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 ;
|
||||
|
||||
|
||||
@@ -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<ast_node>()
|
||||
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<string, vector<*ast_node>>
|
||||
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<ast_node>()
|
||||
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<symbol>, template_types: vector<string>, template_type_replacements: map<string, *type>, is_function: bool): *ast_node {
|
||||
|
||||
@@ -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<ast_node>()))
|
||||
})
|
||||
var is_variadic = get_node("\"...\"", node) != null<tree<symbol>>()
|
||||
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<tree<symbol>>(), 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<symbol>, param_type: *type, new_map: *map<st
|
||||
}
|
||||
}
|
||||
fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): 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())*/
|
||||
|
||||
@@ -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<type>()
|
||||
// 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 += ", "
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ fun print(toPrint: double) {
|
||||
var int_str = new<char>(how_much+2)
|
||||
snprintf(int_str, (how_much+1) cast ulong, "%f", toPrint)
|
||||
print(int_str)
|
||||
delete(int_str)
|
||||
/*delete(int_str)*/
|
||||
}
|
||||
fun print<T>(toPrint: T): void
|
||||
print(string::to_string(toPrint))
|
||||
|
||||
@@ -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<type>()->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<type>()->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<type>()->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<type>()->construct(parameters, return_type, indirection, is_ref, is_variadic)
|
||||
|
||||
fun type_ptr(traits: set<string>): *type {
|
||||
return new<type>()->construct(traits)
|
||||
@@ -54,6 +55,7 @@ fun type_ptr(traits: set<string>): *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<ast_node>()
|
||||
traits.construct()
|
||||
is_ref = false
|
||||
is_variadic = false
|
||||
return this
|
||||
}
|
||||
fun construct(traits_in: set<string>): *type {
|
||||
@@ -77,6 +80,7 @@ obj type (Object) {
|
||||
type_def = null<ast_node>()
|
||||
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<ast_node>()
|
||||
traits.construct()
|
||||
is_ref = is_ref_in
|
||||
is_variadic = false
|
||||
return this
|
||||
}
|
||||
fun construct(type_def_in: *ast_node, traits_in: set<string>): *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<ast_node>()
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user