From 2051f54b559ac5edf67277d4f1134aca2cb9215d Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 28 Apr 2016 18:47:53 -0400 Subject: [PATCH] Added in sizeof intrinsic + piping for more in the future. Inbetween commit before removing sizeof function --- krakenGrammer.kgm | 6 ++- stdlib/ast_nodes.krak | 48 +++++++++++++++++++ stdlib/ast_transformation.krak | 17 +++++++ stdlib/c_generator.krak | 10 ++++ stdlib/importer.krak | 1 + .../test_compiler_intrinsic.expected_results | 5 ++ tests/test_compiler_intrinsic.krak | 12 +++++ 7 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 tests/test_compiler_intrinsic.expected_results create mode 100644 tests/test_compiler_intrinsic.krak diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 8f60d21..37582ca 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -117,6 +117,10 @@ continue_statement = "continue" ; defer_statement = "defer" WS statement ; function_call = unarad WS "\(" WS opt_parameter_list WS "\)" ; +compiler_intrinsic = "#" identifier WS "\(" WS intrinsic_parameter_list WS "\)" | "#" identifier WS "<" WS type_list WS ">" ; +intrinsic_parameter_list = intrinsic_parameter_list WS "," WS intrinsic_parameter | intrinsic_parameter ; +intrinsic_parameter = identifier ; + boolean_expression = boolean_expression WS "\|\|" WS and_boolean_expression | and_boolean_expression ; and_boolean_expression = and_boolean_expression WS "&&" WS bitwise_or | bitwise_or ; bitwise_or = bitwise_or WS "\|" WS bitwise_xor | bitwise_xor ; @@ -129,7 +133,7 @@ expression = expression WS "<<" WS term | expression WS right_shift WS shiftand shiftand = shiftand WS "-" WS term | shiftand WS "\+" WS term | term ; term = term WS "/" WS factor | term WS "\*" WS factor | term WS "%" WS factor | factor ; factor = "\+\+" WS unarad | unarad WS "\+\+" | "--" WS unarad | unarad WS "--" | "\+" WS unarad | "-" WS unarad | "!" WS unarad | "~" WS unarad | "\*" WS unarad | "&" WS unarad | unarad ; -unarad = number | scoped_identifier | scoped_identifier WS template_inst | access_operation | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | unarad WS "[" WS expression WS "]" | lambda | cast_expression ; +unarad = number | scoped_identifier | scoped_identifier WS template_inst | access_operation | function_call | compiler_intrinsic | bool | string | character | "\(" WS boolean_expression WS "\)" | unarad WS "[" WS expression WS "]" | lambda | cast_expression ; cast_expression = "\(" WS boolean_expression WS "\)" WS "cast" WS type ; number = integer | floating_literal ; access_operation = unarad WS "." WS identifier | unarad WS "->" WS identifier | unarad WS "." WS identifier WS template_inst | unarad WS "->" WS identifier WS template_inst ; diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index d58c2b5..3287a58 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -35,6 +35,7 @@ adt ast_node { if_comp: if_comp, simple_passthrough: simple_passthrough, function_call: function_call, + compiler_intrinsic: compiler_intrinsic, cast: cast, value: value } @@ -961,6 +962,50 @@ obj function_call (Object) { return func == func && parameters == other.parameters } } +fun ast_compiler_intrinsic_ptr(intrinsic: string, parameters: vector, type_parameters: vector<*type>, return_type: *type): *ast_node { + var to_ret.construct(intrinsic, parameters, type_parameters, return_type): compiler_intrinsic + var ptr = new() + ptr->copy_construct(&ast_node::compiler_intrinsic(to_ret)) + return ptr +} +fun is_compiler_intrinsic(node: *ast_node): bool { + match(*node) { + ast_node::compiler_intrinsic(backing) return true + } + return false +} +obj compiler_intrinsic (Object) { + var intrinsic: string + var parameters: vector + var type_parameters: vector<*type> + var return_type: *type + fun construct(intrinsic_in: string, parameters_in: vector, type_parameters_in: vector<*type>, return_type_in: *type): *compiler_intrinsic { + intrinsic.copy_construct(&intrinsic_in) + parameters.copy_construct(¶meters_in) + type_parameters.copy_construct(&type_parameters_in) + return_type = return_type_in + return this + } + /*fun copy_construct(old: *function_call) {*/ + fun copy_construct(old: *compiler_intrinsic) { + intrinsic.copy_construct(&old->intrinsic) + parameters.copy_construct(&old->parameters) + type_parameters.copy_construct(&old->type_parameters) + return_type = old->return_type + } + fun destruct() { + intrinsic.destruct() + parameters.destruct() + type_parameters.destruct() + } + fun operator=(other: ref compiler_intrinsic) { + destruct() + copy_construct(&other) + } + fun operator==(other: ref compiler_intrinsic): bool { + return intrinsic == intrinsic && parameters == other.parameters && type_parameters == other.type_parameters && return_type == other.return_type + } +} fun ast_cast_ptr(value: *ast_node, to_type: *type): *ast_node { var to_ret.construct(value, to_type): cast var ptr = new() @@ -1059,6 +1104,7 @@ fun get_ast_children(node: *ast_node): vector<*ast_node> { ast_node::if_comp(backing) return vector<*ast_node>(backing.statement) ast_node::simple_passthrough(backing) return vector<*ast_node>() ast_node::function_call(backing) return vector(backing.func) + backing.parameters + ast_node::compiler_intrinsic(backing) return vector<*ast_node>() ast_node::cast(backing) return vector<*ast_node>(backing.value) ast_node::value(backing) return vector<*ast_node>() } @@ -1087,6 +1133,7 @@ fun get_ast_name(node: *ast_node): string { ast_node::if_comp(backing) return string("if_comp: ") + backing.wanted_generator ast_node::simple_passthrough(backing) return string("simple_passthrough: , string:") + backing.passthrough_str ast_node::function_call(backing) return string("function_call:") + get_ast_name(backing.func) + "(" + backing.parameters.size + ")" + ast_node::compiler_intrinsic(backing) return string("compiler_intrinsic:") + backing.intrinsic + "(" + backing.parameters.size + "," + backing.type_parameters.size + "):" + backing.return_type->to_string() ast_node::cast(backing) return string("cast: ") + get_ast_name(backing.value) + ": " + backing.to_type->to_string() ast_node::value(backing) return string("value: ") + backing.string_value + ": " + backing.value_type->to_string() } @@ -1119,6 +1166,7 @@ fun get_ast_type(node: *ast_node): *type { ast_node::identifier(backing) return backing.type ast_node::function(backing) return backing.type ast_node::function_call(backing) return get_ast_type(backing.func)->return_type + ast_node::compiler_intrinsic(backing) return backing.return_type ast_node::cast(backing) return backing.to_type ast_node::value(backing) return backing.value_type } diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 9fd4f79..5342f34 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -454,6 +454,8 @@ obj ast_transformation (Object) { return transform_match_statement(node, scope, template_replacements) } else if (name == "function_call") { return transform_function_call(node, scope, template_replacements) + } else if (name == "compiler_intrinsic") { + return transform_compiler_intrinsic(node, scope, template_replacements) } else if (name == "lambda") { return transform_lambda(node, scope, template_replacements) } else if (name == "boolean_expression" || name == "and_boolean_expression" @@ -755,6 +757,16 @@ obj ast_transformation (Object) { /*f->function_call.parameters.for_each(fun(param: *ast_node) print(param);)*/ return f } + fun transform_compiler_intrinsic(node: *tree, scope: *ast_node, template_replacements: map): *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 = vector() + var type_parameters = vector<*type>() + if (get_nodes("intrinsic_parameter", node).size) + parameters = get_nodes("intrinsic_parameter", node).map(fun(child: *tree): string return concat_symbol_tree(child);) + if (get_nodes("type", node).size) + type_parameters = get_nodes("type", node).map(fun(child: *tree): *type return transform_type(child, scope, template_replacements);) + return ast_compiler_intrinsic_ptr(concat_symbol_tree(get_node("identifier", node)), parameters, type_parameters, type_ptr(base_type::integer())) + } fun transform_lambda(node: *tree, scope: *ast_node, template_replacements: map): *ast_node { var function_node = second_pass_function(node, scope, template_replacements, false) function_node->function.body_statement = transform_statement(get_node("statement", node), function_node, template_replacements) @@ -918,6 +930,11 @@ obj ast_transformation (Object) { } } } + // this is the case where it's null but not a method call. Should add default to case above and move there + if (!second_param) { + error(node, "Could not find member " + concat_symbol_tree(node->children[2]) + " on the right side of (. or ->) " + concat_symbol_tree(node->children[0]) + + ", whole string: " + concat_symbol_tree(node) + ", left type: " + get_ast_type(first_param)->to_string()) + } } else { second_param = transform(node->children[2], scope, template_replacements) } diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 52fd151..5315ce9 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -911,6 +911,15 @@ obj c_generator (Object) { call_string.value = ref_pre + call_string.value + ref_post return call_string } + fun generate_compiler_intrinsic(node: *ast_node): code_triple { + if (node->compiler_intrinsic.intrinsic == "sizeof") { + if (node->compiler_intrinsic.parameters.size || node->compiler_intrinsic.type_parameters.size != 1) + error("wrong parameters to sizeof compiler intrinsic") + return code_triple("sizeof(") + type_to_c(node->compiler_intrinsic.type_parameters[0]) + ")" + } + error(node->compiler_intrinsic.intrinsic + ": unknown intrinsic") + return code_triple("ERROR") + } // for now, anyway fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>, need_variable: bool): code_triple { @@ -926,6 +935,7 @@ obj c_generator (Object) { ast_node::for_loop(backing) return generate_for_loop(node, enclosing_object, enclosing_func, defer_stack) ast_node::function(backing) return generate_function(node, enclosing_object, enclosing_func, true, need_variable) ast_node::function_call(backing) return generate_function_call(node, enclosing_object, enclosing_func, need_variable) + ast_node::compiler_intrinsic(backing) return generate_compiler_intrinsic(node) ast_node::code_block(backing) return generate_code_block(node, enclosing_object, enclosing_func, defer_stack) ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func, defer_stack) ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, enclosing_func, defer_stack) diff --git a/stdlib/importer.krak b/stdlib/importer.krak index a5f61db..fe76597 100644 --- a/stdlib/importer.krak +++ b/stdlib/importer.krak @@ -123,6 +123,7 @@ obj importer (Object) { collapse_node(symbol("param_assign_list", false), parse_tree) collapse_node(symbol("opt_typed_parameter_list", false), parse_tree) collapse_node(symbol("opt_parameter_list", false), parse_tree) + collapse_node(symbol("intrinsic_parameter_list", false), parse_tree) collapse_node(symbol("identifier_list", false), parse_tree) collapse_node(symbol("adt_option_list", false), parse_tree) collapse_node(symbol("statement_list", false), parse_tree) diff --git a/tests/test_compiler_intrinsic.expected_results b/tests/test_compiler_intrinsic.expected_results new file mode 100644 index 0000000..ddddcb1 --- /dev/null +++ b/tests/test_compiler_intrinsic.expected_results @@ -0,0 +1,5 @@ +1 +4 +4 +8 +8 diff --git a/tests/test_compiler_intrinsic.krak b/tests/test_compiler_intrinsic.krak new file mode 100644 index 0000000..845989e --- /dev/null +++ b/tests/test_compiler_intrinsic.krak @@ -0,0 +1,12 @@ +import simple_print:* + +fun main(): int { + println(#sizeof) + println(#sizeof) + println(#sizeof) + println(#sizeof) + println(#sizeof<*void>) + return 0 +} + +