diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index c10126f..f5e5034 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -190,27 +190,35 @@ obj type_def (Object) { var scope: map> var name: string var self_type: *type + var variables: vector<*ast_node> + var methods: vector<*ast_node> fun construct(nameIn: string): *type_def { scope.construct() name.copy_construct(&nameIn) self_type = null() + variables.construct() + methods.construct() return this } fun copy_construct(old: *type_def) { self_type = old->self_type scope.copy_construct(&old->scope) name.copy_construct(&old->name) + variables.copy_construct(&old->variables) + methods.copy_construct(&old->methods) } fun destruct() { scope.destruct() name.destruct() + variables.destruct() + methods.destruct() } fun operator=(other: ref type_def) { destruct() copy_construct(&other) } fun operator==(other: ref type_def): bool { - return name == other.name && self_type == other.self_type + return name == other.name && self_type == other.self_type && variables == other.variables && methods == other.methods } } fun ast_adt_def_ptr(name: string): *ast_node { @@ -903,7 +911,7 @@ fun get_ast_children(node: *ast_node): vector<*ast_node> { ast_node::translation_unit(backing) return backing.children ast_node::import(backing) return vector<*ast_node>() ast_node::identifier(backing) return vector<*ast_node>() - ast_node::type_def(backing) return vector<*ast_node>() + ast_node::type_def(backing) return backing.variables + backing.methods ast_node::adt_def(backing) return vector<*ast_node>() ast_node::function(backing) return backing.parameters + backing.body_statement ast_node::code_block(backing) return backing.children diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 3681baa..245d6c0 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -82,13 +82,9 @@ obj ast_transformation (Object) { // defines inside of objects + ADTs, outside declaration statements, and function prototypes fun second_pass(parse_tree: *tree, translation_unit: *ast_node) { println(string("Second Pass for ") + translation_unit->translation_unit.name) + // we go through the parse tree for getting functions, but we're going through the ast for the things we've already set up and using the ast_to_syntax map parse_tree->children.for_each(fun(child: *tree) { - if (child->data.name == "type_def") { - // second pass class stuff - // class insides calls into second_pass_declaration and second_pass_function... - } else if (child->data.name == "adt_def") { - // set up options and all the generated functions (operator==, operator!=, copy_construct, operator=, destruct) - } else if (child->data.name == "function") { + if (child->data.name == "function") { var function_node = second_pass_function(child, translation_unit, map()) translation_unit->translation_unit.children.add(function_node) ast_to_syntax.set(function_node, child) @@ -97,6 +93,26 @@ obj ast_transformation (Object) { translation_unit->translation_unit.children.add(transform_declaration_statement(child, translation_unit)) } }) + // work on the ones already started + translation_unit->translation_unit.children.for_each(fun(node: *ast_node) { + match(*node) { + ast_node::type_def(backing) { + var type_def_syntax = ast_to_syntax[node] + type_def_syntax->children.for_each(fun(child: *tree) { + if (child->data.name == "declaration_statement") { + var declaration_node = transform_declaration_statement(child, node) + node->type_def.variables.add(declaration_node) + ast_to_syntax.set(declaration_node, child) + } else if (child->data.name == "function") { + var function_node = second_pass_function(child, node, map()) + node->type_def.methods.add(function_node) + ast_to_syntax.set(function_node, child) + } + }) + } + ast_node::adt_def(backing) do_nothing() // actually go through and do methods inside + } + }) } fun second_pass_function(node: *tree, translation_unit: *ast_node, template_replacements: map): *ast_node { var function_name = concat_symbol_tree(get_node("func_identifier", node)) @@ -126,7 +142,13 @@ obj ast_transformation (Object) { println(string("Third Pass for ") + translation_unit->translation_unit.name) translation_unit->translation_unit.children.for_each(fun(node: *ast_node) { match(*node) { - ast_node::type_def(backing) do_nothing() // actually go through and do methods inside + ast_node::type_def(backing) { + // make sure not a template? or the method not a template? + // also same body problem as below + node->type_def.methods.for_each(fun(method: *ast_node) { + method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), node) + }) + } ast_node::function(backing) { // make sure not a template // huh, I guess I can't actually assign to the backing. diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index c164554..b0da9a6 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -34,6 +34,27 @@ obj c_generator (Object) { var function_definitions: string = "\n/**Function Definitions**/\n" var variable_declarations: string = "\n/**Variable Declarations**/\n" + // moved out from below so that it can be used for methods as well as regular functions (and eventually lambdas...) + var generate_function_definition = fun(child: *ast_node) { + var backing = child->function + + var parameter_types = string() + var parameters = string() + var decorated_name = generate_function(child) + // also add in name decoration + backing.parameters.for_each(fun(parameter: *ast_node) { + if (parameter_types != "") { parameter_types += ", "; parameters += ", ";} + parameter_types += type_to_c(parameter->identifier.type) + parameters += type_to_c(parameter->identifier.type) + " " + parameter->identifier.name + }) + function_prototypes += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameter_types + ");\n" + + // add parameters to destructor thingy (for returns)? Or should that be a different pass? + function_definitions += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ") {\n" + generate_statement(backing.body_statement) + // emit parameter destructors? + function_definitions += "}\n" + } + var type_poset = poset<*ast_node>() // iterate through asts name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree,*ast_node>) { @@ -52,21 +73,7 @@ obj c_generator (Object) { // make sure not a template // or a passthrough // check for and add to parameters if a closure - var parameter_types = string() - var parameters = string() - var decorated_name = generate_function(child) - // also add in name decoration - backing.parameters.for_each(fun(parameter: *ast_node) { - if (parameter_types != "") { parameter_types += ", "; parameters += ", ";} - parameter_types += type_to_c(parameter->identifier.type) - parameters += type_to_c(parameter->identifier.type) + " " + parameter->identifier.name - }) - function_prototypes += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameter_types + ");\n" - - // add parameters to destructor thingy (for returns)? Or should that be a different pass? - function_definitions += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ") {\n" + generate_statement(backing.body_statement) - // emit parameter destructors? - function_definitions += "}\n" + generate_function_definition(child) } ast_node::type_def(backing) { type_poset.add_vertex(child) @@ -76,7 +83,11 @@ obj c_generator (Object) { }) type_poset.get_sorted().for_each(fun(vert: *ast_node) { plain_typedefs += string("typedef struct ") + vert->type_def.name + "_dummy " + vert->type_def.name + ";\n" - structs += string("struct ") + vert->type_def.name + "_dummy {};\n" + structs += string("struct ") + vert->type_def.name + "_dummy {\n" + vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration) + ";\n";) + structs += "};\n" + // generate the methods + vert->type_def.methods.for_each(fun(method: *ast_node) generate_function_definition(method);) }) return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string_pre+function_typedef_string+function_prototypes+variable_declarations+function_definitions + "\n", linker_string) diff --git a/tests/to_parse.krak b/tests/to_parse.krak index 7df62b7..5d6dbe0 100644 --- a/tests/to_parse.krak +++ b/tests/to_parse.krak @@ -39,6 +39,8 @@ fun main(): int { /*for (var j = 0; j < 10; j++;)*/ /*simple_print(j)*/ var an_obj: Something + /*an_obj.member = 20*/ + /*simple_print(an_obj.member)*/ return 0 }