diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 4f0157e..2a12825 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -83,9 +83,8 @@ opt_parameter_list = parameter_list | ; parameter_list = parameter_list WS "," WS parameter | parameter ; parameter = boolean_expression ; -def_nonterm = "def" ; -obj_nonterm = "obj" ; -type_def = def_nonterm WS identifier WS type | obj_nonterm WS identifier WS template_dec WS "{" WS declaration_block WS "}" | obj_nonterm WS identifier WS "{" WS declaration_block WS "}" | obj_nonterm WS identifier WS template_dec WS traits WS "{" WS declaration_block WS "}" | obj_nonterm WS identifier WS traits WS "{" WS declaration_block WS "}" ; +obj_nonterm = "obj" | "uni" ; +type_def = obj_nonterm WS identifier WS template_dec WS "{" WS declaration_block WS "}" | obj_nonterm WS identifier WS "{" WS declaration_block WS "}" | obj_nonterm WS identifier WS template_dec WS traits WS "{" WS declaration_block WS "}" | obj_nonterm WS identifier WS traits WS "{" WS declaration_block WS "}" ; declaration_block = declaration_statement line_end WS declaration_block | function WS declaration_block | declaration_statement line_end | function | ; traits = "\(" WS trait_list WS "\)" ; diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index e466ea7..1945db3 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -190,8 +190,10 @@ obj identifier (Object) { return name == other.name && type == other.type && enclosing_scope == other.enclosing_scope } } -fun ast_type_def_ptr(name: string): *ast_node { - var to_ret.construct(name): type_def +fun ast_type_def_ptr(name: ref string): *ast_node + return ast_type_def_ptr(name, false) +fun ast_type_def_ptr(name: ref string, is_union: bool): *ast_node { + var to_ret.construct(name, is_union): type_def var ptr = new() ptr->copy_construct(&ast_node::type_def(to_ret)) return ptr @@ -205,12 +207,14 @@ fun is_type_def(node: *ast_node): bool { obj type_def (Object) { var scope: map> var name: string + var is_union: bool var self_type: *type var variables: vector<*ast_node> var methods: vector<*ast_node> - fun construct(nameIn: string): *type_def { + fun construct(nameIn: ref string, is_unionIn: bool): *type_def { scope.construct() name.copy_construct(&nameIn) + is_union = is_unionIn self_type = null() variables.construct() methods.construct() @@ -220,6 +224,7 @@ obj type_def (Object) { self_type = old->self_type scope.copy_construct(&old->scope) name.copy_construct(&old->name) + is_union = old->is_union variables.copy_construct(&old->variables) methods.copy_construct(&old->methods) } @@ -234,7 +239,7 @@ obj type_def (Object) { copy_construct(&other) } fun operator==(other: ref type_def): bool { - return name == other.name && self_type == other.self_type && variables == other.variables && methods == other.methods + return name == other.name && is_union == other.is_union && self_type == other.self_type && variables == other.variables && methods == other.methods } } fun ast_adt_def_ptr(name: string): *ast_node { @@ -1128,7 +1133,7 @@ fun get_ast_name(node: *ast_node): string { ast_node::translation_unit(backing) return string("translation_unit: ") + backing.name ast_node::import(backing) return string("import: ") + backing.name + "; [" + backing.imported.reduce(fun(name: string, acc: string): string return acc + " " + name;, 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::type_def(backing) return string("type_def: ") + backing.name + " union?:" + backing.is_union ast_node::adt_def(backing) return string("adt_def: ") + backing.name ast_node::function(backing) { if (backing.is_extern) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 01fd189..8dac84e 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -103,7 +103,8 @@ obj ast_transformation (Object) { add_to_scope(name, template, scope) return template } else { - var type_def_node = ast_type_def_ptr(name) + // pass in whether or not this is a union + var type_def_node = ast_type_def_ptr(name, concat_symbol_tree(get_node("obj_nonterm", child)) == "uni") type_def_node->type_def.self_type = type_ptr(type_def_node, transform_traits(get_node("traits", child))) ast_to_syntax.set(type_def_node, child) add_to_scope("~enclosing_scope", scope, type_def_node) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index d2032b3..9db2783 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -445,8 +445,16 @@ obj c_generator (Object) { type_poset.get_sorted().for_each(fun(vert: *ast_node) { /*var base_name = vert->type_def.name*/ var base_name = get_name(vert) - plain_typedefs += string("typedef struct ") + base_name + "_dummy " + base_name + ";\n" - structs += string("struct ") + base_name + "_dummy {\n" + plain_typedefs += string("typedef ") + if (vert->type_def.is_union) { + plain_typedefs += "union " + structs += "union " + } else { + plain_typedefs += "struct " + structs += "struct " + } + plain_typedefs += base_name + "_dummy " + base_name + ";\n" + structs += base_name + "_dummy {\n" if (is_type_def(vert)) { vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null(), null>>>(), false).one_string() + ";\n";) // also no defer stack // generate the methods (note some of these may be templates) diff --git a/stdlib/importer.krak b/stdlib/importer.krak index 5c0ad88..b339f97 100644 --- a/stdlib/importer.krak +++ b/stdlib/importer.krak @@ -123,8 +123,7 @@ obj importer (Object) { remove_node(symbol("\"while\"", true), parse_tree) remove_node(symbol("\"__if_comp__\"", true), parse_tree) remove_node(symbol("\"comp_simple_passthrough\"", true), parse_tree) - remove_node(symbol("def_nonterm", false), parse_tree) - remove_node(symbol("obj_nonterm", false), parse_tree) + /*remove_node(symbol("obj_nonterm", false), parse_tree)*/ remove_node(symbol("adt_nonterm", false), parse_tree) collapse_node(symbol("case_statement_list", false), parse_tree) diff --git a/stdlib/string.krak b/stdlib/string.krak index 3126e00..db1b1ae 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -4,6 +4,9 @@ import mem import serialize import io +fun to_string(in: bool): string + if (in) return string("true") + else return string("false") fun to_string(in: uchar): string return to_string_num(in) fun to_string(in: short): string @@ -168,6 +171,7 @@ obj string (Object, Serializable) { } fun operator+(integer: int): string return *this + to_string(integer); + fun operator+(b: bool): string return *this + to_string(b); fun operator+(str: *char): string { var newStr.construct(str):string @@ -181,6 +185,7 @@ obj string (Object, Serializable) { } fun operator+=(integer: int) *this += to_string(integer); + fun operator+=(b: bool) *this += to_string(b); fun operator+=(character: char): void { data += character diff --git a/tests/test_union.expected_results b/tests/test_union.expected_results new file mode 100644 index 0000000..c88bae3 --- /dev/null +++ b/tests/test_union.expected_results @@ -0,0 +1,3 @@ +true +4 +4.400000 diff --git a/tests/test_union.krak b/tests/test_union.krak new file mode 100644 index 0000000..4397307 --- /dev/null +++ b/tests/test_union.krak @@ -0,0 +1,22 @@ +import io:* + +uni packed { + var a: int + var b: double +} + +obj loose { + var a: int + var b: double +} + +fun main():int { + var a: packed + var b: loose + println(#sizeof < #sizeof) + a.a = 4 + println(a.a) + a.b = 4.4 + println(a.b) + return 0 +}