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 ;
|
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 ;
|
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_list = typed_parameter_list WS "," WS typed_parameter | typed_parameter ;
|
||||||
typed_parameter = identifier WS dec_type ;
|
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
|
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 {
|
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
|
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>()
|
var ptr = new<ast_node>()
|
||||||
ptr->copy_construct(&ast_node::function(to_ret))
|
ptr->copy_construct(&ast_node::function(to_ret))
|
||||||
return ptr
|
return ptr
|
||||||
@@ -305,7 +307,8 @@ obj function (Object) {
|
|||||||
var body_statement: *ast_node
|
var body_statement: *ast_node
|
||||||
var scope: map<string, vector<*ast_node>>
|
var scope: map<string, vector<*ast_node>>
|
||||||
var is_extern: bool
|
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)
|
name.copy_construct(&name_in)
|
||||||
parameters.copy_construct(¶meters_in)
|
parameters.copy_construct(¶meters_in)
|
||||||
closed_variables.construct()
|
closed_variables.construct()
|
||||||
@@ -313,6 +316,7 @@ obj function (Object) {
|
|||||||
type = type_in
|
type = type_in
|
||||||
body_statement = null<ast_node>()
|
body_statement = null<ast_node>()
|
||||||
is_extern = is_extern_in
|
is_extern = is_extern_in
|
||||||
|
is_variadic = is_variadic_in
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun copy_construct(old: *function) {
|
fun copy_construct(old: *function) {
|
||||||
@@ -323,6 +327,7 @@ obj function (Object) {
|
|||||||
closed_variables.copy_construct(&old->closed_variables)
|
closed_variables.copy_construct(&old->closed_variables)
|
||||||
scope.copy_construct(&old->scope)
|
scope.copy_construct(&old->scope)
|
||||||
is_extern = old->is_extern
|
is_extern = old->is_extern
|
||||||
|
is_variadic = old->is_variadic
|
||||||
}
|
}
|
||||||
fun destruct() {
|
fun destruct() {
|
||||||
name.destruct()
|
name.destruct()
|
||||||
@@ -335,7 +340,7 @@ obj function (Object) {
|
|||||||
copy_construct(&other)
|
copy_construct(&other)
|
||||||
}
|
}
|
||||||
fun operator==(other: ref function): bool {
|
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 {
|
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")
|
error(child, "parameter type none")
|
||||||
parameters.add(ast_identifier_ptr(concat_symbol_tree(get_node("identifier", child)), param_type, null<ast_node>()))
|
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
|
// 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
|
// fix up the enclosing_scope's
|
||||||
parameters.for_each(fun(n: *ast_node) n->identifier.enclosing_scope = function_node;)
|
parameters.for_each(fun(n: *ast_node) n->identifier.enclosing_scope = function_node;)
|
||||||
// add to scope
|
// 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 {
|
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()
|
var param_string = string()
|
||||||
param_types.for_each(fun(t: *type) param_string += t->to_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)*/
|
/*println(string("type sizes don't match ") + param_types.size + " with needed " + param_string)*/
|
||||||
return false
|
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
|
// don't care about references
|
||||||
if (!func_param_types[j]->equality(param_types[j], false)) {
|
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())*/
|
/*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>()))))
|
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>())))
|
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",
|
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 + ")")
|
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) {
|
// parameters.for_each(fun(param: *ast_node) {
|
||||||
for (var i = 0; i < parameters.size; i++;) {
|
for (var i = 0; i < parameters.size; i++;) {
|
||||||
var param = parameters[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 != "")
|
if (call_string != "")
|
||||||
call_string += ", "
|
call_string += ", "
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ fun print(toPrint: double) {
|
|||||||
var int_str = new<char>(how_much+2)
|
var int_str = new<char>(how_much+2)
|
||||||
snprintf(int_str, (how_much+1) cast ulong, "%f", toPrint)
|
snprintf(int_str, (how_much+1) cast ulong, "%f", toPrint)
|
||||||
print(int_str)
|
print(int_str)
|
||||||
delete(int_str)
|
/*delete(int_str)*/
|
||||||
}
|
}
|
||||||
fun print<T>(toPrint: T): void
|
fun print<T>(toPrint: T): void
|
||||||
print(string::to_string(toPrint))
|
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 {
|
fun type_ptr(base: base_type, indirection: int, is_ref: bool): *type {
|
||||||
return new<type>()->construct(base, indirection, is_ref)
|
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): *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)
|
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 {
|
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)
|
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 {
|
fun type_ptr(traits: set<string>): *type {
|
||||||
return new<type>()->construct(traits)
|
return new<type>()->construct(traits)
|
||||||
@@ -54,6 +55,7 @@ fun type_ptr(traits: set<string>): *type {
|
|||||||
obj type (Object) {
|
obj type (Object) {
|
||||||
var base: base_type
|
var base: base_type
|
||||||
var parameter_types: vector<*type>
|
var parameter_types: vector<*type>
|
||||||
|
var is_variadic: bool
|
||||||
var return_type: *type
|
var return_type: *type
|
||||||
var indirection: int
|
var indirection: int
|
||||||
var type_def: *ast_node
|
var type_def: *ast_node
|
||||||
@@ -67,6 +69,7 @@ obj type (Object) {
|
|||||||
type_def = null<ast_node>()
|
type_def = null<ast_node>()
|
||||||
traits.construct()
|
traits.construct()
|
||||||
is_ref = false
|
is_ref = false
|
||||||
|
is_variadic = false
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun construct(traits_in: set<string>): *type {
|
fun construct(traits_in: set<string>): *type {
|
||||||
@@ -77,6 +80,7 @@ obj type (Object) {
|
|||||||
type_def = null<ast_node>()
|
type_def = null<ast_node>()
|
||||||
traits.copy_construct(&traits_in)
|
traits.copy_construct(&traits_in)
|
||||||
is_ref = false
|
is_ref = false
|
||||||
|
is_variadic = false
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun construct(base_in: base_type, indirection_in: int, is_ref_in: bool): *type {
|
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>()
|
type_def = null<ast_node>()
|
||||||
traits.construct()
|
traits.construct()
|
||||||
is_ref = is_ref_in
|
is_ref = is_ref_in
|
||||||
|
is_variadic = false
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun construct(type_def_in: *ast_node, traits_in: set<string>): *type {
|
fun construct(type_def_in: *ast_node, traits_in: set<string>): *type {
|
||||||
@@ -100,9 +105,10 @@ obj type (Object) {
|
|||||||
type_def = type_def_in
|
type_def = type_def_in
|
||||||
traits.copy_construct(&traits_in)
|
traits.copy_construct(&traits_in)
|
||||||
is_ref = false
|
is_ref = false
|
||||||
|
is_variadic = false
|
||||||
return this
|
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())
|
base.copy_construct(&base_type::function())
|
||||||
parameter_types.copy_construct(¶meter_types_in)
|
parameter_types.copy_construct(¶meter_types_in)
|
||||||
return_type = return_type_in
|
return_type = return_type_in
|
||||||
@@ -110,6 +116,7 @@ obj type (Object) {
|
|||||||
type_def = null<ast_node>()
|
type_def = null<ast_node>()
|
||||||
traits.construct()
|
traits.construct()
|
||||||
is_ref = is_ref_in
|
is_ref = is_ref_in
|
||||||
|
is_variadic = is_variadic_in
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun copy_construct(old: *type) {
|
fun copy_construct(old: *type) {
|
||||||
@@ -120,6 +127,7 @@ obj type (Object) {
|
|||||||
type_def = old->type_def
|
type_def = old->type_def
|
||||||
traits.copy_construct(&old->traits)
|
traits.copy_construct(&old->traits)
|
||||||
is_ref = old->is_ref
|
is_ref = old->is_ref
|
||||||
|
is_variadic = old->is_variadic
|
||||||
}
|
}
|
||||||
fun operator=(other: ref type) {
|
fun operator=(other: ref type) {
|
||||||
destruct()
|
destruct()
|
||||||
@@ -134,7 +142,7 @@ obj type (Object) {
|
|||||||
fun operator==(other: ref type):bool return equality(other, true);
|
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: *type, care_about_ref: bool):bool return equality(*other, care_about_ref);
|
||||||
fun equality(other: ref type, care_about_ref: bool):bool {
|
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
|
return false
|
||||||
for (var i = 0; i < parameter_types.size; i++;)
|
for (var i = 0; i < parameter_types.size; i++;)
|
||||||
if (!deref_equality(parameter_types[i], other.parameter_types[i]))
|
if (!deref_equality(parameter_types[i], other.parameter_types[i]))
|
||||||
@@ -156,6 +164,8 @@ obj type (Object) {
|
|||||||
var indr_string = string("")
|
var indr_string = string("")
|
||||||
if (is_ref)
|
if (is_ref)
|
||||||
indr_string += " ref "
|
indr_string += " ref "
|
||||||
|
if (is_variadic)
|
||||||
|
indr_string += " variadic "
|
||||||
for (var i = 0; i < indirection; i++;) indr_string += "*"
|
for (var i = 0; i < indirection; i++;) indr_string += "*"
|
||||||
match (base) {
|
match (base) {
|
||||||
base_type::none() return indr_string + string("none") + trait_string
|
base_type::none() return indr_string + string("none") + trait_string
|
||||||
|
|||||||
Reference in New Issue
Block a user