From ecbbcb4eda56e2467efb0a04e7d668b95856aa4b Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Fri, 29 Apr 2016 01:14:26 -0400 Subject: [PATCH] C extern implemented --- krakenGrammer.kgm | 2 +- stdlib/ast_nodes.krak | 18 +++++++++++----- stdlib/ast_transformation.krak | 33 +++++++++++++++--------------- stdlib/c_generator.krak | 27 ++++++++++++++++++------ tests/test_extern.expected_results | 1 + tests/test_extern.krak | 8 ++++++++ 6 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 tests/test_extern.expected_results create mode 100644 tests/test_extern.krak diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 37582ca..af7dbc9 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -72,7 +72,7 @@ func_identifier = identifier | identifier overloadable_operator ; # HACKY - typed_return has it's own internal whitespace as to not make WS typed_return-reduces to null WS ambigious typed_return = WS dec_type | ; -function = "fun" WS func_identifier WS template_dec WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement | "fun" WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement ; +function = "ext" WS "fun" WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" typed_return | "fun" WS func_identifier WS template_dec WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement | "fun" WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement ; lambda = "fun" WS "\(" WS opt_typed_parameter_list WS "\)" typed_return WS statement ; opt_typed_parameter_list = typed_parameter_list | ; diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index 3287a58..78b5a8a 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -285,8 +285,8 @@ obj adt_def (Object) { return name == other.name && self_type == other.self_type && options == other.options && option_funcs == other.option_funcs && regular_funcs == other.regular_funcs } } -fun ast_function_ptr(name: string, type: *type, parameters: vector<*ast_node>): *ast_node { - var to_ret.construct(name, type, parameters): function +fun ast_function_ptr(name: string, type: *type, parameters: vector<*ast_node>, is_extern: bool): *ast_node { + var to_ret.construct(name, type, parameters, is_extern): function var ptr = new() ptr->copy_construct(&ast_node::function(to_ret)) return ptr @@ -304,13 +304,15 @@ obj function (Object) { var closed_variables: set<*ast_node> var body_statement: *ast_node var scope: map> - fun construct(name_in: string, type_in: *type, parameters_in: vector<*ast_node>): *function { + var is_extern: bool + fun construct(name_in: string, type_in: *type, parameters_in: vector<*ast_node>, is_extern_in: bool): *function { name.copy_construct(&name_in) parameters.copy_construct(¶meters_in) closed_variables.construct() scope.construct() type = type_in body_statement = null() + is_extern = is_extern_in return this } fun copy_construct(old: *function) { @@ -320,6 +322,7 @@ obj function (Object) { parameters.copy_construct(&old->parameters) closed_variables.copy_construct(&old->closed_variables) scope.copy_construct(&old->scope) + is_extern = old->is_extern } fun destruct() { name.destruct() @@ -332,7 +335,7 @@ obj function (Object) { copy_construct(&other) } fun operator==(other: ref function): bool { - return name == name && type == other.type && parameters == other.parameters && body_statement == other.body_statement && closed_variables == other.closed_variables + return name == name && type == other.type && parameters == other.parameters && body_statement == other.body_statement && closed_variables == other.closed_variables && is_extern == other.is_extern } } fun ast_template_ptr(name: string, syntax_node: *tree, template_types: vector, template_type_replacements: map, is_function: bool): *ast_node { @@ -1116,7 +1119,12 @@ fun get_ast_name(node: *ast_node): string { ast_node::identifier(backing) return string("identifier: ") + backing.name + ": " + backing.type->to_string() ast_node::type_def(backing) return string("type_def: ") + backing.name ast_node::adt_def(backing) return string("adt_def: ") + backing.name - ast_node::function(backing) return string("function: ") + backing.name + ": " + backing.type->to_string() + ast_node::function(backing) { + if (backing.is_extern) + return string("extern function: ") + backing.name + ": " + backing.type->to_string() + else + return string("function: ") + backing.name + ": " + backing.type->to_string() + } ast_node::template(backing) return string("template: ") + backing.name ast_node::code_block(backing) return string("code_block") ast_node::statement(backing) return string("statement") diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 5342f34..4caa163 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -167,9 +167,9 @@ obj ast_transformation (Object) { var function_node = null() if (type_syntax) { var identifier_param = ast_identifier_ptr(option_name, ident_type, node) - function_node = ast_function_ptr(option_name, type_ptr(vector(get_ast_type(identifier_param)), node->adt_def.self_type), vector(identifier_param)) + function_node = ast_function_ptr(option_name, type_ptr(vector(get_ast_type(identifier_param)), node->adt_def.self_type), vector(identifier_param), false) } else { - function_node = ast_function_ptr(option_name, type_ptr(vector<*type>(), node->adt_def.self_type), vector<*ast_node>()) + function_node = ast_function_ptr(option_name, type_ptr(vector<*type>(), node->adt_def.self_type), vector<*ast_node>(), false) } add_to_scope(option_name, function_node, node) add_to_scope("~enclosing_scope", node, function_node) @@ -184,11 +184,11 @@ obj ast_transformation (Object) { var copy_construct_param = ast_identifier_ptr(string("in"), node->adt_def.self_type->clone_with_indirection(1,false), node) var assign_param = ast_identifier_ptr(string("in"), node->adt_def.self_type->clone_with_indirection(0,true), node) vector( - make_pair("operator==", ast_function_ptr(string("operator=="), type_ptr(vector(equals_param->identifier.type), type_ptr(base_type::boolean())), vector(equals_param))), - make_pair("operator!=", ast_function_ptr(string("operator!="), type_ptr(vector(nequals_param->identifier.type), type_ptr(base_type::boolean())), vector(nequals_param))), - make_pair("copy_construct", ast_function_ptr(string("copy_construct"), type_ptr(vector(copy_construct_param->identifier.type), type_ptr(base_type::void_return())), vector(copy_construct_param))), - make_pair("operator=", ast_function_ptr(string("operator="), type_ptr(vector(assign_param->identifier.type), type_ptr(base_type::void_return())), vector(assign_param))), - make_pair("destruct", ast_function_ptr(string("destruct"), type_ptr(vector<*type>(), type_ptr(base_type::void_return())), vector<*ast_node>())) + make_pair("operator==", ast_function_ptr(string("operator=="), type_ptr(vector(equals_param->identifier.type), type_ptr(base_type::boolean())), vector(equals_param), false)), + make_pair("operator!=", ast_function_ptr(string("operator!="), type_ptr(vector(nequals_param->identifier.type), type_ptr(base_type::boolean())), vector(nequals_param), false)), + make_pair("copy_construct", ast_function_ptr(string("copy_construct"), type_ptr(vector(copy_construct_param->identifier.type), type_ptr(base_type::void_return())), vector(copy_construct_param), false)), + make_pair("operator=", ast_function_ptr(string("operator="), type_ptr(vector(assign_param->identifier.type), type_ptr(base_type::void_return())), vector(assign_param), false)), + make_pair("destruct", ast_function_ptr(string("destruct"), type_ptr(vector<*type>(), type_ptr(base_type::void_return())), vector<*ast_node>(), false)) ).for_each(fun(func_pair: pair<*char, *ast_node>) { node->adt_def.regular_funcs.add(func_pair.second) add_to_scope(string(func_pair.first), func_pair.second, node) @@ -234,7 +234,7 @@ obj ast_transformation (Object) { parameters.add(ast_identifier_ptr(concat_symbol_tree(get_node("identifier", child)), param_type, null())) }) // figure out function type and make function_node - var function_node = ast_function_ptr(function_name, type_ptr(parameters.map(fun(parameter: *ast_node): *type return parameter->identifier.type;), return_type), parameters) + var function_node = ast_function_ptr(function_name, type_ptr(parameters.map(fun(parameter: *ast_node): *type return parameter->identifier.type;), return_type), parameters, get_node("\"ext\"", node) && true) // fix up the enclosing_scope's parameters.for_each(fun(n: *ast_node) n->identifier.enclosing_scope = function_node;) // add to scope @@ -263,7 +263,8 @@ obj ast_transformation (Object) { // make sure not a template // huh, I guess I can't actually assign to the backing. // This is actually a little bit of a problem, maybe these should be pointers also. All the pointers! - node->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map()) + if (!node->function.is_extern) + node->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map()) } } }) @@ -1109,18 +1110,18 @@ fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node { // none of the builtin functions should take in references param_types = param_types.map(fun(t: *type): *type return t->clone_without_ref();) if (name == "==" || name == "!=" || name == ">" || name == "<" || name == "<=" || name == ">" || name == ">=" || name == "&&" || name == "||" || name == "!") - return ast_function_ptr(name, type_ptr(param_types, type_ptr(base_type::boolean())), vector<*ast_node>()) + return ast_function_ptr(name, type_ptr(param_types, type_ptr(base_type::boolean())), vector<*ast_node>(), false) 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[1]), vector<*ast_node>(), false) if (name == "[]") - return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>()) + return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) if (name == "&" && param_types.size == 1) - return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_increased_indirection()), vector<*ast_node>()) + return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_increased_indirection()), vector<*ast_node>(), false) if (name == "\*" && param_types.size == 1) - return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>()) + return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) if (param_types.size > 1 && param_types[1]->rank() > param_types[0]->rank()) - 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>()) + return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>(), false) + return ast_function_ptr(name, type_ptr(param_types, param_types[0]), vector<*ast_node>(), false) } fun unify_type(template_type: *tree, param_type: *type, new_map: *map, template_replacements: map) { /*println(string("Unifying type: ") + concat_symbol_tree(template_type))*/ diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 5315ce9..7b7affe 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -80,6 +80,7 @@ obj c_generator (Object) { var function_type_map: map var function_typedef_string: string var closure_struct_definitions: string + var c_keyword_avoid: set var replacement_map: map var longest_replacement: int var linker_string: string @@ -91,6 +92,8 @@ obj c_generator (Object) { function_typedef_string.construct() closure_struct_definitions.construct() linker_string.construct() + c_keyword_avoid.construct() + c_keyword_avoid.add(string("extern")) replacement_map.construct() // IMPORTANT longest_replacement = 3 @@ -146,6 +149,7 @@ obj c_generator (Object) { function_type_map.copy_construct(&old->function_type_map) function_typedef_string.copy_construct(&old->function_typedef_string) closure_struct_definitions.copy_construct(&old->closure_struct_definitions) + c_keyword_avoid.copy_construct(&old->c_keyword_avoid) replacement_map.copy_construct(&old->replacement_map) longest_replacement = old->longest_replacement linker_string.copy_construct(&old->linker_string) @@ -160,6 +164,7 @@ obj c_generator (Object) { function_type_map.destruct() function_typedef_string.destruct() closure_struct_definitions.destruct() + c_keyword_avoid.destruct() replacement_map.destruct() linker_string.destruct() } @@ -182,7 +187,11 @@ obj c_generator (Object) { parameters += closed_type_name + "* closure_data" } - var decorated_name = generate_function(child, enclosing_object, null(), false, false).one_string() + var decorated_name = string() + if (backing.is_extern) + decorated_name = backing.name + else + decorated_name = generate_function(child, enclosing_object, null(), false, false).one_string() backing.parameters.for_each(fun(parameter: *ast_node) { if (parameter_types != "") { parameter_types += ", "; parameters += ", ";} parameter_types += type_to_c(parameter->identifier.type) @@ -216,13 +225,14 @@ obj c_generator (Object) { var defer_stack = stack>>(make_pair(false, stack<*ast_node>())) var prototype_and_header = generate_function_prototype_and_header(child, enclosing_object, is_lambda, &defer_stack) function_prototypes += prototype_and_header.first - function_definitions += prototype_and_header.second + if (!backing.is_extern) + function_definitions += prototype_and_header.second if (backing.body_statement) { function_definitions += string(" {\n") + generate_statement(backing.body_statement, enclosing_object, child, &defer_stack).one_string() function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string() function_definitions += "}\n" - } else { - // adt constructor + } 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 @@ -361,7 +371,8 @@ obj c_generator (Object) { ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null(), null>>>(), false).one_string() + ";\n" // false - don't do defer ast_node::function(backing) { // check for and add to parameters if a closure - generate_function_definition(child, null(), false) + if (!backing.is_extern) + generate_function_definition(child, null(), false) } ast_node::template(backing) { backing.instantiated.for_each(fun(node: *ast_node) { @@ -1027,6 +1038,8 @@ obj c_generator (Object) { return backing.name if (backing.name == "main") return backing.name + if (backing.is_extern) + return backing.name result = "fun_" var upper = backing.scope.get_with_default(string("~enclosing_scope"), vector(null()))[0] if (upper && is_type_def(upper)) @@ -1042,8 +1055,10 @@ obj c_generator (Object) { } if (result == "impossible name") error("HUGE PROBLEMS") - if (ast_name_map.contains_value(result)) + // TODO keyword avoid seems not to work + if (ast_name_map.contains_value(result) || c_keyword_avoid.contains(result)) result += get_id() + println("HERE: " + result) ast_name_map.set(node, result) return result } diff --git a/tests/test_extern.expected_results b/tests/test_extern.expected_results new file mode 100644 index 0000000..a67a57c --- /dev/null +++ b/tests/test_extern.expected_results @@ -0,0 +1 @@ +Hello extern! diff --git a/tests/test_extern.krak b/tests/test_extern.krak new file mode 100644 index 0000000..7553480 --- /dev/null +++ b/tests/test_extern.krak @@ -0,0 +1,8 @@ + +ext fun printf(format_str: *char, actual_str: *char): int + +fun main():int { + printf("%s", "Hello extern!\n") +} + +