diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index a7fcd19..b978177 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -338,8 +338,8 @@ obj code_block (Object) { return children == other.children && scope == other.scope } } -fun ast_statement_ptr(): *ast_node { - var to_ret.construct(): statement +fun ast_statement_ptr(child: *ast_node): *ast_node { + var to_ret.construct(child): statement var ptr = new() ptr->copy_construct(&ast_node::statement(to_ret)) return ptr @@ -353,9 +353,10 @@ fun is_statement(node: *ast_node): bool { obj statement (Object) { var scope: map> var child: *ast_node - fun construct(): *statement { + fun construct(child_in: *ast_node): *statement { child = null() scope.construct() + child = child_in return this } fun copy_construct(old: *statement) { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 447aa64..b467b5a 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -160,344 +160,353 @@ obj ast_transformation (Object) { fun fourth_pass(parse_tree: *tree, translation_unit: *ast_node) { println(string("Fourth Pass for ") + translation_unit->translation_unit.name) } - fun transform_type(node: *tree, scope: *ast_node, template_replacements: map): *type { - // check for references and step down - // always get to pre-reffed level - var real_node = get_node("pre_reffed", node) - // check for indirection and step down - var indirection = 0 - while (get_node("pre_reffed", real_node)) { - real_node = get_node("pre_reffed", real_node) - indirection++ - } - var type_syntax_str = concat_symbol_tree(real_node) - println(type_syntax_str + " *************************") - // should take into account indirection and references... - if (type_syntax_str == "void") - return type_ptr(base_type::void_return(), indirection) - else if (type_syntax_str == "bool") - return type_ptr(base_type::boolean(), indirection) - else if (type_syntax_str == "int") - return type_ptr(base_type::integer(), indirection) - else if (type_syntax_str == "float") - return type_ptr(base_type::floating(), indirection) - else if (type_syntax_str == "double") - return type_ptr(base_type::double_precision(), indirection) - else if (type_syntax_str == "char") - return type_ptr(base_type::character(), indirection) - else if (/* check for function type*/ false) - return type_ptr(base_type::function(), indirection) - else { - // do lookup for objects, ADTs, templates, etc - var possibilities = scope_lookup(type_syntax_str, scope) - print("There are "); print(possibilities.size); println(" possibilites for this object type lookup") - for (var i = 0; i < possibilities.size; i++;) { - match(*possibilities[i]) { - ast_node::type_def(backing) return backing.self_type->clone_with_indirection(indirection) - } - } - println("No objects in lookup, returning none") - return type_ptr(base_type::none(), indirection) - } - } -/*NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree* scope, std::vector types, bool limitToFunction, std::map templateTypeReplacements) {*/ - fun transform(node: *tree, scope: *ast_node): *ast_node return transform(node, scope, search_type::none()) +} - fun transform(node: *tree, scope: *ast_node, searching_for: search_type): *ast_node { - var name = node->data.name - if (name == "identifier" || name == "scoped_identifier") { - return transform_identifier(node, scope, searching_for) - } else if (name == "code_block") { - return transform_code_block(node, scope) - } else if (name == "if_comp") { - return transform_if_comp(node, scope) - } else if (name == "simple_passthrough") { - return transform_simple_passthrough(node, scope) - } else if (name == "statement") { - return transform_statement(node, scope) - } else if (name == "declaration_statement") { - return transform_declaration_statement(node, scope) - } else if (name == "assignment_statement") { - return transform_assignment_statement(node, scope) - } else if (name == "if_statement") { - return transform_if_statement(node, scope) - } else if (name == "while_loop") { - return transform_while_loop(node, scope) - } else if (name == "for_loop") { - return transform_for_loop(node, scope) - } else if (name == "return_statement") { - return transform_return_statement(node, scope) - } else if (name == "continue_statement" || name == "break_statement") { - return transform_branching_statement(node, scope) - } else if (name == "defer_statement") { - return transform_defer_statement(node, scope) - } else if (name == "function_call") { - return transform_function_call(node, scope) - } else if (name == "boolean_expression" || name == "and_boolean_expression" - || name == "bool_exp" || name == "expression" - || name == "shiftand" || name == "term" - || name == "factor" || name == "unarad" - || name == "access_operation" - ) { - // for now, assume passthrough and just transform underneath - return transform_expression(node, scope, searching_for) - } else if (name == "bool" || name == "string" - || name == "character" || name == "number" - ) { - println(string("transforming value: ") + name) - return transform_value(node, scope) - } - print("FAILED TO TRANSFORM: "); print(name + ": "); println(concat_symbol_tree(node)) - return null() +fun transform_type(node: *tree, scope: *ast_node, template_replacements: map): *type { + // check for references and step down + // always get to pre-reffed level + var real_node = get_node("pre_reffed", node) + // check for indirection and step down + var indirection = 0 + while (get_node("pre_reffed", real_node)) { + real_node = get_node("pre_reffed", real_node) + indirection++ } - fun transform_all(nodes: vector<*tree>, scope: *ast_node): vector<*ast_node> { - return nodes.map(fun(node: *tree): *ast_node return transform(node, scope);) - } - fun transform_identifier(node: *tree, scope: *ast_node, searching_for: search_type): *ast_node { - // first, we check for and generate this - var name = concat_symbol_tree(node) - if (name == "this") { - while (!is_type_def(scope)) scope = get_ast_scope(scope)->get(string("~enclosing_scope"))[0] - return ast_identifier_ptr("this", scope->type_def.self_type->clone_with_indirection(1)) + var type_syntax_str = concat_symbol_tree(real_node) + println(type_syntax_str + " *************************") + // should take into account indirection and references... + if (type_syntax_str == "void") + return type_ptr(base_type::void_return(), indirection) + else if (type_syntax_str == "bool") + return type_ptr(base_type::boolean(), indirection) + else if (type_syntax_str == "int") + return type_ptr(base_type::integer(), indirection) + else if (type_syntax_str == "float") + return type_ptr(base_type::floating(), indirection) + else if (type_syntax_str == "double") + return type_ptr(base_type::double_precision(), indirection) + else if (type_syntax_str == "char") + return type_ptr(base_type::character(), indirection) + else if (/* check for function type*/ false) + return type_ptr(base_type::function(), indirection) + else { + // do lookup for objects, ADTs, templates, etc + var possibilities = scope_lookup(type_syntax_str, scope) + print("There are "); print(possibilities.size); println(" possibilites for this object type lookup") + for (var i = 0; i < possibilities.size; i++;) { + match(*possibilities[i]) { + ast_node::type_def(backing) return backing.self_type->clone_with_indirection(indirection) + } } - match (searching_for) { - search_type::none() return identifier_lookup(name, scope) - search_type::function(type_vec) return function_lookup(name, scope, type_vec) - } - println("FAILED SEARCH FOR") - return null() + println("No objects in lookup, returning none") + return type_ptr(base_type::none(), indirection) } - fun transform_value(node: *tree, scope: *ast_node): *ast_node { - var value_str = concat_symbol_tree(node) - var value_type = null() - if (value_str[0] == '"') - value_type = type_ptr(base_type::character(), 1) - else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course) - value_type = type_ptr(base_type::character()) - else { - // should differentiate between float and double... - var contains_dot = false - for (var i = 0; i < value_str.length(); i++;) { - if (value_str[i] == '.') { - contains_dot = true +} +fun transform(node: *tree, scope: *ast_node): *ast_node return transform(node, scope, search_type::none()) +fun transform(node: *tree, scope: *ast_node, searching_for: search_type): *ast_node { + var name = node->data.name + if (name == "identifier" || name == "scoped_identifier") { + return transform_identifier(node, scope, searching_for) + } else if (name == "code_block") { + return transform_code_block(node, scope) + } else if (name == "if_comp") { + return transform_if_comp(node, scope) + } else if (name == "simple_passthrough") { + return transform_simple_passthrough(node, scope) + } else if (name == "statement") { + return transform_statement(node, scope) + } else if (name == "declaration_statement") { + return transform_declaration_statement(node, scope) + } else if (name == "assignment_statement") { + return transform_assignment_statement(node, scope) + } else if (name == "if_statement") { + return transform_if_statement(node, scope) + } else if (name == "while_loop") { + return transform_while_loop(node, scope) + } else if (name == "for_loop") { + return transform_for_loop(node, scope) + } else if (name == "return_statement") { + return transform_return_statement(node, scope) + } else if (name == "continue_statement" || name == "break_statement") { + return transform_branching_statement(node, scope) + } else if (name == "defer_statement") { + return transform_defer_statement(node, scope) + } else if (name == "function_call") { + return transform_function_call(node, scope) + } else if (name == "boolean_expression" || name == "and_boolean_expression" + || name == "bool_exp" || name == "expression" + || name == "shiftand" || name == "term" + || name == "factor" || name == "unarad" + || name == "access_operation" + ) { + // for now, assume passthrough and just transform underneath + return transform_expression(node, scope, searching_for) + } else if (name == "bool" || name == "string" + || name == "character" || name == "number" + ) { + println(string("transforming value: ") + name) + return transform_value(node, scope) + } + print("FAILED TO TRANSFORM: "); print(name + ": "); println(concat_symbol_tree(node)) + return null() +} +fun transform_all(nodes: vector<*tree>, scope: *ast_node): vector<*ast_node> { + return nodes.map(fun(node: *tree): *ast_node return transform(node, scope);) +} +fun transform_identifier(node: *tree, scope: *ast_node, searching_for: search_type): *ast_node { + // first, we check for and generate this + var name = concat_symbol_tree(node) + if (name == "this") { + while (!is_type_def(scope)) scope = get_ast_scope(scope)->get(string("~enclosing_scope"))[0] + return ast_identifier_ptr("this", scope->type_def.self_type->clone_with_indirection(1)) + } + match (searching_for) { + search_type::none() return identifier_lookup(name, scope) + search_type::function(type_vec) return function_lookup(name, scope, type_vec) + } + println("FAILED SEARCH FOR") + return null() +} +fun transform_value(node: *tree, scope: *ast_node): *ast_node { + var value_str = concat_symbol_tree(node) + var value_type = null() + if (value_str[0] == '"') + value_type = type_ptr(base_type::character(), 1) + else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course) + value_type = type_ptr(base_type::character()) + else { + // should differentiate between float and double... + var contains_dot = false + for (var i = 0; i < value_str.length(); i++;) { + if (value_str[i] == '.') { + contains_dot = true + break + } + } + if (contains_dot) + value_type = type_ptr(base_type::floating()) + else + value_type = type_ptr(base_type::integer()) + } + return ast_value_ptr(value_str, value_type) +} +fun transform_code_block(node: *tree, scope: *ast_node): *ast_node { + var new_block = ast_code_block_ptr() + add_to_scope("~enclosing_scope", scope, new_block) + new_block->code_block.children = transform_all(node->children, new_block) + return new_block +} +fun transform_if_comp(node: *tree, scope: *ast_node): *ast_node { + var new_if_comp = ast_if_comp_ptr() + new_if_comp->if_comp.wanted_generator = concat_symbol_tree(get_node("identifier", node)) + new_if_comp->if_comp.statement = transform_statement(get_node("statement", node), scope) + return new_if_comp +} +fun transform_simple_passthrough(node: *tree, scope: *ast_node): *ast_node { + var new_passthrough = ast_simple_passthrough_ptr() + // setup passthrough params and string + new_passthrough->simple_passthrough.passthrough_str = concat_symbol_tree(get_node("triple_quoted_string", node)).slice(3,-4) + return new_passthrough +} +fun transform_statement(node: *tree, scope: *ast_node): *ast_node return ast_statement_ptr(transform(node->children[0], scope)); +fun transform_declaration_statement(node: *tree, scope: *ast_node): *ast_node { + // this might have an init position method call + var identifiers = get_nodes("identifier", node) + var name = concat_symbol_tree(identifiers[0]) + // may have type, or an expression, or both + var type_syntax_node = get_node("type", node) + var expression_syntax_node = get_node("boolean_expression", node) + var ident_type = null() + var expression = null() + if (type_syntax_node) ident_type = transform_type(type_syntax_node, scope, map()) + if (expression_syntax_node) { + expression = transform(expression_syntax_node, scope) + if (!type_syntax_node) + ident_type = get_ast_type(expression) + } + if (!ident_type) error("declaration statement with no type or expression from which to inference type") + var identifier = ast_identifier_ptr(name, ident_type) + var declaration = ast_declaration_statement_ptr(identifier, expression) + // ok, deal with the possible init position method call + if (identifiers.size == 2) { + var method = transform(identifiers[1], ident_type->type_def) + var parameters = get_nodes("parameter", node).map(fun(child: *tree): *ast_node return transform(get_node("boolean_expression", child), scope);) + declaration->declaration_statement.init_method_call = make_method_call(identifier, method, parameters) + } + add_to_scope(name, identifier, scope) + return declaration +} +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 { + return function_lookup(name, object, parameter_types) || false +} +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 { + 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: ") + println(method) + return make_method_call(object_ident, method, parameters) +} +fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vector<*ast_node>): *ast_node { + 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)) + return ast_function_call_ptr(method_access, parameters) +} +fun transform_assignment_statement(node: *tree, scope: *ast_node): *ast_node { + var assignment = ast_assignment_statement_ptr(transform(get_node("factor", node), scope), transform(get_node("boolean_expression", node), scope)) + return assignment +} +fun transform_if_statement(node: *tree, scope: *ast_node): *ast_node { + var if_statement = ast_if_statement_ptr(transform_expression(get_node("boolean_expression", node), scope)) + // one variable declarations might be in a code_block-less if statement + add_to_scope("~enclosing_scope", scope, if_statement) + var statements = transform_all(get_nodes("statement", node), if_statement) + if_statement->if_statement.then_part = statements[0] + // we have an else + if (statements.size == 2) + if_statement->if_statement.else_part = statements[1] + return if_statement +} +fun transform_while_loop(node: *tree, scope: *ast_node): *ast_node { + var while_loop = ast_while_loop_ptr(transform_expression(get_node("boolean_expression", node), scope)) + add_to_scope("~enclosing_scope", scope, while_loop) + while_loop->while_loop.statement = transform(get_node("statement", node), while_loop) + return while_loop +} +fun transform_for_loop(node: *tree, scope: *ast_node): *ast_node { + var for_loop = ast_for_loop_ptr() + add_to_scope("~enclosing_scope", scope, for_loop) + var statements = get_nodes("statement", node) + for_loop->for_loop.init = transform(statements[0], for_loop) + for_loop->for_loop.condition = transform(get_node("boolean_expression", node), for_loop) + for_loop->for_loop.update = transform(statements[1], for_loop) + for_loop->for_loop.body = transform(statements[2], for_loop) + return for_loop +} +fun transform_return_statement(node: *tree, scope: *ast_node): *ast_node { + return ast_return_statement_ptr(transform(node->children[0], scope)) +} +fun transform_branching_statement(node: *tree, scope: *ast_node): *ast_node { + if (node->data.name == "break_statement") + return ast_branching_statement_ptr(branching_type::break_stmt()) + return ast_branching_statement_ptr(branching_type::continue_stmt()) +} +fun transform_defer_statement(node: *tree, scope: *ast_node): *ast_node { + return ast_defer_statement_ptr(transform(node->children[0], scope)) +} +fun transform_function_call(node: *tree, scope: *ast_node): *ast_node { + // 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): *ast_node return transform(get_node("boolean_expression", child), scope);) + var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);) + var f = ast_function_call_ptr(transform(get_node("unarad", node), scope, search_type::function(parameter_types)), parameters) + /*print("function call function ")*/ + /*println(f->function_call.func)*/ + /*print("function call parameters ")*/ + /*f->function_call.parameters.for_each(fun(param: *ast_node) print(param);)*/ + return f +} +fun transform_expression(node: *tree, scope: *ast_node): *ast_node return transform_expression(node, scope, search_type::none()) +fun transform_expression(node: *tree, scope: *ast_node, searching_for: search_type): *ast_node { + // figure out what the expression is, handle overloads, or you know + // ignore everything and do a passthrough + var func_name = string() + var parameters = vector<*ast_node>() + if (node->children.size == 1) + return transform(node->children[0], scope, searching_for) + else if (node->children.size == 2) { + var check_if_post = concat_symbol_tree(node->children[1]) + if (check_if_post == "--" || check_if_post == "++") { + // give the post-operators a special suffix so the c_generator knows to emit them post + func_name = concat_symbol_tree(node->children[1]) + "p" + parameters = vector(transform(node->children[0], scope)) + } else { + func_name = concat_symbol_tree(node->children[0]) + parameters = vector(transform(node->children[1], scope)) + } + } else { + func_name = concat_symbol_tree(node->children[1]) + var first_param = transform(node->children[0], scope) + var second_param = null() + if (func_name == "." || func_name == "->") { + println("Gonna do the internal scope thing") + second_param = transform(node->children[2], get_ast_type(first_param)->type_def, searching_for) + } else { + println("Gonna do regular scope thing") + second_param = transform(node->children[2], scope) + } + parameters = vector(first_param, second_param) + } + var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);) + return ast_function_call_ptr(get_builtin_function(func_name, parameter_types), parameters) +} +fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node { + if (name == "." || name == "->") + return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>()) + return ast_function_ptr(name, type_ptr(param_types, param_types[0]), vector<*ast_node>()) +} +fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>): *ast_node { + println(string("doing function lookup for: ") + name) + var param_string = string() + param_types.for_each(fun(t: *type) param_string += t->to_string() + ", ";) + var results = scope_lookup(name, scope) + print(results.size); println(" number of results") + for (var i = 0; i < results.size; i++;) { + if (is_function(results[i])) { + var func_param_types = get_ast_type(results[i])->parameter_types + if (func_param_types.size != param_types.size) { + println(string("type sizes don't match") + get_ast_type(results[i])->to_string() + " with needed " + param_string) + continue + } + var param_types_match = true + for (var j = 0; j < param_types.size; j++;) { + if (*func_param_types[j] != *param_types[j]) { + param_types_match = false break } } - if (contains_dot) - value_type = type_ptr(base_type::floating()) - else - value_type = type_ptr(base_type::integer()) + if (param_types_match) + return results[i] } - return ast_value_ptr(value_str, value_type) + println(string("either isn't function or types don't match ") + get_ast_type(results[i])->to_string() + " with needed " + param_string) } - fun transform_code_block(node: *tree, scope: *ast_node): *ast_node { - var new_block = ast_code_block_ptr() - add_to_scope("~enclosing_scope", scope, new_block) - new_block->code_block.children = transform_all(node->children, new_block) - return new_block - } - fun transform_if_comp(node: *tree, scope: *ast_node): *ast_node { - var new_if_comp = ast_if_comp_ptr() - new_if_comp->if_comp.wanted_generator = concat_symbol_tree(get_node("identifier", node)) - new_if_comp->if_comp.statement = transform_statement(get_node("statement", node), scope) - return new_if_comp - } - fun transform_simple_passthrough(node: *tree, scope: *ast_node): *ast_node { - var new_passthrough = ast_simple_passthrough_ptr() - // setup passthrough params and string - new_passthrough->simple_passthrough.passthrough_str = concat_symbol_tree(get_node("triple_quoted_string", node)).slice(3,-4) - return new_passthrough - } - fun transform_statement(node: *tree, scope: *ast_node): *ast_node { - var new_statement = ast_statement_ptr() - new_statement->statement.child = transform(node->children[0], scope) - return new_statement - } - fun transform_declaration_statement(node: *tree, scope: *ast_node): *ast_node { - // this might have an init position method call - var identifiers = get_nodes("identifier", node) - var name = concat_symbol_tree(identifiers[0]) - // may have type, or an expression, or both - var type_syntax_node = get_node("type", node) - var expression_syntax_node = get_node("boolean_expression", node) - var ident_type = null() - var expression = null() - if (type_syntax_node) ident_type = transform_type(type_syntax_node, scope, map()) - if (expression_syntax_node) { - expression = transform(expression_syntax_node, scope) - if (!type_syntax_node) - ident_type = get_ast_type(expression) - } - if (!ident_type) error("declaration statement with no type or expression from which to inference type") - var identifier = ast_identifier_ptr(name, ident_type) - var declaration = ast_declaration_statement_ptr(identifier, expression) - // ok, deal with the possible init position method call - if (identifiers.size == 2) { - var method = transform(identifiers[1], ident_type->type_def) - var parameters = get_nodes("parameter", node).map(fun(child: *tree): *ast_node return transform(get_node("boolean_expression", child), scope);) - var method_access = ast_function_call_ptr(get_builtin_function(string("."), vector(ident_type, get_ast_type(method))), vector(identifier, method)) - declaration->declaration_statement.init_method_call = ast_function_call_ptr(method_access, parameters) - } - add_to_scope(name, identifier, scope) - return declaration - } - fun transform_assignment_statement(node: *tree, scope: *ast_node): *ast_node { - var assignment = ast_assignment_statement_ptr(transform(get_node("factor", node), scope), transform(get_node("boolean_expression", node), scope)) - return assignment - } - fun transform_if_statement(node: *tree, scope: *ast_node): *ast_node { - var if_statement = ast_if_statement_ptr(transform_expression(get_node("boolean_expression", node), scope)) - // one variable declarations might be in a code_block-less if statement - add_to_scope("~enclosing_scope", scope, if_statement) - var statements = transform_all(get_nodes("statement", node), if_statement) - if_statement->if_statement.then_part = statements[0] - // we have an else - if (statements.size == 2) - if_statement->if_statement.else_part = statements[1] - return if_statement - } - fun transform_while_loop(node: *tree, scope: *ast_node): *ast_node { - var while_loop = ast_while_loop_ptr(transform_expression(get_node("boolean_expression", node), scope)) - add_to_scope("~enclosing_scope", scope, while_loop) - while_loop->while_loop.statement = transform(get_node("statement", node), while_loop) - return while_loop - } - fun transform_for_loop(node: *tree, scope: *ast_node): *ast_node { - var for_loop = ast_for_loop_ptr() - add_to_scope("~enclosing_scope", scope, for_loop) - var statements = get_nodes("statement", node) - for_loop->for_loop.init = transform(statements[0], for_loop) - for_loop->for_loop.condition = transform(get_node("boolean_expression", node), for_loop) - for_loop->for_loop.update = transform(statements[1], for_loop) - for_loop->for_loop.body = transform(statements[2], for_loop) - return for_loop - } - fun transform_return_statement(node: *tree, scope: *ast_node): *ast_node { - return ast_return_statement_ptr(transform(node->children[0], scope)) - } - fun transform_branching_statement(node: *tree, scope: *ast_node): *ast_node { - if (node->data.name == "break_statement") - return ast_branching_statement_ptr(branching_type::break_stmt()) - return ast_branching_statement_ptr(branching_type::continue_stmt()) - } - fun transform_defer_statement(node: *tree, scope: *ast_node): *ast_node { - return ast_defer_statement_ptr(transform(node->children[0], scope)) - } - fun transform_function_call(node: *tree, scope: *ast_node): *ast_node { - // 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): *ast_node return transform(get_node("boolean_expression", child), scope);) - var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);) - var f = ast_function_call_ptr(transform(get_node("unarad", node), scope, search_type::function(parameter_types)), parameters) - /*print("function call function ")*/ - /*println(f->function_call.func)*/ - /*print("function call parameters ")*/ - /*f->function_call.parameters.for_each(fun(param: *ast_node) print(param);)*/ - return f - } - fun transform_expression(node: *tree, scope: *ast_node): *ast_node return transform_expression(node, scope, search_type::none()) - fun transform_expression(node: *tree, scope: *ast_node, searching_for: search_type): *ast_node { - // figure out what the expression is, handle overloads, or you know - // ignore everything and do a passthrough - var func_name = string() - var parameters = vector<*ast_node>() - if (node->children.size == 1) - return transform(node->children[0], scope, searching_for) - else if (node->children.size == 2) { - var check_if_post = concat_symbol_tree(node->children[1]) - if (check_if_post == "--" || check_if_post == "++") { - // give the post-operators a special suffix so the c_generator knows to emit them post - func_name = concat_symbol_tree(node->children[1]) + "p" - parameters = vector(transform(node->children[0], scope)) - } else { - func_name = concat_symbol_tree(node->children[0]) - parameters = vector(transform(node->children[1], scope)) - } - } else { - func_name = concat_symbol_tree(node->children[1]) - var first_param = transform(node->children[0], scope) - var second_param = null() - if (func_name == "." || func_name == "->") { - println("Gonna do the internal scope thing") - second_param = transform(node->children[2], get_ast_type(first_param)->type_def, searching_for) - } else { - println("Gonna do regular scope thing") - second_param = transform(node->children[2], scope) - } - parameters = vector(first_param, second_param) - } - var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);) - return ast_function_call_ptr(get_builtin_function(func_name, parameter_types), parameters) - } - fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node { - if (name == "." || name == "->") - return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>()) - return ast_function_ptr(name, type_ptr(param_types, param_types[0]), vector<*ast_node>()) - } - fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>): *ast_node { - println(string("doing function lookup for: ") + name) - var param_string = string() - param_types.for_each(fun(t: *type) param_string += t->to_string() + ", ";) - var results = scope_lookup(name, scope) - print(results.size); println(" number of results") - for (var i = 0; i < results.size; i++;) { - if (is_function(results[i])) { - var func_param_types = get_ast_type(results[i])->parameter_types - if (func_param_types.size != param_types.size) { - println(string("type sizes don't match") + get_ast_type(results[i])->to_string() + " with needed " + param_string) - continue - } - var param_types_match = true - for (var j = 0; j < param_types.size; j++;) { - if (*func_param_types[j] != *param_types[j]) { - param_types_match = false - break - } - } - if (param_types_match) - return results[i] - } - println(string("either isn't function or types don't match ") + get_ast_type(results[i])->to_string() + " with needed " + param_string) - } - println(string("function lookup failed for ") + name) + println(string("function lookup failed for ") + name) + return null() +} +fun identifier_lookup(name: string, scope: *ast_node): *ast_node { + println(string("doing identifier lookup for: ") + name) + var results = scope_lookup(name, scope) + if (!results.size) { + println(string("identifier lookup failed for ") + name) return null() } - fun identifier_lookup(name: string, scope: *ast_node): *ast_node { - println(string("doing identifier lookup for: ") + name) - var results = scope_lookup(name, scope) - if (!results.size) { - println(string("identifier lookup failed for ") + name) - return null() - } - return results[0] + return results[0] +} +fun scope_lookup(name: string, scope: *ast_node): vector<*ast_node> { + println("*****Doing a name lookup for*****") + println(name) + return scope_lookup_helper(name, scope) +} +fun scope_lookup_helper(name: string, scope: *ast_node): vector<*ast_node> { + // need to do properly scopded lookups + // prevent re-checking the same one... + print("scope is: ") + get_ast_scope(scope)->for_each(fun(key: string, value: vector<*ast_node>) print(key + " ");) + println() + var results = vector<*ast_node>() + if (get_ast_scope(scope)->contains_key(name)) { + println(name + " is in scope, adding to results") + results += get_ast_scope(scope)->get(name) } - fun scope_lookup(name: string, scope: *ast_node): vector<*ast_node> { - println("*****Doing a name lookup for*****") - println(name) - return scope_lookup_helper(name, scope) - } - fun scope_lookup_helper(name: string, scope: *ast_node): vector<*ast_node> { - // need to do properly scopded lookups - // prevent re-checking the same one... - print("scope is: ") - get_ast_scope(scope)->for_each(fun(key: string, value: vector<*ast_node>) print(key + " ");) - println() - var results = vector<*ast_node>() - if (get_ast_scope(scope)->contains_key(name)) { - println(name + " is in scope, adding to results") - results += get_ast_scope(scope)->get(name) - } - if (get_ast_scope(scope)->contains_key(string("~enclosing_scope"))) - results += scope_lookup_helper(name, get_ast_scope(scope)->get(string("~enclosing_scope"))[0]) - if (is_translation_unit(scope)) { - scope->translation_unit.children.for_each(fun(child: *ast_node) { - if (is_import(child) && child->import.imported.contains(name)) { - println(name + " is indeed imported") - results += scope_lookup_helper(name, child->import.translation_unit) - } else println(name + " is not imported (this time)") - }) - } - return results + if (get_ast_scope(scope)->contains_key(string("~enclosing_scope"))) + results += scope_lookup_helper(name, get_ast_scope(scope)->get(string("~enclosing_scope"))[0]) + if (is_translation_unit(scope)) { + scope->translation_unit.children.for_each(fun(child: *ast_node) { + if (is_import(child) && child->import.imported.contains(name)) { + println(name + " is indeed imported") + results += scope_lookup_helper(name, child->import.translation_unit) + } else println(name + " is not imported (this time)") + }) } + return results } fun concat_symbol_tree(node: *tree): string { diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 64f21e9..0b796a9 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -8,6 +8,8 @@ import tree:* import symbol:* import ast_nodes:* import poset:* +// we import ast_transformation for its make_method_call function +import ast_transformation:* fun code_triple(): code_triple return code_triple(string(), string(), string()); fun code_triple(only: *char): code_triple return code_triple(string(), string(only), string()); @@ -172,11 +174,14 @@ obj c_generator (Object) { } fun generate_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple return generate(node->statement.child, enclosing_object, defer_stack) + ";\n"; fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { - // add destruct to defer_stac + // add destruct to defer_stack var identifier = node->declaration_statement.identifier + var ident_type = identifier->identifier.type var to_ret = code_triple() + type_to_c(identifier->identifier.type) + " " + identifier->identifier.name if (node->declaration_statement.expression) to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, null>>>()) if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, null>>>()) + if (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 } fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node): code_triple { diff --git a/stdlib/type.krak b/stdlib/type.krak index d09e9f9..c43420a 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -121,5 +121,11 @@ obj type (Object) { to_ret->indirection = ind return to_ret } + fun is_object(): bool { + match (base) { + base_type::object() return true + } + return false + } } diff --git a/tests/to_parse.krak b/tests/to_parse.krak index f3a5f33..46754ea 100644 --- a/tests/to_parse.krak +++ b/tests/to_parse.krak @@ -17,8 +17,8 @@ obj Something (ObjectTrait) { member = old->member } fun destruct() { - simple_println("Destructing a Something") - member = -800 + simple_print("Destructing a Something: ") + simple_println(member) } fun method(a: int):int { return 5+a+member + other_method() @@ -107,6 +107,7 @@ fun main(): int { simple_println(test_methods.member) simple_println(test_methods_param.member) var second_obj = test_methods + second_obj.member += 5 simple_println(second_obj.member) return 0 }