Saving a lot of work on ADTs. Finishing should mostly just be filling in the different operator functions in the c_generator
This commit is contained in:
@@ -246,25 +246,40 @@ fun is_adt_def(node: *ast_node): bool {
|
|||||||
obj adt_def (Object) {
|
obj adt_def (Object) {
|
||||||
var scope: map<string, vector<*ast_node>>
|
var scope: map<string, vector<*ast_node>>
|
||||||
var name: string
|
var name: string
|
||||||
|
var self_type: *type
|
||||||
|
var options: vector<*ast_node>
|
||||||
|
var option_funcs: vector<*ast_node>
|
||||||
|
var regular_funcs: vector<*ast_node>
|
||||||
fun construct(nameIn: string): *adt_def {
|
fun construct(nameIn: string): *adt_def {
|
||||||
scope.construct()
|
scope.construct()
|
||||||
name.copy_construct(&nameIn)
|
name.copy_construct(&nameIn)
|
||||||
|
self_type = null<type>()
|
||||||
|
options.construct()
|
||||||
|
option_funcs.construct()
|
||||||
|
regular_funcs.construct()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun copy_construct(old: *adt_def) {
|
fun copy_construct(old: *adt_def) {
|
||||||
scope.copy_construct(&old->scope)
|
scope.copy_construct(&old->scope)
|
||||||
name.copy_construct(&old->name)
|
name.copy_construct(&old->name)
|
||||||
|
self_type = old->self_type
|
||||||
|
options.copy_construct(&old->options)
|
||||||
|
option_funcs.copy_construct(&old->option_funcs)
|
||||||
|
regular_funcs.copy_construct(&old->regular_funcs)
|
||||||
}
|
}
|
||||||
fun destruct() {
|
fun destruct() {
|
||||||
scope.destruct()
|
scope.destruct()
|
||||||
name.destruct()
|
name.destruct()
|
||||||
|
options.destruct()
|
||||||
|
option_funcs.destruct()
|
||||||
|
regular_funcs.destruct()
|
||||||
}
|
}
|
||||||
fun operator=(other: ref adt_def) {
|
fun operator=(other: ref adt_def) {
|
||||||
destruct()
|
destruct()
|
||||||
copy_construct(&other)
|
copy_construct(&other)
|
||||||
}
|
}
|
||||||
fun operator==(other: ref adt_def): bool {
|
fun operator==(other: ref adt_def): bool {
|
||||||
return name == other.name
|
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>): *ast_node {
|
fun ast_function_ptr(name: string, type: *type, parameters: vector<*ast_node>): *ast_node {
|
||||||
@@ -491,8 +506,8 @@ obj if_statement (Object) {
|
|||||||
return condition == other.condition && then_part == other.then_part && else_part == other.else_part
|
return condition == other.condition && then_part == other.then_part && else_part == other.else_part
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun ast_match_statement_ptr(): *ast_node {
|
fun ast_match_statement_ptr(value: *ast_node): *ast_node {
|
||||||
var to_ret.construct(): match_statement
|
var to_ret.construct(value): match_statement
|
||||||
var ptr = new<ast_node>()
|
var ptr = new<ast_node>()
|
||||||
ptr->copy_construct(&ast_node::match_statement(to_ret))
|
ptr->copy_construct(&ast_node::match_statement(to_ret))
|
||||||
return ptr
|
return ptr
|
||||||
@@ -505,22 +520,29 @@ fun is_match_statement(node: *ast_node): bool {
|
|||||||
}
|
}
|
||||||
obj match_statement (Object) {
|
obj match_statement (Object) {
|
||||||
var scope: map<string, vector<*ast_node>>
|
var scope: map<string, vector<*ast_node>>
|
||||||
fun construct(): *match_statement {
|
var value: *ast_node
|
||||||
|
var cases: vector<*ast_node>
|
||||||
|
fun construct(value_in: *ast_node): *match_statement {
|
||||||
scope.construct()
|
scope.construct()
|
||||||
|
value = value_in
|
||||||
|
cases.construct()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun copy_construct(old: *match_statement) {
|
fun copy_construct(old: *match_statement) {
|
||||||
scope.copy_construct(&old->scope)
|
scope.copy_construct(&old->scope)
|
||||||
|
value = old->value
|
||||||
|
cases.copy_construct(&old->cases)
|
||||||
}
|
}
|
||||||
fun destruct() {
|
fun destruct() {
|
||||||
scope.destruct()
|
scope.destruct()
|
||||||
|
cases.destruct()
|
||||||
}
|
}
|
||||||
fun operator=(other: ref match_statement) {
|
fun operator=(other: ref match_statement) {
|
||||||
destruct()
|
destruct()
|
||||||
copy_construct(&other)
|
copy_construct(&other)
|
||||||
}
|
}
|
||||||
fun operator==(other: ref match_statement): bool {
|
fun operator==(other: ref match_statement): bool {
|
||||||
return true
|
return value == other.value && cases == other.cases && scope == other.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun ast_case_statement_ptr(): *ast_node {
|
fun ast_case_statement_ptr(): *ast_node {
|
||||||
@@ -537,12 +559,21 @@ fun is_case_statement(node: *ast_node): bool {
|
|||||||
}
|
}
|
||||||
obj case_statement (Object) {
|
obj case_statement (Object) {
|
||||||
var scope: map<string, vector<*ast_node>>
|
var scope: map<string, vector<*ast_node>>
|
||||||
|
var option: *ast_node
|
||||||
|
var unpack_ident: *ast_node
|
||||||
|
var statement: *ast_node
|
||||||
fun construct(): *case_statement {
|
fun construct(): *case_statement {
|
||||||
scope.construct()
|
scope.construct()
|
||||||
|
option = null<ast_node>()
|
||||||
|
unpack_ident = null<ast_node>()
|
||||||
|
statement = null<ast_node>()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun copy_construct(old: *case_statement) {
|
fun copy_construct(old: *case_statement) {
|
||||||
scope.copy_construct(&old->scope)
|
scope.copy_construct(&old->scope)
|
||||||
|
option = old->option
|
||||||
|
unpack_ident = old->unpack_ident
|
||||||
|
statement = old->statement
|
||||||
}
|
}
|
||||||
fun destruct() {
|
fun destruct() {
|
||||||
scope.destruct()
|
scope.destruct()
|
||||||
@@ -552,7 +583,7 @@ obj case_statement (Object) {
|
|||||||
copy_construct(&other)
|
copy_construct(&other)
|
||||||
}
|
}
|
||||||
fun operator==(other: ref case_statement): bool {
|
fun operator==(other: ref case_statement): bool {
|
||||||
return true
|
return option == other.option && unpack_ident == other.unpack_ident && statement == other.statement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun ast_while_loop_ptr(condition: *ast_node): *ast_node {
|
fun ast_while_loop_ptr(condition: *ast_node): *ast_node {
|
||||||
@@ -974,14 +1005,14 @@ fun get_ast_children(node: *ast_node): vector<*ast_node> {
|
|||||||
ast_node::import(backing) return vector<*ast_node>()
|
ast_node::import(backing) return vector<*ast_node>()
|
||||||
ast_node::identifier(backing) return vector<*ast_node>()
|
ast_node::identifier(backing) return vector<*ast_node>()
|
||||||
ast_node::type_def(backing) return backing.variables + backing.methods
|
ast_node::type_def(backing) return backing.variables + backing.methods
|
||||||
ast_node::adt_def(backing) return vector<*ast_node>()
|
ast_node::adt_def(backing) return backing.options + backing.option_funcs
|
||||||
ast_node::function(backing) return backing.parameters + backing.body_statement
|
ast_node::function(backing) return backing.parameters + backing.body_statement
|
||||||
ast_node::template(backing) return backing.instantiated
|
ast_node::template(backing) return backing.instantiated
|
||||||
ast_node::code_block(backing) return backing.children
|
ast_node::code_block(backing) return backing.children
|
||||||
ast_node::statement(backing) return vector<*ast_node>(backing.child)
|
ast_node::statement(backing) return vector<*ast_node>(backing.child)
|
||||||
ast_node::if_statement(backing) return vector(backing.condition, backing.then_part, backing.else_part)
|
ast_node::if_statement(backing) return vector(backing.condition, backing.then_part, backing.else_part)
|
||||||
ast_node::match_statement(backing) return vector<*ast_node>()
|
ast_node::match_statement(backing) return vector(backing.value) + backing.cases
|
||||||
ast_node::case_statement(backing) return vector<*ast_node>()
|
ast_node::case_statement(backing) return vector(backing.option, backing.unpack_ident, backing.statement)
|
||||||
ast_node::while_loop(backing) return vector(backing.condition, backing.statement)
|
ast_node::while_loop(backing) return vector(backing.condition, backing.statement)
|
||||||
ast_node::for_loop(backing) return vector(backing.init, backing.condition, backing.update, backing.body)
|
ast_node::for_loop(backing) return vector(backing.init, backing.condition, backing.update, backing.body)
|
||||||
ast_node::return_statement(backing) return vector(backing.return_value)
|
ast_node::return_statement(backing) return vector(backing.return_value)
|
||||||
@@ -1018,9 +1049,10 @@ fun get_ast_name(node: *ast_node): string {
|
|||||||
ast_node::declaration_statement(backing) return string("declaration_statement")
|
ast_node::declaration_statement(backing) return string("declaration_statement")
|
||||||
ast_node::if_comp(backing) return string("if_comp: ") + backing.wanted_generator
|
ast_node::if_comp(backing) return string("if_comp: ") + backing.wanted_generator
|
||||||
ast_node::simple_passthrough(backing) return string("simple_passthrough: , string:") + backing.passthrough_str
|
ast_node::simple_passthrough(backing) return string("simple_passthrough: , string:") + backing.passthrough_str
|
||||||
ast_node::function_call(backing) return string("function_call:(") + backing.parameters.size + ")"
|
ast_node::function_call(backing) return string("function_call:") + get_ast_name(backing.func) + "(" + backing.parameters.size + ")"
|
||||||
ast_node::value(backing) return string("value: ") + backing.string_value + ": " + backing.value_type->to_string()
|
ast_node::value(backing) return string("value: ") + backing.string_value + ": " + backing.value_type->to_string()
|
||||||
}
|
}
|
||||||
|
return string("impossible adt type")
|
||||||
}
|
}
|
||||||
fun get_ast_scope(node: *ast_node): *map<string,vector<*ast_node>> {
|
fun get_ast_scope(node: *ast_node): *map<string,vector<*ast_node>> {
|
||||||
match (*node) {
|
match (*node) {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ obj ast_transformation (Object) {
|
|||||||
} else if (child->data.name == "adt_def") {
|
} else if (child->data.name == "adt_def") {
|
||||||
var name = concat_symbol_tree(get_node("identifier", child))
|
var name = concat_symbol_tree(get_node("identifier", child))
|
||||||
var adt_def_node = ast_adt_def_ptr(name)
|
var adt_def_node = ast_adt_def_ptr(name)
|
||||||
|
adt_def_node->adt_def.self_type = type_ptr(adt_def_node, set(string("Object")))
|
||||||
translation_unit->translation_unit.children.add(adt_def_node)
|
translation_unit->translation_unit.children.add(adt_def_node)
|
||||||
ast_to_syntax.set(adt_def_node, child)
|
ast_to_syntax.set(adt_def_node, child)
|
||||||
add_to_scope("~enclosing_scope", translation_unit, adt_def_node)
|
add_to_scope("~enclosing_scope", translation_unit, adt_def_node)
|
||||||
@@ -129,7 +130,7 @@ obj ast_transformation (Object) {
|
|||||||
translation_unit->translation_unit.children.for_each(fun(node: *ast_node) {
|
translation_unit->translation_unit.children.for_each(fun(node: *ast_node) {
|
||||||
match(*node) {
|
match(*node) {
|
||||||
ast_node::type_def(backing) second_pass_type_def(ast_to_syntax[node], node, translation_unit, map<string, *type>())
|
ast_node::type_def(backing) second_pass_type_def(ast_to_syntax[node], node, translation_unit, map<string, *type>())
|
||||||
ast_node::adt_def(backing) do_nothing() // actually go through and do methods inside
|
ast_node::adt_def(backing) second_pass_adt_def(ast_to_syntax[node], node, translation_unit, map<string, *type>())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -147,6 +148,51 @@ obj ast_transformation (Object) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fun second_pass_adt_def(adt_def_syntax: *tree<symbol>, node: *ast_node, scope: *ast_node, template_replacements: map<string, *type>) {
|
||||||
|
get_nodes("adt_option", adt_def_syntax).for_each(fun(adt_option: *tree<symbol>) {
|
||||||
|
var ident_type: *type
|
||||||
|
var type_syntax = get_node("type", adt_option)
|
||||||
|
if (type_syntax)
|
||||||
|
ident_type = transform_type(type_syntax, scope, template_replacements)
|
||||||
|
else
|
||||||
|
ident_type = type_ptr(base_type::no_type_adt_option())
|
||||||
|
var option_name = concat_symbol_tree(get_node("identifier", adt_option))
|
||||||
|
var identifier = ast_identifier_ptr(option_name, ident_type, node)
|
||||||
|
node->adt_def.options.add(identifier)
|
||||||
|
// we add the identifier first so that it's found before the function when doing option.thingy
|
||||||
|
add_to_scope(option_name, identifier, node)
|
||||||
|
add_to_scope("~enclosing_scope", node, identifier)
|
||||||
|
ast_to_syntax.set(identifier, adt_option)
|
||||||
|
|
||||||
|
var function_node = null<ast_node>()
|
||||||
|
if (type_syntax)
|
||||||
|
function_node = ast_function_ptr(option_name, type_ptr(vector(get_ast_type(identifier)), node->adt_def.self_type), vector(identifier))
|
||||||
|
else
|
||||||
|
function_node = ast_function_ptr(option_name, type_ptr(vector<*type>(), node->adt_def.self_type), vector<*ast_node>())
|
||||||
|
add_to_scope(option_name, function_node, node)
|
||||||
|
add_to_scope("~enclosing_scope", node, function_node)
|
||||||
|
node->adt_def.option_funcs.add(function_node)
|
||||||
|
})
|
||||||
|
// we fake operator==, operator!=, copy_construct, operator=, and destruct like so
|
||||||
|
// note they don't even have real parameters (but the type has them correctly) or bodies
|
||||||
|
|
||||||
|
// I'm not sure this is the correct enclosing scope, but I'm not sure how to do it with the function either
|
||||||
|
var equals_param = ast_identifier_ptr(string("in"), node->adt_def.self_type->clone_with_indirection(0,true), node)
|
||||||
|
var nequals_param = ast_identifier_ptr(string("in"), node->adt_def.self_type->clone_with_indirection(0,true), node)
|
||||||
|
var copy_construct_param = ast_identifier_ptr(string("in"), node->adt_def.self_type->clone_with_indirection(1,false), node)
|
||||||
|
var assign_param = ast_identifier_ptr(string("in"), node->adt_def.self_type->clone_with_indirection(0,true), node)
|
||||||
|
vector(
|
||||||
|
make_pair("operator==", ast_function_ptr(string("operator=="), type_ptr(vector(equals_param->identifier.type), type_ptr(base_type::boolean())), vector(equals_param))),
|
||||||
|
make_pair("operator!=", ast_function_ptr(string("operator!="), type_ptr(vector(nequals_param->identifier.type), type_ptr(base_type::boolean())), vector(nequals_param))),
|
||||||
|
make_pair("copy_construct", ast_function_ptr(string("copy_construct"), type_ptr(vector(copy_construct_param->identifier.type), type_ptr(base_type::void_return())), vector(copy_construct_param))),
|
||||||
|
make_pair("operator=", ast_function_ptr(string("operator="), type_ptr(vector(assign_param->identifier.type), type_ptr(base_type::void_return())), vector(assign_param))),
|
||||||
|
make_pair("destruct", ast_function_ptr(string("destruct"), type_ptr(vector<*type>(), type_ptr(base_type::void_return())), vector<*ast_node>()))
|
||||||
|
).for_each(fun(func_pair: pair<*char, *ast_node>) {
|
||||||
|
node->adt_def.regular_funcs.add(func_pair.second)
|
||||||
|
add_to_scope(string(func_pair.first), func_pair.second, node)
|
||||||
|
add_to_scope("~enclosing_scope", node, func_pair.second)
|
||||||
|
})
|
||||||
|
}
|
||||||
fun second_pass_function(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>, do_raw_template: bool): *ast_node {
|
fun second_pass_function(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>, do_raw_template: bool): *ast_node {
|
||||||
var func_identifier_node = get_node("func_identifier", node)
|
var func_identifier_node = get_node("func_identifier", node)
|
||||||
var function_name = string("lambda")
|
var function_name = string("lambda")
|
||||||
@@ -340,6 +386,7 @@ obj ast_transformation (Object) {
|
|||||||
for (var i = 0; i < possibilities.size; i++;) {
|
for (var i = 0; i < possibilities.size; i++;) {
|
||||||
match(*possibilities[i]) {
|
match(*possibilities[i]) {
|
||||||
ast_node::type_def(backing) return backing.self_type->clone_with_indirection(indirection, is_ref)
|
ast_node::type_def(backing) return backing.self_type->clone_with_indirection(indirection, is_ref)
|
||||||
|
ast_node::adt_def(backing) return backing.self_type->clone_with_indirection(indirection, is_ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println("No objects in lookup, returning none")
|
println("No objects in lookup, returning none")
|
||||||
@@ -375,6 +422,8 @@ obj ast_transformation (Object) {
|
|||||||
return transform_branching_statement(node, scope)
|
return transform_branching_statement(node, scope)
|
||||||
} else if (name == "defer_statement") {
|
} else if (name == "defer_statement") {
|
||||||
return transform_defer_statement(node, scope, template_replacements)
|
return transform_defer_statement(node, scope, template_replacements)
|
||||||
|
} else if (name == "match_statement") {
|
||||||
|
return transform_match_statement(node, scope, template_replacements)
|
||||||
} else if (name == "function_call") {
|
} else if (name == "function_call") {
|
||||||
return transform_function_call(node, scope, template_replacements)
|
return transform_function_call(node, scope, template_replacements)
|
||||||
} else if (name == "lambda") {
|
} else if (name == "lambda") {
|
||||||
@@ -629,6 +678,31 @@ obj ast_transformation (Object) {
|
|||||||
fun transform_defer_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
fun transform_defer_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
||||||
return ast_defer_statement_ptr(transform(node->children[0], scope, template_replacements))
|
return ast_defer_statement_ptr(transform(node->children[0], scope, template_replacements))
|
||||||
}
|
}
|
||||||
|
fun transform_match_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
||||||
|
var to_ret = ast_match_statement_ptr(transform(get_node("boolean_expression", node), scope, template_replacements))
|
||||||
|
get_nodes("case_statement", node).for_each(fun(syntax: *tree<symbol>) to_ret->match_statement.cases.add(transform_case_statement(syntax, scope, template_replacements));)
|
||||||
|
return to_ret
|
||||||
|
}
|
||||||
|
fun transform_case_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
||||||
|
var to_ret = ast_case_statement_ptr()
|
||||||
|
var the_adts = scope_lookup(concat_symbol_tree(get_node("scoped_identifier", get_node("scoped_identifier", node))), scope)
|
||||||
|
if (the_adts.size != 1)
|
||||||
|
error(string("the adts too large for ") + concat_symbol_tree(get_node("scoped_identifier", node)))
|
||||||
|
var the_adt = the_adts[0]
|
||||||
|
var the_option_name = concat_symbol_tree(get_node("identifier", get_node("scoped_identifier", node)))
|
||||||
|
var the_option = the_adt->adt_def.options.find_first_satisfying(fun(option: *ast_node): bool return option->identifier.name == the_option_name;)
|
||||||
|
to_ret->case_statement.option = the_option
|
||||||
|
var possible_ident = get_node("identifier", node)
|
||||||
|
if (possible_ident) {
|
||||||
|
var ident = ast_identifier_ptr(concat_symbol_tree(possible_ident), the_option->identifier.type, scope)
|
||||||
|
to_ret->case_statement.unpack_ident = ident
|
||||||
|
add_to_scope(ident->identifier.name, ident, to_ret)
|
||||||
|
}
|
||||||
|
//add to scope
|
||||||
|
add_to_scope("~enclosing_scope", scope, to_ret)
|
||||||
|
to_ret->case_statement.statement = transform(get_node("statement", node), to_ret, template_replacements)
|
||||||
|
return to_ret
|
||||||
|
}
|
||||||
fun transform_function_call(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
fun transform_function_call(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
||||||
// don't bother with a full transform for parameters with their own function, just get the boolean expression and transform it
|
// don't bother with a full transform for parameters with their own function, just get the boolean expression and transform it
|
||||||
var parameters = get_nodes("parameter", node).map(fun(child: *tree<symbol>): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);)
|
var parameters = get_nodes("parameter", node).map(fun(child: *tree<symbol>): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);)
|
||||||
@@ -826,7 +900,7 @@ obj ast_transformation (Object) {
|
|||||||
fun find_and_make_any_operator_overload_call(func_name: string, parameters: vector<*ast_node>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
fun find_and_make_any_operator_overload_call(func_name: string, parameters: vector<*ast_node>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
||||||
var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);)
|
var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);)
|
||||||
var possible_overload = null<ast_node>()
|
var possible_overload = null<ast_node>()
|
||||||
if (parameter_types[0]->is_object() && parameter_types[0]->indirection == 0) {
|
if ((parameter_types[0]->is_adt() || parameter_types[0]->is_object()) && parameter_types[0]->indirection == 0) {
|
||||||
possible_overload = function_lookup(string("operator")+func_name, parameter_types.first()->type_def, parameter_types.slice(1,-1))
|
possible_overload = function_lookup(string("operator")+func_name, parameter_types.first()->type_def, parameter_types.slice(1,-1))
|
||||||
if (!possible_overload)
|
if (!possible_overload)
|
||||||
possible_overload = find_or_instantiate_template_function(string("operator")+func_name, null<tree<symbol>>(), parameter_types.first()->type_def, parameter_types.slice(1,-1), template_replacements, map<string, *type>())
|
possible_overload = find_or_instantiate_template_function(string("operator")+func_name, null<tree<symbol>>(), parameter_types.first()->type_def, parameter_types.slice(1,-1), template_replacements, map<string, *type>())
|
||||||
@@ -952,6 +1026,7 @@ fun has_method(object: *ast_node, name: string, parameter_types: vector<*type>):
|
|||||||
fun make_method_call(object_ident: *ast_node, name: *char, parameters: vector<*ast_node>): *ast_node return make_method_call(object_ident, string(name), parameters);
|
fun make_method_call(object_ident: *ast_node, name: *char, parameters: vector<*ast_node>): *ast_node return make_method_call(object_ident, string(name), parameters);
|
||||||
fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<*ast_node>): *ast_node {
|
fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<*ast_node>): *ast_node {
|
||||||
println("MAKE METHOD CALL OUT:")
|
println("MAKE METHOD CALL OUT:")
|
||||||
|
// note that this type_def is the adt_def if this is an adt type
|
||||||
var method = function_lookup(name, get_ast_type(object_ident)->type_def, parameters.map(fun(param: *ast_node): *type return get_ast_type(param);))
|
var method = function_lookup(name, get_ast_type(object_ident)->type_def, parameters.map(fun(param: *ast_node): *type return get_ast_type(param);))
|
||||||
print("Here is the Method: ")
|
print("Here is the Method: ")
|
||||||
println(method)
|
println(method)
|
||||||
@@ -1061,7 +1136,7 @@ fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>):
|
|||||||
var results = scope_lookup(name, scope)
|
var results = scope_lookup(name, scope)
|
||||||
print(results.size); println(" number of results")
|
print(results.size); println(" number of results")
|
||||||
for (var i = 0; i < results.size; i++;) {
|
for (var i = 0; i < results.size; i++;) {
|
||||||
if ((is_function(results[i]) || is_identifier(results[i])) && function_satisfies_params(results[i], param_types)) {
|
if ((is_function(results[i]) || (is_identifier(results[i]) && get_ast_type(results[i])->is_function())) && function_satisfies_params(results[i], param_types)) {
|
||||||
return results[i]
|
return results[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,38 @@ obj c_generator (Object) {
|
|||||||
replacement_map.destruct()
|
replacement_map.destruct()
|
||||||
}
|
}
|
||||||
fun get_id(): string return to_string(id_counter++);
|
fun get_id(): string return to_string(id_counter++);
|
||||||
|
fun generate_function_prototype_and_header(child: *ast_node, enclosing_object: *ast_node, is_lambda: bool, defer_stack: *stack<pair<bool,stack<*ast_node>>>):pair<string,string> {
|
||||||
|
var backing = child->function
|
||||||
|
|
||||||
|
var parameter_types = string()
|
||||||
|
var parameters = string()
|
||||||
|
// lambdas can have the enclosing object too, if it's needed (lambda in a method)
|
||||||
|
if (enclosing_object && !is_lambda) {
|
||||||
|
parameter_types = type_to_c(enclosing_object->type_def.self_type) + "*"
|
||||||
|
parameters = type_to_c(enclosing_object->type_def.self_type) + "* this"
|
||||||
|
}
|
||||||
|
if (backing.closed_variables.size()) {
|
||||||
|
println("HAS CLOSED VARIABLES")
|
||||||
|
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
|
||||||
|
var closed_type_name = get_closure_struct_type(backing.closed_variables)
|
||||||
|
parameter_types += closed_type_name + "*"
|
||||||
|
parameters += closed_type_name + "* closure_data"
|
||||||
|
}
|
||||||
|
|
||||||
|
var decorated_name = generate_function(child, enclosing_object, null<ast_node>(), false, false).one_string()
|
||||||
|
backing.parameters.for_each(fun(parameter: *ast_node) {
|
||||||
|
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
|
||||||
|
parameter_types += type_to_c(parameter->identifier.type)
|
||||||
|
parameters += type_to_c(parameter->identifier.type) + " " + get_name(parameter)
|
||||||
|
|
||||||
|
// add parameters to destructor thingy (for returns)? Or should that be a different pass?
|
||||||
|
var parameter_type = parameter->identifier.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>())))
|
||||||
|
})
|
||||||
|
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 + ")")
|
||||||
|
}
|
||||||
fun generate_c(name_ast_map: map<string, pair<*tree<symbol>,*ast_node>>): pair<string,string> {
|
fun generate_c(name_ast_map: map<string, pair<*tree<symbol>,*ast_node>>): pair<string,string> {
|
||||||
var linker_string:string = ""
|
var linker_string:string = ""
|
||||||
var prequal: string = "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n"
|
var prequal: string = "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n"
|
||||||
@@ -176,42 +208,49 @@ obj c_generator (Object) {
|
|||||||
// moved out from below so that it can be used for methods as well as regular functions (and eventually lambdas...)
|
// moved out from below so that it can be used for methods as well as regular functions (and eventually lambdas...)
|
||||||
var generate_function_definition = fun(child: *ast_node, enclosing_object: *ast_node, is_lambda: bool) {
|
var generate_function_definition = fun(child: *ast_node, enclosing_object: *ast_node, is_lambda: bool) {
|
||||||
var backing = child->function
|
var backing = child->function
|
||||||
|
|
||||||
var parameter_types = string()
|
|
||||||
var parameters = string()
|
|
||||||
// lambdas can have the enclosing object too, if it's needed (lambda in a method)
|
|
||||||
if (enclosing_object && !is_lambda) {
|
|
||||||
parameter_types = type_to_c(enclosing_object->type_def.self_type) + "*"
|
|
||||||
parameters = type_to_c(enclosing_object->type_def.self_type) + "* this"
|
|
||||||
}
|
|
||||||
if (backing.closed_variables.size()) {
|
|
||||||
println("HAS CLOSED VARIABLES")
|
|
||||||
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
|
|
||||||
var closed_type_name = get_closure_struct_type(backing.closed_variables)
|
|
||||||
parameter_types += closed_type_name + "*"
|
|
||||||
parameters += closed_type_name + "* closure_data"
|
|
||||||
}
|
|
||||||
|
|
||||||
// stack-stack thing // this could be a stack of strings too, maybe
|
// stack-stack thing // this could be a stack of strings too, maybe
|
||||||
// start out with one stack on the stack
|
// start out with one stack on the stack
|
||||||
var defer_stack = stack<pair<bool,stack<*ast_node>>>(make_pair(false, stack<*ast_node>()))
|
var defer_stack = stack<pair<bool,stack<*ast_node>>>(make_pair(false, stack<*ast_node>()))
|
||||||
|
var prototype_and_header = generate_function_prototype_and_header(child, enclosing_object, is_lambda, &defer_stack)
|
||||||
var decorated_name = generate_function(child, enclosing_object, null<ast_node>(), false, false).one_string()
|
function_prototypes += prototype_and_header.first
|
||||||
backing.parameters.for_each(fun(parameter: *ast_node) {
|
function_definitions += prototype_and_header.second
|
||||||
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
|
if (backing.body_statement) {
|
||||||
parameter_types += type_to_c(parameter->identifier.type)
|
function_definitions += string(" {\n") + generate_statement(backing.body_statement, enclosing_object, child, &defer_stack).one_string()
|
||||||
parameters += type_to_c(parameter->identifier.type) + " " + get_name(parameter)
|
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||||
|
function_definitions += "}\n"
|
||||||
// add parameters to destructor thingy (for returns)? Or should that be a different pass?
|
} else {
|
||||||
var parameter_type = parameter->identifier.type
|
// adt constructor
|
||||||
if (!parameter_type->is_ref && parameter_type->indirection == 0 && parameter_type->is_object() && has_method(parameter_type->type_def, "destruct", vector<*type>()))
|
// wow. no pass in for no this
|
||||||
defer_stack.top().second.push(ast_statement_ptr(make_method_call(parameter, "destruct", vector<*ast_node>())))
|
enclosing_object = get_ast_scope(child)->get(string("~enclosing_scope"))[0]
|
||||||
})
|
// if this is an option constructor
|
||||||
function_prototypes += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameter_types + ");\n"
|
if (enclosing_object->adt_def.options.any_true(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;)) {
|
||||||
function_definitions += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ") {\n" + generate_statement(backing.body_statement, enclosing_object, child, &defer_stack).one_string()
|
var option_ident = enclosing_object->adt_def.options.find_first_satisfying(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;)
|
||||||
// emit parameter destructors?
|
function_definitions += " { \n"
|
||||||
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
function_definitions += type_to_c(enclosing_object->adt_def.self_type) + " to_ret;\n"
|
||||||
function_definitions += "}\n"
|
function_definitions += string("to_ret.flag = ") + string("enum_opt_") + get_name(option_ident) + ";\n"
|
||||||
|
if (option_ident->identifier.type->is_empty_adt_option())
|
||||||
|
function_definitions += "/*no inner data*/\n"
|
||||||
|
else
|
||||||
|
function_definitions += string("to_ret.data.") + get_name(option_ident) + " = " + get_name(option_ident) + ";\n"
|
||||||
|
function_definitions += "return to_ret;\n"
|
||||||
|
function_definitions += "}\n"
|
||||||
|
} else {
|
||||||
|
// this is one of the other functions instead
|
||||||
|
function_definitions += "{"
|
||||||
|
if (backing.name == "operator==") {
|
||||||
|
function_definitions += "/*operator==*/"
|
||||||
|
} else if (backing.name == "operator!=") {
|
||||||
|
function_definitions += "/*operator!=*/"
|
||||||
|
} else if (backing.name == "copy_construct") {
|
||||||
|
function_definitions += "/*copy_construct*/"
|
||||||
|
} else if (backing.name == "operator=") {
|
||||||
|
function_definitions += "/*operator=*/"
|
||||||
|
} else if (backing.name == "destruct") {
|
||||||
|
function_definitions += "/*destruct*/"
|
||||||
|
}
|
||||||
|
function_definitions += "}\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var type_poset = poset<*ast_node>()
|
var type_poset = poset<*ast_node>()
|
||||||
@@ -225,7 +264,7 @@ obj c_generator (Object) {
|
|||||||
while(enclosing_object_traverse && !is_type_def(enclosing_object_traverse) &&
|
while(enclosing_object_traverse && !is_type_def(enclosing_object_traverse) &&
|
||||||
get_ast_scope(enclosing_object_traverse) && get_ast_scope(enclosing_object_traverse)->contains_key(string("~enclosing_scope")))
|
get_ast_scope(enclosing_object_traverse) && get_ast_scope(enclosing_object_traverse)->contains_key(string("~enclosing_scope")))
|
||||||
enclosing_object_traverse = get_ast_scope(enclosing_object_traverse)->get(string("~enclosing_scope"))[0]
|
enclosing_object_traverse = get_ast_scope(enclosing_object_traverse)->get(string("~enclosing_scope"))[0]
|
||||||
if (enclosing_object_traverse && is_type_def(enclosing_object_traverse))
|
if (enclosing_object_traverse && is_type_def(enclosing_object_traverse))
|
||||||
generate_function_definition(child, enclosing_object_traverse, true)
|
generate_function_definition(child, enclosing_object_traverse, true)
|
||||||
else
|
else
|
||||||
generate_function_definition(child, null<ast_node>(), true)
|
generate_function_definition(child, null<ast_node>(), true)
|
||||||
@@ -266,6 +305,14 @@ obj c_generator (Object) {
|
|||||||
type_poset.add_relationship(child, var_type->type_def)
|
type_poset.add_relationship(child, var_type->type_def)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
ast_node::adt_def(backing) {
|
||||||
|
type_poset.add_vertex(child)
|
||||||
|
backing.options.for_each(fun(i: *ast_node) {
|
||||||
|
var var_type = get_ast_type(i)
|
||||||
|
if (!var_type->indirection && var_type->type_def)
|
||||||
|
type_poset.add_relationship(child, var_type->type_def)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -274,15 +321,37 @@ obj c_generator (Object) {
|
|||||||
var base_name = get_name(vert)
|
var base_name = get_name(vert)
|
||||||
plain_typedefs += string("typedef struct ") + base_name + "_dummy " + base_name + ";\n"
|
plain_typedefs += string("typedef struct ") + base_name + "_dummy " + base_name + ";\n"
|
||||||
structs += string("struct ") + base_name + "_dummy {\n"
|
structs += string("struct ") + base_name + "_dummy {\n"
|
||||||
vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n";) // also no defer stack
|
if (is_type_def(vert)) {
|
||||||
|
vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n";) // also no defer stack
|
||||||
|
// generate the methods (note some of these may be templates)
|
||||||
|
vert->type_def.methods.for_each(fun(method: *ast_node) {
|
||||||
|
if (is_template(method))
|
||||||
|
method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m, vert, false);)
|
||||||
|
else
|
||||||
|
generate_function_definition(method, vert, false);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// adt
|
||||||
|
var add_to_structs = string()
|
||||||
|
var add_to_enum = string()
|
||||||
|
vert->adt_def.options.for_each(fun(option: *ast_node) {
|
||||||
|
add_to_enum += string("enum_opt_") + get_name(option) + ","
|
||||||
|
if (!option->identifier.type->is_empty_adt_option())
|
||||||
|
add_to_structs += generate_declaration_statement(ast_declaration_statement_ptr(option, null<ast_node>()), null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n"
|
||||||
|
})
|
||||||
|
structs += string("enum { ") + add_to_enum + " } flag;\n"
|
||||||
|
structs += string("union { ") + add_to_structs + " } data;\n"
|
||||||
|
// now do methods and generation functions
|
||||||
|
vert->adt_def.option_funcs.for_each(fun(option_func: *ast_node) {
|
||||||
|
// no vert so no this
|
||||||
|
generate_function_definition(option_func, null<ast_node>(), false);
|
||||||
|
})
|
||||||
|
vert->adt_def.regular_funcs.for_each(fun(regular_func: *ast_node) {
|
||||||
|
// want the this this time
|
||||||
|
generate_function_definition(regular_func, vert, false);
|
||||||
|
})
|
||||||
|
}
|
||||||
structs += "};\n"
|
structs += "};\n"
|
||||||
// generate the methods (note some of these may be templates)
|
|
||||||
vert->type_def.methods.for_each(fun(method: *ast_node) {
|
|
||||||
if (is_template(method))
|
|
||||||
method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m, vert, false);)
|
|
||||||
else
|
|
||||||
generate_function_definition(method, vert, false);
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string+closure_struct_definitions+function_prototypes+variable_declarations+function_definitions + "\n", linker_string)
|
return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string+closure_struct_definitions+function_prototypes+variable_declarations+function_definitions + "\n", linker_string)
|
||||||
@@ -337,7 +406,7 @@ obj c_generator (Object) {
|
|||||||
// we only make it first if it's a function type though, so that global levels still work
|
// we only make it first if it's a function type though, so that global levels still work
|
||||||
var to_ret = code_triple(type_to_c(identifier->identifier.type) + " " + get_name(identifier), string(), string())
|
var to_ret = code_triple(type_to_c(identifier->identifier.type) + " " + get_name(identifier), string(), string())
|
||||||
if (node->declaration_statement.expression) {
|
if (node->declaration_statement.expression) {
|
||||||
if (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection()))) {
|
if (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection())))) {
|
||||||
to_ret.pre += ";\n"
|
to_ret.pre += ";\n"
|
||||||
to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack, false)
|
to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack, false)
|
||||||
} else {
|
} else {
|
||||||
@@ -357,7 +426,7 @@ obj c_generator (Object) {
|
|||||||
to_ret.pre += ";\n"
|
to_ret.pre += ";\n"
|
||||||
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||||
}
|
}
|
||||||
if (add_to_defer && ident_type->is_object() && ident_type->indirection == 0 && has_method(ident_type->type_def, "destruct", vector<*type>()))
|
if (add_to_defer && ident_type->indirection == 0 && (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>()))))
|
||||||
defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))
|
defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))
|
||||||
return to_ret
|
return to_ret
|
||||||
}
|
}
|
||||||
@@ -431,7 +500,7 @@ obj c_generator (Object) {
|
|||||||
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>())
|
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>())
|
||||||
// have to pass false to the declaration generator, so can't do it through generate_statement
|
// have to pass false to the declaration generator, so can't do it through generate_statement
|
||||||
to_ret.pre = generate_declaration_statement(declaration, enclosing_object, enclosing_func, defer_stack, false).one_string() + ";\n"
|
to_ret.pre = generate_declaration_statement(declaration, enclosing_object, enclosing_func, defer_stack, false).one_string() + ";\n"
|
||||||
if (return_value_type->is_object() && !function_return_type->is_ref && return_value_type->indirection == 0 && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1)))) {
|
if (!function_return_type->is_ref && return_value_type->indirection == 0 && (return_value_type->is_adt() || (return_value_type->is_object() && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1)))))) {
|
||||||
to_ret.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_value))))), enclosing_object, enclosing_func, defer_stack).one_string()
|
to_ret.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_value))))), enclosing_object, enclosing_func, defer_stack).one_string()
|
||||||
} else {
|
} else {
|
||||||
var refamp = string()
|
var refamp = string()
|
||||||
@@ -447,7 +516,7 @@ obj c_generator (Object) {
|
|||||||
to_ret += code_triple(" ") + generate(return_value, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
to_ret += code_triple(" ") + generate(return_value, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||||
// generate all in stack by passing -1, make sure added after we calculate the return value
|
// generate all in stack by passing -1, make sure added after we calculate the return value
|
||||||
to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string()
|
to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string()
|
||||||
|
|
||||||
return to_ret
|
return to_ret
|
||||||
}
|
}
|
||||||
fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
|
fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
|
||||||
@@ -478,6 +547,25 @@ obj c_generator (Object) {
|
|||||||
defer_stack->top().second.push(node->defer_statement.statement)
|
defer_stack->top().second.push(node->defer_statement.statement)
|
||||||
return code_triple("/*defer wanna know what*/")
|
return code_triple("/*defer wanna know what*/")
|
||||||
}
|
}
|
||||||
|
fun generate_match_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
|
||||||
|
var to_ret = code_triple("/* begin match */")
|
||||||
|
var matching_value = generate(node->match_statement.value, enclosing_object, enclosing_func, defer_stack, true)
|
||||||
|
to_ret.pre += matching_value.pre
|
||||||
|
to_ret.post += matching_value.post
|
||||||
|
node->match_statement.cases.for_each(fun(case_node: *ast_node) {
|
||||||
|
var option_str = generate(case_node->case_statement.option, enclosing_object, enclosing_func, defer_stack, false).one_string()
|
||||||
|
var to_ret_case = code_triple("/*case ") + option_str + "*/ if(" + matching_value.value + ".flag == " + string("enum_opt_") + option_str + ") {\n"
|
||||||
|
if (case_node->case_statement.unpack_ident) {
|
||||||
|
to_ret_case += generate_declaration_statement(ast_declaration_statement_ptr(case_node->case_statement.unpack_ident, null<ast_node>()), null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string()
|
||||||
|
to_ret_case += string(" = ") + matching_value.value + ".data." + option_str + ";\n"
|
||||||
|
} else {
|
||||||
|
to_ret_case += "/*no unpack_ident*/\n"
|
||||||
|
}
|
||||||
|
to_ret_case += generate(case_node->case_statement.statement, enclosing_object, enclosing_func, defer_stack, false).one_string() + "\n}\n"
|
||||||
|
to_ret += to_ret_case.one_string()
|
||||||
|
})
|
||||||
|
return to_ret
|
||||||
|
}
|
||||||
fun generate_value(node: *ast_node, need_variable: bool): code_triple {
|
fun generate_value(node: *ast_node, need_variable: bool): code_triple {
|
||||||
var value = node->value.string_value
|
var value = node->value.string_value
|
||||||
var to_ret = string()
|
var to_ret = string()
|
||||||
@@ -487,7 +575,7 @@ obj c_generator (Object) {
|
|||||||
to_ret = string("\"")
|
to_ret = string("\"")
|
||||||
if (value.slice(0,3) == "\"\"\"")
|
if (value.slice(0,3) == "\"\"\"")
|
||||||
value = value.slice(3,-4)
|
value = value.slice(3,-4)
|
||||||
else
|
else
|
||||||
value = value.slice(1,-2)
|
value = value.slice(1,-2)
|
||||||
value.for_each(fun(c: char) {
|
value.for_each(fun(c: char) {
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
@@ -553,7 +641,9 @@ obj c_generator (Object) {
|
|||||||
is_function(node->function_call.func->function_call.parameters[1]) &&
|
is_function(node->function_call.func->function_call.parameters[1]) &&
|
||||||
(is_type_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0]) ||
|
(is_type_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0]) ||
|
||||||
// or if it's a templated method (yes, this has gotten uuuuugly)
|
// or if it's a templated method (yes, this has gotten uuuuugly)
|
||||||
is_type_def(get_ast_scope(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0])->get(string("~enclosing_scope"))[0]))
|
is_type_def(get_ast_scope(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0])->get(string("~enclosing_scope"))[0]) ||
|
||||||
|
// or it's in an adt
|
||||||
|
is_adt_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0]))
|
||||||
// should get uglier when we have to figure out if it's just an inside lambda
|
// should get uglier when we have to figure out if it's just an inside lambda
|
||||||
|
|
||||||
if (dot_style_method_call) {
|
if (dot_style_method_call) {
|
||||||
@@ -611,8 +701,13 @@ obj c_generator (Object) {
|
|||||||
}
|
}
|
||||||
// don't propegate enclosing function down right of access
|
// don't propegate enclosing function down right of access
|
||||||
// XXX what about enclosing object? should it be the thing on the left?
|
// XXX what about enclosing object? should it be the thing on the left?
|
||||||
if (func_name == "." || func_name == "->")
|
if (func_name == "." || func_name == "->") {
|
||||||
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + func_name + generate(parameters[1], null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false) + string(")")
|
// special case right hand side is an adt to access inside of adt
|
||||||
|
var in_between = string()
|
||||||
|
if (get_ast_type(parameters[0])->is_adt())
|
||||||
|
in_between = "data."
|
||||||
|
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + func_name + in_between + generate(parameters[1], null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false) + string(")")
|
||||||
|
}
|
||||||
if (func_name == "[]")
|
if (func_name == "[]")
|
||||||
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + string("])")
|
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + string("])")
|
||||||
// the post ones need to be post-ed specifically, and take the p off
|
// the post ones need to be post-ed specifically, and take the p off
|
||||||
@@ -633,12 +728,12 @@ obj c_generator (Object) {
|
|||||||
var in_function_param_type = func_type->parameter_types[i]
|
var in_function_param_type = func_type->parameter_types[i]
|
||||||
if (call_string != "")
|
if (call_string != "")
|
||||||
call_string += ", "
|
call_string += ", "
|
||||||
|
|
||||||
if (in_function_param_type->is_ref)
|
if (in_function_param_type->is_ref)
|
||||||
call_string += "&"
|
call_string += "&"
|
||||||
|
|
||||||
var param_type = get_ast_type(param)
|
var param_type = get_ast_type(param)
|
||||||
if (param_type->is_object() && !in_function_param_type->is_ref && param_type->indirection == 0 && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1)))) {
|
if (!in_function_param_type->is_ref && param_type->indirection == 0 && (param_type->is_adt() || (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1)))))) {
|
||||||
var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type->clone_without_ref(), null<ast_node>())
|
var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type->clone_without_ref(), null<ast_node>())
|
||||||
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>())
|
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>())
|
||||||
// have to pass false to the declaration generator, so can't do it through generate_statement
|
// have to pass false to the declaration generator, so can't do it through generate_statement
|
||||||
@@ -650,13 +745,8 @@ obj c_generator (Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var pre_call = string()
|
var pre_call = string()
|
||||||
// we now have temporary return variables for all objects, even without destruct so we can do chained method calls
|
// temporary returns if we're asked for them or we need them for destruct
|
||||||
// actually all non-ref returns, for chained any calls
|
var needs_temp_for_destruct = func_return_type->indirection == 0 && (func_return_type->is_adt() || (func_return_type->is_object() && has_method(func_return_type->type_def, "destruct", vector<*type>())))
|
||||||
// well, now only if we also pass in true for need_variable
|
|
||||||
// XXX this should change to only if we know we need it by having an enum or bool passed down to this call...
|
|
||||||
// if (func_return_type->is_object() && !func_return_type->is_ref && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())) {
|
|
||||||
// if (func_return_type->is_object() && !func_return_type->is_ref && func_return_type->indirection == 0) {
|
|
||||||
var needs_temp_for_destruct = func_return_type->is_object() && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())
|
|
||||||
if (!func_return_type->is_ref && (needs_temp_for_destruct || (!func_return_type->is_void() && need_variable)) ) {
|
if (!func_return_type->is_ref && (needs_temp_for_destruct || (!func_return_type->is_void() && need_variable)) ) {
|
||||||
// kind of ugly combo here of
|
// kind of ugly combo here of
|
||||||
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null<ast_node>())
|
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null<ast_node>())
|
||||||
@@ -676,6 +766,7 @@ obj c_generator (Object) {
|
|||||||
}
|
}
|
||||||
if (!is_function(node->function_call.func) || node->function_call.func->function.closed_variables.size()) {
|
if (!is_function(node->function_call.func) || node->function_call.func->function.closed_variables.size()) {
|
||||||
// not function, so we must be an identifier or function call return or something
|
// not function, so we must be an identifier or function call return or something
|
||||||
|
println(get_ast_name(node->function_call.func) + " is not a function! must be a lambda or something")
|
||||||
if (!dot_style_method_call) {
|
if (!dot_style_method_call) {
|
||||||
// lambda
|
// lambda
|
||||||
if (pre_call == "" && (!func_return_type->is_void() || func_return_type->indirection)) {
|
if (pre_call == "" && (!func_return_type->is_void() || func_return_type->indirection)) {
|
||||||
@@ -739,6 +830,7 @@ obj c_generator (Object) {
|
|||||||
ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func, defer_stack)
|
ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func, defer_stack)
|
||||||
ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, enclosing_func, defer_stack)
|
ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, enclosing_func, defer_stack)
|
||||||
ast_node::defer_statement(backing) return generate_defer_statement(node, enclosing_object, enclosing_func, defer_stack)
|
ast_node::defer_statement(backing) return generate_defer_statement(node, enclosing_object, enclosing_func, defer_stack)
|
||||||
|
ast_node::match_statement(backing) return generate_match_statement(node, enclosing_object, enclosing_func, defer_stack)
|
||||||
ast_node::value(backing) return generate_value(node, need_variable)
|
ast_node::value(backing) return generate_value(node, need_variable)
|
||||||
ast_node::identifier(backing) return generate_identifier(node, enclosing_object, enclosing_func)
|
ast_node::identifier(backing) return generate_identifier(node, enclosing_object, enclosing_func)
|
||||||
}
|
}
|
||||||
@@ -759,9 +851,8 @@ obj c_generator (Object) {
|
|||||||
base_type::integer() return indirection + string("int")
|
base_type::integer() return indirection + string("int")
|
||||||
base_type::floating() return indirection + string("float")
|
base_type::floating() return indirection + string("float")
|
||||||
base_type::double_precision() return indirection + string("double")
|
base_type::double_precision() return indirection + string("double")
|
||||||
base_type::object() {
|
base_type::object() return type->type_def->type_def.name
|
||||||
return type->type_def->type_def.name
|
base_type::adt() return type->type_def->adt_def.name
|
||||||
}
|
|
||||||
base_type::function() {
|
base_type::function() {
|
||||||
var temp = indirection + string("function_")
|
var temp = indirection + string("function_")
|
||||||
type->parameter_types.for_each(fun(parameter_type: *type) temp += type_decoration(parameter_type) + "_";)
|
type->parameter_types.for_each(fun(parameter_type: *type) temp += type_decoration(parameter_type) + "_";)
|
||||||
@@ -784,9 +875,8 @@ obj c_generator (Object) {
|
|||||||
base_type::integer() return string("int") + indirection
|
base_type::integer() return string("int") + indirection
|
||||||
base_type::floating() return string("float") + indirection
|
base_type::floating() return string("float") + indirection
|
||||||
base_type::double_precision() return string("double") + indirection
|
base_type::double_precision() return string("double") + indirection
|
||||||
base_type::object() {
|
base_type::object() return get_name(type->type_def) + indirection
|
||||||
return get_name(type->type_def) + indirection
|
base_type::adt() return get_name(type->type_def) + indirection
|
||||||
}
|
|
||||||
base_type::function() {
|
base_type::function() {
|
||||||
// maybe disregard indirection in the future?
|
// maybe disregard indirection in the future?
|
||||||
if (function_type_map.contains_key(*type))
|
if (function_type_map.contains_key(*type))
|
||||||
@@ -815,11 +905,14 @@ obj c_generator (Object) {
|
|||||||
var upper = backing.scope[string("~enclosing_scope")][0]
|
var upper = backing.scope[string("~enclosing_scope")][0]
|
||||||
result = backing.name
|
result = backing.name
|
||||||
if (is_template(upper))
|
if (is_template(upper))
|
||||||
upper->template.instantiated_map.reverse_get(node).for_each(fun(t: ref type) result += string("_") + type_decoration(&t);)
|
upper->template.instantiated_map.reverse_get(node).for_each(fun(t: ref type) result += string("_") + type_decoration(&t);)
|
||||||
|
}
|
||||||
|
ast_node::adt_def(backing) {
|
||||||
|
result = backing.name
|
||||||
}
|
}
|
||||||
ast_node::function(backing) {
|
ast_node::function(backing) {
|
||||||
// be careful, operators like . come through this
|
// be careful, operators like . come through this, but so do adt constructor funcs
|
||||||
if (!backing.body_statement)
|
if (!backing.body_statement && !backing.scope.contains_key(string("~enclosing_scope")))
|
||||||
return backing.name
|
return backing.name
|
||||||
if (backing.name == "main")
|
if (backing.name == "main")
|
||||||
return backing.name
|
return backing.name
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import io:*
|
|||||||
adt base_type {
|
adt base_type {
|
||||||
none,
|
none,
|
||||||
object,
|
object,
|
||||||
|
adt,
|
||||||
|
no_type_adt_option,
|
||||||
template,
|
template,
|
||||||
template_type,
|
template_type,
|
||||||
void_return,
|
void_return,
|
||||||
@@ -82,7 +84,10 @@ obj type (Object) {
|
|||||||
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 {
|
||||||
base.copy_construct(&base_type::object())
|
if (is_type_def(type_def_in))
|
||||||
|
base.copy_construct(&base_type::object())
|
||||||
|
else
|
||||||
|
base.copy_construct(&base_type::adt())
|
||||||
parameter_types.construct()
|
parameter_types.construct()
|
||||||
indirection = 0
|
indirection = 0
|
||||||
return_type = null<type>()
|
return_type = null<type>()
|
||||||
@@ -143,6 +148,8 @@ obj type (Object) {
|
|||||||
match (base) {
|
match (base) {
|
||||||
base_type::none() return all_string + string("none")
|
base_type::none() return all_string + string("none")
|
||||||
base_type::object() return all_string + type_def->type_def.name
|
base_type::object() return all_string + type_def->type_def.name
|
||||||
|
base_type::adt() return all_string + type_def->adt_def.name
|
||||||
|
base_type::no_type_adt_option() return all_string + "no_type_adt_option"
|
||||||
base_type::template() return all_string + string("template")
|
base_type::template() return all_string + string("template")
|
||||||
base_type::template_type() return all_string + string("template_type")
|
base_type::template_type() return all_string + string("template_type")
|
||||||
base_type::void_return() return all_string + string("void_return")
|
base_type::void_return() return all_string + string("void_return")
|
||||||
@@ -189,6 +196,12 @@ obj type (Object) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
fun is_adt(): bool {
|
||||||
|
match (base) {
|
||||||
|
base_type::adt() return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
fun is_function(): bool {
|
fun is_function(): bool {
|
||||||
match (base) {
|
match (base) {
|
||||||
base_type::function() return true
|
base_type::function() return true
|
||||||
@@ -201,5 +214,11 @@ obj type (Object) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
fun is_empty_adt_option(): bool {
|
||||||
|
match (base) {
|
||||||
|
base_type::no_type_adt_option() return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ obj vector<T> (Object, Serializable) {
|
|||||||
}
|
}
|
||||||
return newVec
|
return newVec
|
||||||
}
|
}
|
||||||
|
fun find_first_satisfying(func: fun(T):bool): T return filter(func)[0]
|
||||||
fun filter(func: fun(T):bool):vector<T> {
|
fun filter(func: fun(T):bool):vector<T> {
|
||||||
var newVec.construct(): vector<T>
|
var newVec.construct(): vector<T>
|
||||||
for (var i = 0; i < size; i++;)
|
for (var i = 0; i < size; i++;)
|
||||||
|
|||||||
Reference in New Issue
Block a user