Now using adt_lower, which also makes the backing deconstruct a reference, which makes sense
This commit is contained in:
@@ -9,7 +9,7 @@ import serialize:*
|
||||
import interpreter:*
|
||||
import os:*
|
||||
import ast_transformation:*
|
||||
/*import adt_lower:**/
|
||||
import adt_lower:*
|
||||
import defer_lower:*
|
||||
import c_line_control:*
|
||||
import c_generator:*
|
||||
@@ -100,8 +100,8 @@ fun main(argc: int, argv: **char):int {
|
||||
var importer.construct(parsers, ast_pass, vector(string(), base_dir + "/stdlib/")): importer
|
||||
importer.import(kraken_file_name)
|
||||
// Passes
|
||||
/*printlnerr("Lowering ADTs")*/
|
||||
/*adt_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)*/
|
||||
printlnerr("Lowering ADTs")
|
||||
adt_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
|
||||
printlnerr("Lowering Defer")
|
||||
defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
|
||||
if (interpret_instead) {
|
||||
|
||||
@@ -12,22 +12,199 @@ import ast_transformation:*
|
||||
import pass_common:*
|
||||
|
||||
fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
||||
var type_def_option_map = map<*ast_node, vector<*ast_node>>()
|
||||
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
|
||||
var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
|
||||
match(*node) {
|
||||
ast_node::adt_def(backing) {
|
||||
println(backing.name + ": entered!")
|
||||
/*println(backing.name + ": transforming!")*/
|
||||
type_def_option_map[node] = vector<*ast_node>()
|
||||
var replacement = ast_type_def_ptr(backing.name, false);
|
||||
// we're going to be replacing adt_def in the same ptr, so this works
|
||||
replacement->type_def.self_type = node->adt_def.self_type
|
||||
var replacement_this = make_this_noncached(replacement)
|
||||
var option_union = ast_type_def_ptr(backing.name + "_union", true);
|
||||
node->adt_def.options.for_each(fun(opt: *ast_node) {
|
||||
// want to keep them around
|
||||
/*if (opt->identifier.type->is_empty_adt_option())*/
|
||||
/*opt->identifier.type = type_ptr(base_type::character())*/
|
||||
if (!opt->identifier.type->is_empty_adt_option())
|
||||
option_union->type_def.variables.add(ast_declaration_statement_ptr(opt, null<ast_node>(), false))
|
||||
type_def_option_map[node].add(opt)
|
||||
})
|
||||
var option_union_type = type_ptr(option_union)
|
||||
option_union->type_def.self_type = option_union_type
|
||||
var option_union_ident = ast_identifier_ptr(string("data"), option_union_type, replacement)
|
||||
replacement->type_def.variables.add(ast_declaration_statement_ptr(option_union_ident, null<ast_node>(), false))
|
||||
add_to_scope("data", option_union_ident, replacement)
|
||||
var flag = ast_identifier_ptr(string("flag"), type_ptr(base_type::integer()), replacement)
|
||||
replacement->type_def.variables.add(ast_declaration_statement_ptr(flag, null<ast_node>(), false))
|
||||
add_to_scope("flag", flag, replacement)
|
||||
add_before_in(option_union, node, parent_chain)
|
||||
var enclosing_scope = node->adt_def.scope[string("~enclosing_scope")][0]
|
||||
var idx = 0
|
||||
node->adt_def.option_funcs.for_each(fun(func: *ast_node) {
|
||||
var adt_type = replacement->type_def.self_type
|
||||
var block = ast_code_block_ptr()
|
||||
func->function.body_statement = ast_statement_ptr(block)
|
||||
var to_ret = ast_identifier_ptr(string("to_ret"), adt_type, block)
|
||||
block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(to_ret, null<ast_node>(), false)))
|
||||
|
||||
var value = ast_value_ptr(to_string(idx), type_ptr(base_type::integer()))
|
||||
block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call(".", vector(to_ret, flag)), value)))
|
||||
/*var opt = option_union->type_def.variables[idx]->declaration_statement.identifier*/
|
||||
var opt = type_def_option_map[node][idx]
|
||||
var lvalue = make_operator_call(".", vector(make_operator_call(".", vector(to_ret, option_union_ident)), opt))
|
||||
if (func->function.parameters.size) {
|
||||
// do copy_construct if it should
|
||||
block->code_block.children.add(ast_statement_ptr(assign_or_copy_construct_statement(lvalue, func->function.parameters[0])))
|
||||
}
|
||||
/*} else {*/
|
||||
/*// init our placeholders with 0 for equality, etc*/
|
||||
/*block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(lvalue, ast_value_ptr(string("0"), type_ptr(base_type::character())))))*/
|
||||
/*}*/
|
||||
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(to_ret)))
|
||||
add_before_in(func, node, parent_chain)
|
||||
add_to_scope(func->function.name, func, enclosing_scope)
|
||||
add_to_scope("~enclosing_scope", enclosing_scope, func)
|
||||
idx++
|
||||
})
|
||||
node->adt_def.regular_funcs.for_each(fun(func: *ast_node) {
|
||||
var block = ast_code_block_ptr()
|
||||
func->function.body_statement = ast_statement_ptr(block)
|
||||
if (func->function.name == "operator==") {
|
||||
var other = func->function.parameters[0]
|
||||
var if_stmt = ast_if_statement_ptr(make_operator_call("!=", vector(make_operator_call("->", vector(replacement_this, flag)), make_operator_call(".", vector(other, flag)))))
|
||||
if_stmt->if_statement.then_part = ast_statement_ptr(ast_return_statement_ptr(ast_value_ptr(string("false"), type_ptr(base_type::boolean()))))
|
||||
block->code_block.children.add(if_stmt)
|
||||
|
||||
/*for (var i = 0; i < option_union->type_def.variables.size; i++;) {*/
|
||||
for (var i = 0; i < type_def_option_map[node].size; i++;) {
|
||||
if (get_ast_type(type_def_option_map[node][i])->is_empty_adt_option())
|
||||
continue
|
||||
var if_stmt_inner = ast_if_statement_ptr(make_operator_call("==", vector(make_operator_call("->", vector(replacement_this, flag)), ast_value_ptr(to_string(i), type_ptr(base_type::integer())))))
|
||||
/*var option = option_union->type_def.variables[i]->declaration_statement.identifier*/
|
||||
var option = type_def_option_map[node][i]
|
||||
var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option))
|
||||
var their_option = make_operator_call(".", vector(make_operator_call(".", vector(other, option_union_ident)), option))
|
||||
if_stmt_inner->if_statement.then_part = ast_statement_ptr(ast_return_statement_ptr(possible_object_equality(our_option, their_option)))
|
||||
block->code_block.children.add(if_stmt_inner)
|
||||
}
|
||||
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(ast_value_ptr(string("true"), type_ptr(base_type::boolean())))))
|
||||
} else if (func->function.name == "operator!=") {
|
||||
var other = func->function.parameters[0]
|
||||
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(make_operator_call("!", vector(make_method_call(replacement_this, "operator==", vector(other)))))))
|
||||
} else if (func->function.name == "construct") {
|
||||
var value = ast_value_ptr(string("-1"), type_ptr(base_type::integer()))
|
||||
block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), value)))
|
||||
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(replacement_this)))
|
||||
} else if (func->function.name == "copy_construct") {
|
||||
var other = func->function.parameters[0]
|
||||
block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), make_operator_call("->", vector(other, flag)))))
|
||||
/*for (var i = 0; i < option_union->type_def.variables.size; i++;) {*/
|
||||
for (var i = 0; i < type_def_option_map[node].size; i++;) {
|
||||
if (get_ast_type(type_def_option_map[node][i])->is_empty_adt_option())
|
||||
continue
|
||||
var if_stmt_inner = ast_if_statement_ptr(make_operator_call("==", vector(make_operator_call("->", vector(replacement_this, flag)), ast_value_ptr(to_string(i), type_ptr(base_type::integer())))))
|
||||
/*var option = option_union->type_def.variables[i]->declaration_statement.identifier*/
|
||||
var option = type_def_option_map[node][i]
|
||||
var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option))
|
||||
var their_option = make_operator_call(".", vector(make_operator_call("->", vector(other, option_union_ident)), option))
|
||||
if_stmt_inner->if_statement.then_part = ast_statement_ptr(assign_or_copy_construct_statement(our_option, their_option))
|
||||
block->code_block.children.add(if_stmt_inner)
|
||||
}
|
||||
} else if (func->function.name == "operator=") {
|
||||
var other = func->function.parameters[0]
|
||||
block->code_block.children.add(ast_statement_ptr(make_method_call(replacement_this, "destruct", vector<*ast_node>())))
|
||||
block->code_block.children.add(ast_statement_ptr(make_method_call(replacement_this, "copy_construct", vector(make_operator_call("&", vector(other))))))
|
||||
} else if (func->function.name == "destruct") {
|
||||
for (var i = 0; i < type_def_option_map[node].size; i++;) {
|
||||
var option = type_def_option_map[node][i]
|
||||
var option_type = get_ast_type(option)
|
||||
if (option_type->is_empty_adt_option())
|
||||
continue
|
||||
if (option_type->indirection == 0 && option_type->is_object() && has_method(option_type->type_def, "destruct", vector<*type>())) {
|
||||
var if_stmt_inner = ast_if_statement_ptr(make_operator_call("==", vector(make_operator_call("->", vector(replacement_this, flag)), ast_value_ptr(to_string(i), type_ptr(base_type::integer())))))
|
||||
var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option))
|
||||
if_stmt_inner->if_statement.then_part = ast_statement_ptr(make_method_call(our_option, "destruct", vector<*ast_node>()))
|
||||
block->code_block.children.add(if_stmt_inner)
|
||||
}
|
||||
}
|
||||
} else error("impossible adt method")
|
||||
replacement->type_def.methods.add(func)
|
||||
add_to_scope(func->function.name, func, replacement)
|
||||
add_to_scope("~enclosing_scope", replacement, func)
|
||||
})
|
||||
add_to_scope("~enclosing_scope", enclosing_scope, option_union)
|
||||
add_to_scope("~enclosing_scope", enclosing_scope, replacement)
|
||||
*node = *replacement
|
||||
}
|
||||
}
|
||||
}
|
||||
var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
|
||||
run_on_tree(helper_before, empty_pass_half, syntax_ast_pair.second)
|
||||
})
|
||||
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
|
||||
var second_helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
|
||||
match(*node) {
|
||||
ast_node::adt_def(backing) {
|
||||
println(backing.name + ": exited!")
|
||||
ast_node::match_statement(backing) {
|
||||
/*println("Match statement!")*/
|
||||
var block = ast_code_block_ptr()
|
||||
var value = backing.value
|
||||
/*var holder = ast_identifier_ptr(string("holder"), get_ast_type(value), block)*/
|
||||
var holder = ast_identifier_ptr(string("holder"), get_ast_type(value)->clone_with_increased_indirection(), block)
|
||||
block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(holder, null<ast_node>(), false)))
|
||||
// dirty hack
|
||||
var if_hack = ast_if_statement_ptr(ast_assignment_statement_ptr(holder, make_operator_call("&", vector(value))))
|
||||
block->code_block.children.add(if_hack)
|
||||
var if_block = ast_code_block_ptr()
|
||||
if_hack->if_statement.then_part = if_block
|
||||
/*block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(holder, make_operator_call("&", vector(value)), false)))*/
|
||||
backing.cases.for_each(fun(case_stmt: *ast_node) {
|
||||
var option = case_stmt->case_statement.option
|
||||
/*println(string("case: ") + get_ast_name(option))*/
|
||||
var flag = get_from_scope(get_ast_type(value)->type_def, "flag")
|
||||
var data = get_from_scope(get_ast_type(value)->type_def, "data")
|
||||
var option_num = -7
|
||||
if (!type_def_option_map.contains_key(get_ast_type(value)->type_def))
|
||||
error("trying to match on non-adt")
|
||||
for (var i = 0; i < type_def_option_map[get_ast_type(value)->type_def].size; i++;)
|
||||
if (type_def_option_map[get_ast_type(value)->type_def][i] == option)
|
||||
option_num = i;
|
||||
/*var condition = make_operator_call("==", vector(make_operator_call(".", vector(holder, flag)), ast_value_ptr(to_string(option_num), type_ptr(base_type::integer()))))*/
|
||||
var condition = make_operator_call("==", vector(make_operator_call("->", vector(holder, flag)), ast_value_ptr(to_string(option_num), type_ptr(base_type::integer()))))
|
||||
var if_stmt = ast_if_statement_ptr(condition)
|
||||
var inner_block = ast_code_block_ptr()
|
||||
var unpack_ident = case_stmt->case_statement.unpack_ident
|
||||
if (unpack_ident) {
|
||||
/*var get_option = make_operator_call(".", vector(make_operator_call(".", vector(holder, data)), option))*/
|
||||
var get_option = make_operator_call(".", vector(make_operator_call("->", vector(holder, data)), option))
|
||||
get_option = make_operator_call("&", vector(get_option))
|
||||
unpack_ident->identifier.type = unpack_ident->identifier.type->clone_with_ref()
|
||||
inner_block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(unpack_ident, get_option, false)))
|
||||
}
|
||||
inner_block->code_block.children.add(case_stmt->case_statement.statement)
|
||||
if_stmt->if_statement.then_part = inner_block
|
||||
if_block->code_block.children.add(if_stmt)
|
||||
})
|
||||
*node = *block
|
||||
}
|
||||
ast_node::function_call(backing) {
|
||||
if (is_function(backing.func) && (backing.func->function.name == "." || backing.func->function.name == "->")) {
|
||||
var left_type = get_ast_type(backing.parameters[0])
|
||||
if (left_type->is_object() && is_identifier(backing.parameters[1])) {
|
||||
for (var i = 0; i < left_type->type_def->type_def.variables.size; i++;)
|
||||
if (left_type->type_def->type_def.variables[i]->declaration_statement.identifier == backing.parameters[1])
|
||||
return;
|
||||
/*println(backing.parameters[1]->identifier.name + " getting, adt . or -> call!")*/
|
||||
var object = node->function_call.parameters[0]
|
||||
node->function_call.parameters[0] = make_operator_call(backing.func->function.name, vector(object, get_from_scope(left_type->type_def, "data")))
|
||||
node->function_call.func = get_builtin_function(".", vector(get_ast_type(get_from_scope(left_type->type_def, "data")), get_ast_type(backing.parameters[1])))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
run_on_tree(helper_before, helper_after, syntax_ast_pair.second)
|
||||
run_on_tree(second_helper, empty_pass_half, syntax_ast_pair.second)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -983,7 +983,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 {
|
||||
var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);)
|
||||
var possible_overload = null<ast_node>()
|
||||
if ((parameter_types[0]->is_adt() || parameter_types[0]->is_object()) && parameter_types[0]->indirection == 0) {
|
||||
if (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))
|
||||
if (!possible_overload) {
|
||||
var inherited_replacements = map<string, *type>()
|
||||
@@ -1112,6 +1112,10 @@ obj ast_transformation (Object) {
|
||||
return fitting_functions.max(fun(a: pair<*ast_node, int>, b: pair<*ast_node, int>): bool return a.second < b.second;).first
|
||||
}
|
||||
}
|
||||
fun get_from_scope(node: *ast_node, member: *char): *ast_node
|
||||
return get_from_scope(node, string(member))
|
||||
fun get_from_scope(node: *ast_node, member: string): *ast_node
|
||||
return get_ast_scope(node)->get(member).first()
|
||||
fun has_method(object: *ast_node, name: *char, parameter_types: vector<*type>): bool return has_method(object, string(name), parameter_types);
|
||||
fun has_method(object: *ast_node, name: string, parameter_types: vector<*type>): bool {
|
||||
/*println("HAS METHOD:")*/
|
||||
@@ -1131,13 +1135,18 @@ fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<*
|
||||
}
|
||||
fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vector<*ast_node>): *ast_node {
|
||||
/*println("MAKE METHOD CALL IN:")*/
|
||||
var method_access = ast_function_call_ptr(get_builtin_function(string("."), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method))
|
||||
var access_op = "."
|
||||
if (get_ast_type(object_ident)->indirection)
|
||||
access_op = "->"
|
||||
var method_access = ast_function_call_ptr(get_builtin_function(string(access_op), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method))
|
||||
return ast_function_call_ptr(method_access, parameters)
|
||||
}
|
||||
fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params);
|
||||
fun make_operator_call(func: string, params: vector<*ast_node>): *ast_node {
|
||||
return ast_function_call_ptr(get_builtin_function(func, params.map(fun(p:*ast_node): *type return get_ast_type(p);)), params)
|
||||
}
|
||||
fun get_builtin_function(name: *char, param_types: vector<*type>): *ast_node
|
||||
return get_builtin_function(string(name), param_types, null<tree<symbol>>())
|
||||
fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node
|
||||
return get_builtin_function(name, param_types, null<tree<symbol>>())
|
||||
fun get_builtin_function(name: string, param_types: vector<*type>, syntax: *tree<symbol>): *ast_node {
|
||||
|
||||
@@ -223,7 +223,7 @@ obj c_generator (Object) {
|
||||
|
||||
// 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>()))))
|
||||
if (!parameter_type->is_ref && parameter_type->indirection == 0 && (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) {
|
||||
@@ -261,119 +261,7 @@ obj c_generator (Object) {
|
||||
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
function_definitions += "}\n"
|
||||
} else if (!backing.is_extern) {
|
||||
// adt constructor if no body and not extern
|
||||
// wow. no pass in for no this
|
||||
enclosing_object = get_ast_scope(child)->get(string("~enclosing_scope"))[0]
|
||||
// if this is an option constructor
|
||||
if (enclosing_object->adt_def.options.any_true(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;)) {
|
||||
var option_ident = enclosing_object->adt_def.options.find_first_satisfying(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;)
|
||||
var option_type = option_ident->identifier.type
|
||||
function_definitions += " { \n"
|
||||
var to_ret_ident = ast_identifier_ptr("to_ret", enclosing_object->type_def.self_type, enclosing_object)
|
||||
function_definitions += type_to_c(enclosing_object->adt_def.self_type) + " "+ get_name(to_ret_ident) + ";\n"
|
||||
function_definitions += get_name(to_ret_ident) + ".flag = " + string("enum_opt_") + get_name(option_ident) + ";\n"
|
||||
if (option_type->is_empty_adt_option())
|
||||
function_definitions += "/*no inner data*/\n"
|
||||
else {
|
||||
var param = backing.parameters[0]
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "copy_construct", vector(option_type->clone_with_increased_indirection()))))) {
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call(".", vector(to_ret_ident, option_ident)), "copy_construct", vector(make_operator_call("&", vector(param))))), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
} else {
|
||||
function_definitions += get_name(to_ret_ident) +".data." + get_name(option_ident) + " = " + get_name(param) + ";\n"
|
||||
}
|
||||
}
|
||||
function_definitions += "return " + get_name(to_ret_ident) + ";\n"
|
||||
function_definitions += "}\n"
|
||||
} else {
|
||||
// this is one of the other functions instead
|
||||
var adt_this = ast_identifier_ptr("this", enclosing_object->type_def.self_type->clone_with_indirection(1), enclosing_object)
|
||||
function_definitions += "{\n"
|
||||
if (backing.name == "operator==") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*operator==*/"
|
||||
function_definitions += string("if (this->flag != ") + generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string() + ".flag) return false;\n"
|
||||
enclosing_object->adt_def.options.for_each(fun(option: *ast_node) {
|
||||
var option_type = option->identifier.type
|
||||
function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string() + ") {\n"
|
||||
if (option_type->is_empty_adt_option()) {
|
||||
function_definitions += "return true;"
|
||||
} else {
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "operator==", vector(option_type))))) {
|
||||
defer_stack.push(make_pair(false, stack<*ast_node>()))
|
||||
var equals_res = generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "operator==", vector(make_operator_call(".", vector(param, option))))), null<ast_node>(), null<ast_node>(), &defer_stack, false)
|
||||
equals_res.value = string("bool result = ") + equals_res.value + ";\n"
|
||||
equals_res.post += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
defer_stack.pop()
|
||||
function_definitions += equals_res.one_string() + "return result;\n"
|
||||
} else if (option_type->is_object()) {
|
||||
// if we are an object but don't define an operator== function (or it is templated)
|
||||
// always return false.
|
||||
function_definitions += "return false;\n"
|
||||
} else {
|
||||
var option_name = generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string()
|
||||
var param_name = generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string()
|
||||
function_definitions += string("return this->data.") + option_name + " == " + param_name + ".data." + option_name + ";\n"
|
||||
}
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
})
|
||||
} else if (backing.name == "operator!=") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*operator!=*/"
|
||||
defer_stack.push(make_pair(false, stack<*ast_node>()))
|
||||
var equals_res = generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "operator==", vector(param))), null<ast_node>(), null<ast_node>(), &defer_stack, false)
|
||||
equals_res.value = string("bool result = !") + equals_res.value + ";\n"
|
||||
equals_res.post += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
defer_stack.pop()
|
||||
function_definitions += equals_res.one_string() + "return result;\n"
|
||||
} else if (backing.name == "construct") {
|
||||
function_definitions += "/*construct*/"
|
||||
function_definitions += "this->flag = -1;\n"
|
||||
function_definitions += "return this;\n"
|
||||
} else if (backing.name == "copy_construct") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*copy_construct*/"
|
||||
function_definitions += string("this->flag = ") + generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string() + "->flag;\n"
|
||||
enclosing_object->adt_def.options.for_each(fun(option: *ast_node) {
|
||||
var option_type = option->identifier.type
|
||||
function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string() + ") {\n"
|
||||
if (option_type->is_empty_adt_option()) {
|
||||
function_definitions += "/*no data to copy*/;"
|
||||
} else {
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "copy_construct", vector(option_type->clone_with_increased_indirection()))))) {
|
||||
// don't really need the defer_stack
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "copy_construct", vector(make_operator_call("&", vector(make_operator_call("->", vector(param, option))))))), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
} else {
|
||||
var option_name = generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string()
|
||||
var param_name = generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string()
|
||||
function_definitions += string("this->data.") + option_name + " = " + param_name + "->data." + option_name + ";\n"
|
||||
}
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
})
|
||||
} else if (backing.name == "operator=") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*operator=*/"
|
||||
defer_stack.push(make_pair(false, stack<*ast_node>()))
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "destruct", vector<*ast_node>())), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "copy_construct", vector(make_operator_call("&", vector(param))))), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
defer_stack.pop()
|
||||
} else if (backing.name == "destruct") {
|
||||
function_definitions += "/*destruct*/"
|
||||
enclosing_object->adt_def.options.for_each(fun(option: *ast_node) {
|
||||
var option_type = option->identifier.type
|
||||
function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string() + ") {\n"
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "destruct", vector<*type>())))) {
|
||||
// don't really need the defer_stack
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "destruct", vector<*ast_node>())), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
})
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
}
|
||||
error("Empty function statement and not extern - no ADTs anymore!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,12 +320,7 @@ obj c_generator (Object) {
|
||||
})
|
||||
}
|
||||
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)
|
||||
})
|
||||
error("ADT remaining!")
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -464,25 +347,7 @@ obj c_generator (Object) {
|
||||
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>(), false), 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);
|
||||
})
|
||||
error("no adt, but how did we get this far?")
|
||||
}
|
||||
structs += "};\n"
|
||||
})
|
||||
@@ -545,7 +410,7 @@ obj c_generator (Object) {
|
||||
pre_stuff = string("extern ") + pre_stuff
|
||||
var to_ret = code_triple(pre_stuff, string(), string())
|
||||
if (node->declaration_statement.expression) {
|
||||
if (ident_type->indirection == 0 && (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()))))) {
|
||||
if (ident_type->indirection == 0 && (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 += 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 {
|
||||
@@ -565,7 +430,8 @@ obj c_generator (Object) {
|
||||
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)
|
||||
}
|
||||
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>()))))
|
||||
// reference can happen because some passes generate them (adt_lower right now)
|
||||
if (add_to_defer && !ident_type->is_ref && ident_type->indirection == 0 && (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>())))
|
||||
return to_ret
|
||||
}
|
||||
@@ -593,7 +459,8 @@ obj c_generator (Object) {
|
||||
// stick another stack on
|
||||
defer_stack->push(make_pair(true, stack<*ast_node>()))
|
||||
// gotta take off last semicolon
|
||||
var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||
/*var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)*/
|
||||
var init = generate(node->for_loop.init, enclosing_object, enclosing_func, defer_stack, false)
|
||||
var cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||
var update = generate(node->for_loop.update, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||
var do_update_name = string("do_update") + get_id()
|
||||
@@ -645,7 +512,7 @@ obj c_generator (Object) {
|
||||
if ((function_return_type->is_object() || return_value_type->is_object()) && !function_return_type->equality(return_value_type, false))
|
||||
// note the clone with decreased indirection because of the clone with increased indirection above
|
||||
error(ast_to_syntax[node], string("return type does not match: ") + function_return_type->to_string() + ", " + return_value_type->to_string());
|
||||
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)))))) {
|
||||
if (!function_return_type->is_ref && return_value_type->indirection == 0 && (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()
|
||||
} else {
|
||||
var refamp = string()
|
||||
@@ -850,11 +717,7 @@ obj c_generator (Object) {
|
||||
// don't propegate enclosing function down right of access
|
||||
// XXX what about enclosing object? should it be the thing on the left?
|
||||
if (func_name == "." || func_name == "->") {
|
||||
// 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(")")
|
||||
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(")")
|
||||
}
|
||||
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("])")
|
||||
@@ -886,7 +749,7 @@ obj c_generator (Object) {
|
||||
call_string += "&"
|
||||
|
||||
var param_type = get_ast_type(param)
|
||||
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)))))) {
|
||||
if (!in_function_param_type->is_ref && param_type->indirection == 0 && (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 declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>(), false)
|
||||
// have to pass false to the declaration generator, so can't do it through generate_statement
|
||||
@@ -899,7 +762,7 @@ obj c_generator (Object) {
|
||||
}
|
||||
var pre_call = string()
|
||||
// temporary returns if we're asked for them or we need them for destruct
|
||||
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>())))
|
||||
var needs_temp_for_destruct = func_return_type->indirection == 0 && (func_return_type->is_object() && 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)) ) {
|
||||
// kind of ugly combo here of
|
||||
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null<ast_node>())
|
||||
@@ -971,7 +834,7 @@ obj c_generator (Object) {
|
||||
return code_triple("sizeof(") + type_to_c(node->compiler_intrinsic.type_parameters[0]) + ")"
|
||||
} else if (node->compiler_intrinsic.intrinsic == "link") {
|
||||
node->compiler_intrinsic.parameters.for_each(fun(str: string) {
|
||||
linker_string += string("-l") + str + " "
|
||||
linker_string += string("-l") + str + " "
|
||||
})
|
||||
return code_triple()
|
||||
}
|
||||
@@ -1028,7 +891,6 @@ obj c_generator (Object) {
|
||||
base_type::floating() return indirection + string("float")
|
||||
base_type::double_precision() return indirection + string("double")
|
||||
base_type::object() return cify_name(type->type_def->type_def.name)
|
||||
base_type::adt() return type->type_def->adt_def.name
|
||||
base_type::function() {
|
||||
var temp = indirection + string("function_")
|
||||
type->parameter_types.for_each(fun(parameter_type: *type) temp += type_decoration(parameter_type) + "_";)
|
||||
@@ -1058,7 +920,6 @@ obj c_generator (Object) {
|
||||
base_type::floating() return string("float") + indirection
|
||||
base_type::double_precision() return string("double") + indirection
|
||||
base_type::object() return get_name(type->type_def) + indirection
|
||||
base_type::adt() return get_name(type->type_def) + indirection
|
||||
base_type::function() {
|
||||
// maybe disregard indirection in the future?
|
||||
type = type->clone_with_indirection(0,false)
|
||||
@@ -1094,7 +955,7 @@ obj c_generator (Object) {
|
||||
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
|
||||
error("shouldn't have adt")
|
||||
}
|
||||
ast_node::function(backing) {
|
||||
// be careful, operators like . come through this, but so do adt constructor funcs
|
||||
|
||||
@@ -20,7 +20,6 @@ fun get_line(node: *tree<symbol>, name: string): *ast_node {
|
||||
fun c_line_control(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
||||
var first = true
|
||||
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
|
||||
var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {}
|
||||
var helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
|
||||
match(*node) {
|
||||
ast_node::statement(backing) {
|
||||
@@ -32,7 +31,7 @@ fun c_line_control(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, as
|
||||
}
|
||||
}
|
||||
if (first)
|
||||
run_on_tree(helper, helper_after, syntax_ast_pair.second)
|
||||
run_on_tree(helper, empty_pass_half, syntax_ast_pair.second)
|
||||
first = false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -288,7 +288,6 @@ fun store_into_variable(to: value, from: value) {
|
||||
// TODO - check to make sure that we don't have to cast pre assign (perhaps alwyas send through the cast?)
|
||||
match (variable.second->base) {
|
||||
base_type::object() { assert(is_object_like(from), "mismatching assignemnt types - from is not object"); memmove(variable.first, from.object_like.first, type_size(from.object_like.second)); }
|
||||
base_type::adt() error(string("trying to store into an adt: ") + variable.second->to_string())
|
||||
base_type::function() { assert(is_function(from), "mismatching assignemnt types - from is not function"); *(variable.first) cast *pair<*ast_node, map<*ast_node,value>> = from.function; }
|
||||
base_type::boolean() { assert(is_boolean(from), "mismatching assignemnt types - from is not boolean"); *(variable.first) cast *bool = from.boolean; }
|
||||
base_type::character() { assert(is_character(from), "mismatching assignemnt types - from is not character"); *(variable.first) cast *char = from.character; }
|
||||
@@ -493,7 +492,7 @@ fun pop_and_free(var_stack: *stack<map<*ast_node, value>>) {
|
||||
|
||||
obj interpreter (Object) {
|
||||
var ast_to_syntax: map<*ast_node, *tree<symbol>>
|
||||
var name_ast_map: map<string, pair<*tree<symbol>,*ast_node>>
|
||||
var name_ast_map: map<string, pair<*tree<symbol>,*ast_node>>
|
||||
var globals: map<*ast_node, value>
|
||||
var id_counter: int
|
||||
fun get_id(): string return to_string(id_counter++);
|
||||
@@ -615,7 +614,7 @@ obj interpreter (Object) {
|
||||
var parameters = vector<value>()
|
||||
var parameter_sources = vector<*ast_node>()
|
||||
// if we don't have to copy_construct params (is an operator, or has no object params)
|
||||
if (func_name == "&" || !func_call_parameters.any_true(fun(p: *ast_node): bool return get_ast_type(p)->is_object_like() && get_ast_type(p)->indirection == 0;)) {
|
||||
if (func_name == "&" || !func_call_parameters.any_true(fun(p: *ast_node): bool return get_ast_type(p)->is_object() && get_ast_type(p)->indirection == 0;)) {
|
||||
parameters = func_call_parameters.map(fun(p: *ast_node): value return interpret(p, var_stack, enclosing_object, enclosing_func, defer_stack).first;)
|
||||
if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/"
|
||||
|| func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">="
|
||||
@@ -694,7 +693,7 @@ obj interpreter (Object) {
|
||||
else
|
||||
new_var_stack.top()[param_ident] = wrap_into_variable(parameters[i])
|
||||
} else {
|
||||
new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
|
||||
new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
|
||||
//HERE
|
||||
(new_var_stack.top()[param_ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct()
|
||||
store_into_variable(new_var_stack.top()[param_ident], get_real_value(parameters[i]))
|
||||
@@ -716,17 +715,17 @@ obj interpreter (Object) {
|
||||
new_var_stack.top()[param_ident] = param
|
||||
else
|
||||
new_var_stack.top()[param_ident] = wrap_into_variable(param)
|
||||
} else if (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_increased_indirection()))))) {
|
||||
} else if (param_type->indirection == 0 && (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_increased_indirection())))) {
|
||||
var temp_ident = ast_identifier_ptr(string("temporary_param") + get_id(), param_type, null<ast_node>())
|
||||
var_stack->top()[temp_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
|
||||
var_stack->top()[temp_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
|
||||
//HERE
|
||||
(var_stack->top()[temp_ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct()
|
||||
interpret(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(parameter_sources[i]))))), var_stack, enclosing_object, enclosing_func, ¶m_defer_stack)
|
||||
new_var_stack.top()[param_ident] = var_stack->top()[temp_ident]
|
||||
new_var_stack.top()[param_ident] = var_stack->top()[temp_ident]
|
||||
// note that we destruct the temp version because that's the one in the var_stack
|
||||
param_defer_stack.push(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())))
|
||||
} else {
|
||||
new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
|
||||
new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
|
||||
//HERE
|
||||
(new_var_stack.top()[param_ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct()
|
||||
store_into_variable(new_var_stack.top()[param_ident], get_real_value(interpret(parameter_sources[i], var_stack, enclosing_object, enclosing_func, ¶m_defer_stack).first))
|
||||
@@ -744,7 +743,7 @@ obj interpreter (Object) {
|
||||
pop_and_free(var_stack)
|
||||
}
|
||||
var return_type = func->function.type->return_type
|
||||
if (!return_type->is_ref && return_type->indirection == 0 && (return_type->is_adt() || (return_type->is_object() && has_method(return_type->type_def, "destruct", vector<*type>())))) {
|
||||
if (!return_type->is_ref && return_type->indirection == 0 && (return_type->is_object() && has_method(return_type->type_def, "destruct", vector<*type>()))) {
|
||||
var temp_ident = ast_identifier_ptr(string("temporary_return_to_be_destructed") + get_id(), return_type, null<ast_node>())
|
||||
var_stack->top()[temp_ident] = value::variable(make_pair(to_ret.object_like.first, to_ret.object_like.second))
|
||||
defer_stack->push(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())))
|
||||
@@ -829,7 +828,7 @@ obj interpreter (Object) {
|
||||
fun interpret_if_statement(if_stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair<value, control_flow> {
|
||||
var_stack->push(map<*ast_node,value>())
|
||||
var inner_defer_stack = stack<*ast_node>()
|
||||
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
if (truthy(interpret(if_stmt->if_statement.condition, var_stack, enclosing_object, enclosing_func, &inner_defer_stack).first)) {
|
||||
value_from_inside = interpret(if_stmt->if_statement.then_part, var_stack, enclosing_object, enclosing_func, &inner_defer_stack)
|
||||
} else if (if_stmt->if_statement.else_part) {
|
||||
@@ -842,7 +841,7 @@ obj interpreter (Object) {
|
||||
fun interpret_while_loop(while_loop: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair<value, control_flow> {
|
||||
var_stack->push(map<*ast_node,value>())
|
||||
var inner_defer_stack = stack<*ast_node>()
|
||||
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
var going = true
|
||||
while (going && truthy(interpret(while_loop->while_loop.condition, var_stack, enclosing_object, enclosing_func, &inner_defer_stack).first)) {
|
||||
value_from_inside = interpret(while_loop->while_loop.statement, var_stack, enclosing_object, enclosing_func, &inner_defer_stack)
|
||||
@@ -851,7 +850,7 @@ obj interpreter (Object) {
|
||||
if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre())
|
||||
going = false
|
||||
if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con())
|
||||
value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
}
|
||||
interpret_from_defer_stack(&inner_defer_stack, var_stack, value::void_nothing(), enclosing_func)
|
||||
pop_and_free(var_stack)
|
||||
@@ -860,7 +859,7 @@ obj interpreter (Object) {
|
||||
fun interpret_for_loop(for_loop: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> {
|
||||
var defer_stack = stack<*ast_node>()
|
||||
var_stack->push(map<*ast_node,value>())
|
||||
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
var going = true
|
||||
interpret(for_loop->for_loop.init, var_stack, enclosing_object, enclosing_func, &defer_stack)
|
||||
while (going && truthy(interpret(for_loop->for_loop.condition, var_stack, enclosing_object, enclosing_func, &defer_stack).first)) {
|
||||
@@ -868,7 +867,7 @@ obj interpreter (Object) {
|
||||
if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre())
|
||||
going = false
|
||||
if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con())
|
||||
value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
|
||||
|
||||
// only run update if we're not breaking or continuing
|
||||
if (going)
|
||||
@@ -931,11 +930,11 @@ obj interpreter (Object) {
|
||||
var to_ret.construct(): value
|
||||
if (get_ast_type(enclosing_func)->return_type->is_ref) {
|
||||
to_ret = interpret(return_expression, var_stack, enclosing_object, enclosing_func, defer_stack).first
|
||||
} else if (return_type->indirection == 0 && (return_type->is_adt() || (return_type->is_object() && has_method(return_type->type_def, "copy_construct", vector(return_type->clone_with_increased_indirection()))))) {
|
||||
} else if (return_type->indirection == 0 && (return_type->is_object() && has_method(return_type->type_def, "copy_construct", vector(return_type->clone_with_increased_indirection())))) {
|
||||
var_stack->push(map<*ast_node,value>())
|
||||
var inner_defer_stack = stack<*ast_node>()
|
||||
var temp_ident = ast_identifier_ptr(string("temporary_return"), return_type, null<ast_node>())
|
||||
var_stack->top()[temp_ident] = value::variable(make_pair(malloc(type_size(return_type)), return_type))
|
||||
var_stack->top()[temp_ident] = value::variable(make_pair(malloc(type_size(return_type)), return_type))
|
||||
interpret(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_expression))))), var_stack, enclosing_object, enclosing_func, &inner_defer_stack)
|
||||
to_ret = var_stack->top()[temp_ident]
|
||||
interpret_from_defer_stack(&inner_defer_stack, var_stack, enclosing_object, enclosing_func)
|
||||
@@ -943,7 +942,7 @@ obj interpreter (Object) {
|
||||
var_stack->pop()
|
||||
/*pop_and_free(var_stack)*/
|
||||
} else {
|
||||
to_ret = value::variable(make_pair(malloc(type_size(return_type)), return_type))
|
||||
to_ret = value::variable(make_pair(malloc(type_size(return_type)), return_type))
|
||||
//HERE
|
||||
(to_ret.variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct()
|
||||
var ret_val = interpret(return_expression, var_stack, enclosing_object, enclosing_func, defer_stack).first
|
||||
@@ -954,11 +953,11 @@ obj interpreter (Object) {
|
||||
fun interpret_declaration_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair<value, control_flow> {
|
||||
var ident = stmt->declaration_statement.identifier
|
||||
var ident_type = ident->identifier.type
|
||||
var_stack->top()[ident] = value::variable(make_pair(malloc(type_size(ident_type)),ident_type))
|
||||
var_stack->top()[ident] = value::variable(make_pair(malloc(type_size(ident_type)),ident_type))
|
||||
//HERE
|
||||
(var_stack->top()[ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct()
|
||||
if (stmt->declaration_statement.expression) {
|
||||
if (ident_type->indirection == 0 && (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(stmt->declaration_statement.expression)->clone_with_increased_indirection())))))
|
||||
if (ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(stmt->declaration_statement.expression)->clone_with_increased_indirection()))))
|
||||
interpret(ast_statement_ptr(make_method_call(ident, "copy_construct", vector(make_operator_call("&", vector(stmt->declaration_statement.expression))))), var_stack, enclosing_object, enclosing_func, defer_stack)
|
||||
else
|
||||
store_into_variable(var_stack->top()[ident], get_real_value(interpret(stmt->declaration_statement.expression, var_stack, enclosing_object, enclosing_func, defer_stack).first))
|
||||
@@ -966,7 +965,7 @@ obj interpreter (Object) {
|
||||
interpret(stmt->declaration_statement.init_method_call, var_stack, enclosing_object, enclosing_func, defer_stack)
|
||||
}
|
||||
// defering destructs
|
||||
if (ident_type->indirection == 0 && (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>()))))
|
||||
if (ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>())))
|
||||
defer_stack->push(ast_statement_ptr(make_method_call(ident, "destruct", vector<*ast_node>())))
|
||||
return make_pair(value::void_nothing(), control_flow::nor())
|
||||
}
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
import ast_nodes:*
|
||||
import ast_transformation:*
|
||||
import mem:*
|
||||
import util:*
|
||||
import vector:*
|
||||
import stack:*
|
||||
import string:*
|
||||
|
||||
fun make_this_noncached(object: *ast_node): *ast_node {
|
||||
return ast_identifier_ptr("this", object->type_def.self_type->clone_with_indirection(1), object)
|
||||
}
|
||||
fun possible_object_equality(lvalue: *ast_node, rvalue: *ast_node): *ast_node {
|
||||
var ltype = get_ast_type(lvalue)
|
||||
var rtype = get_ast_type(rvalue)
|
||||
if (ltype->indirection == 0 && (ltype->is_object() && has_method(ltype->type_def, "operator==", vector(rtype)))) {
|
||||
return make_method_call(lvalue, "operator==", vector(rvalue))
|
||||
} else if (ltype->is_object())
|
||||
// return false if object but no operator== (right now don't try for templated)
|
||||
return ast_value_ptr(string("false"), type_ptr(base_type::boolean()))
|
||||
return make_operator_call("==", vector(lvalue, rvalue))
|
||||
}
|
||||
|
||||
// for now, needs source to already be in a variable for copy_constructing
|
||||
fun assign_or_copy_construct_statement(lvalue: *ast_node, rvalue: *ast_node): *ast_node {
|
||||
var ltype = get_ast_type(lvalue)
|
||||
if (ltype->indirection == 0 && (ltype->is_object() && has_method(ltype->type_def, "copy_construct", vector(ltype->clone_with_increased_indirection()))))
|
||||
return make_method_call(lvalue, "copy_construct", vector(make_operator_call("&", vector(rvalue))))
|
||||
return ast_assignment_statement_ptr(lvalue, rvalue)
|
||||
}
|
||||
|
||||
fun get_children_pointer(node: *ast_node): *vector<*ast_node> {
|
||||
var bc = null<vector<*ast_node>>()
|
||||
match(*node) {
|
||||
@@ -54,6 +77,11 @@ fun replace_with_in(orig: *ast_node, new: *ast_node, in: *ast_node) {
|
||||
}
|
||||
}
|
||||
|
||||
fun add_before_in(to_add: ref vector<*ast_node>, before: *ast_node, in: *stack<*ast_node>)
|
||||
to_add.for_each(fun(n: *ast_node) add_before_in(n, before, in);)
|
||||
fun add_before_in(to_add: vector<*ast_node>, before: *ast_node, in: *ast_node)
|
||||
to_add.for_each(fun(n: *ast_node) add_before_in(n, before, in);)
|
||||
|
||||
fun add_before_in(to_add: *ast_node, before: *ast_node, in: *stack<*ast_node>)
|
||||
add_before_in(to_add, before, in->top())
|
||||
fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) {
|
||||
@@ -68,6 +96,7 @@ fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) {
|
||||
error(string("cannot add_before_in to ") + get_ast_name(in))
|
||||
}
|
||||
|
||||
fun empty_pass_half(node: *ast_node, parent_chain: *stack<*ast_node>) {}
|
||||
fun run_on_tree(func_before: fun(*ast_node,*stack<*ast_node>):void, func_after: fun(*ast_node,*stack<*ast_node>):void, tree: *ast_node) {
|
||||
var parent_stack = stack<*ast_node>()
|
||||
run_on_tree_helper(func_before, func_after, tree, &parent_stack)
|
||||
@@ -79,7 +108,9 @@ fun run_on_tree_helper(func_before: fun(*ast_node,*stack<*ast_node>):void, func_
|
||||
match(*node) {
|
||||
ast_node::translation_unit(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::type_def(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::adt_def(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::function(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::template(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::code_block(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::if_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
@@ -87,6 +118,17 @@ fun run_on_tree_helper(func_before: fun(*ast_node,*stack<*ast_node>):void, func_
|
||||
ast_node::case_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::while_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::for_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::return_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::defer_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::assignment_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::declaration_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::if_comp(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
ast_node::function_call(backing) {
|
||||
if (!is_function(backing.func))
|
||||
run_on_tree_helper(func_before, func_after, backing.func, parent_chain)
|
||||
node->function_call.parameters.for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
}
|
||||
ast_node::cast(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
||||
}
|
||||
parent_chain->pop()
|
||||
func_after(node, parent_chain)
|
||||
|
||||
@@ -10,7 +10,6 @@ import io:*
|
||||
adt base_type {
|
||||
none,
|
||||
object,
|
||||
adt,
|
||||
no_type_adt_option,
|
||||
function,
|
||||
template,
|
||||
@@ -95,10 +94,7 @@ obj type (Object) {
|
||||
return this
|
||||
}
|
||||
fun construct(type_def_in: *ast_node, traits_in: set<string>): *type {
|
||||
if (is_type_def(type_def_in))
|
||||
base.copy_construct(&base_type::object())
|
||||
else
|
||||
base.copy_construct(&base_type::adt())
|
||||
base.copy_construct(&base_type::object())
|
||||
parameter_types.construct()
|
||||
indirection = 0
|
||||
return_type = null<type>()
|
||||
@@ -160,7 +156,7 @@ obj type (Object) {
|
||||
traits.for_each(fun(t: string) trait_string += t;)
|
||||
trait_string += "] "
|
||||
}
|
||||
|
||||
|
||||
var indr_string = string("")
|
||||
if (is_ref)
|
||||
indr_string += " ref "
|
||||
@@ -169,8 +165,7 @@ obj type (Object) {
|
||||
for (var i = 0; i < indirection; i++;) indr_string += "*"
|
||||
match (base) {
|
||||
base_type::none() return indr_string + string("none") + trait_string
|
||||
base_type::object() return indr_string + type_def->type_def.name + trait_string
|
||||
base_type::adt() return indr_string + type_def->adt_def.name + trait_string
|
||||
base_type::object() return indr_string + get_ast_name(type_def) + trait_string
|
||||
base_type::no_type_adt_option() return indr_string + "no_type_adt_option" + trait_string
|
||||
base_type::template() return indr_string + string("template") + trait_string
|
||||
base_type::template_type() return indr_string + string("template_type") + trait_string
|
||||
@@ -225,20 +220,12 @@ obj type (Object) {
|
||||
to_ret->is_ref = is_ref_in
|
||||
return to_ret
|
||||
}
|
||||
fun is_object_like(): bool
|
||||
return is_object() || is_adt()
|
||||
fun is_object(): bool {
|
||||
match (base) {
|
||||
base_type::object() return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
fun is_adt(): bool {
|
||||
match (base) {
|
||||
base_type::adt() return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
fun is_function(): bool {
|
||||
match (base) {
|
||||
base_type::function() return true
|
||||
|
||||
@@ -14,13 +14,15 @@ destructed object 100 : 100
|
||||
copy constructed object 100 : 300 from 100 : 200
|
||||
destructed object 100 : 200
|
||||
copy constructed object 100 : 400 from 100 : 300
|
||||
destructed object 100 : 300
|
||||
copy constructed object 100 : 500 from 100 : 400
|
||||
destructed object 100 : 400
|
||||
done assignment to old variable
|
||||
matched an_obj correctly 100 : 500
|
||||
int assignment to old var
|
||||
destructed object 100 : 300
|
||||
copy constructed object 100 : 600 from 100 : 500
|
||||
destructed object 100 : 500
|
||||
done assignment to old variable
|
||||
matched an_obj correctly 100 : 600
|
||||
int assignment to old var
|
||||
destructed object 100 : 600
|
||||
done int assignment to old var
|
||||
matched an_int correctly 1337
|
||||
test copy_construct for non ref equality
|
||||
@@ -31,6 +33,8 @@ destructed object 110 : 110
|
||||
copy constructed object 110 : 310 from 110 : 210
|
||||
destructed object 110 : 210
|
||||
copy constructed object 110 : 410 from 110 : 310
|
||||
copy constructed object 110 : 510 from 110 : 410
|
||||
destructed object 110 : 410
|
||||
destructed object 110 : 310
|
||||
gonna make object in function 110
|
||||
constructed object 110 : 110
|
||||
@@ -39,10 +43,13 @@ destructed object 110 : 110
|
||||
copy constructed object 110 : 310 from 110 : 210
|
||||
destructed object 110 : 210
|
||||
copy constructed object 110 : 410 from 110 : 310
|
||||
destructed object 110 : 310
|
||||
copy constructed object 110 : 510 from 110 : 410
|
||||
destructed object 110 : 510
|
||||
destructed object 110 : 410
|
||||
destructed object 110 : 310
|
||||
copy constructed object 110 : 610 from 110 : 510
|
||||
destructed object 110 : 610
|
||||
equality an_obj correctly
|
||||
destructed object 110 : 410
|
||||
destructed object 110 : 410
|
||||
destructed object 110 : 510
|
||||
destructed object 110 : 510
|
||||
done test copy_construct for non ref equality
|
||||
10
|
||||
|
||||
@@ -157,6 +157,7 @@ fun main():int {
|
||||
else
|
||||
println("equality an_obj incorrectly ")
|
||||
println("done test copy_construct for non ref equality");
|
||||
println(maybe_object::an_int(10).an_int)
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user