diff --git a/kraken.krak b/kraken.krak index 36e30e6..499057b 100644 --- a/kraken.krak +++ b/kraken.krak @@ -140,6 +140,7 @@ fun main(argc: int, argv: **char):int { defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) /*printlnerr("Counting Nodes")*/ /*node_counter(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)*/ + // Lowers #ctce and the current #ctce_pass printlnerr("Lowering CTCE") ctce_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) /*printlnerr("Counting Nodes")*/ diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 2bf11fa..56fb37f 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -128,8 +128,6 @@ obj ast_transformation (Object) { } else if (child->data.name == "declaration_statement") { // second pass declaration can actually just call a normal transform (but maybe should be it's own method to do so because typedef has to do it too?)... translation_unit->translation_unit.children.add(transform_declaration_statement(child, translation_unit, map())) - } else if (child->data.name == "compiler_intrinsic") { - translation_unit->translation_unit.children.add(transform_compiler_intrinsic(child, translation_unit, map())) } }) // work on the ones already started @@ -254,30 +252,30 @@ obj ast_transformation (Object) { parameters.for_each(fun(parameter: *ast_node) add_to_scope(parameter->identifier.name, parameter, function_node);) return function_node } - // The third pass finishes up by doing all function bodies (top level and methods in objects) + // The third pass finishes up by doing all function bodies (top level and methods in objects), and top level compiler intrinsics fun third_pass(parse_tree: *tree, translation_unit: *ast_node) { /*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) { - // make sure not a template? or the method not a template? // also same body problem as below - if (!is_template(node)) { - node->type_def.methods.for_each(fun(method: *ast_node) { - if (!is_template(method)) - method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map()) - }) - } + backing.methods.for_each(fun(method: *ast_node) { + if (!is_template(method)) + method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map()) + }) } ast_node::function(backing) { // 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! - if (!node->function.is_extern) - node->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map()) + if (!backing.is_extern) + backing.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map()) } } }) + parse_tree->children.for_each(fun(child: *tree) { + if (child->data.name == "compiler_intrinsic") { + translation_unit->translation_unit.children.add(transform_compiler_intrinsic(child, translation_unit, map())) + } + }) } // The fourth pass generates the class templates that have not yet been generated in a worklist loop fun fourth_pass(parse_tree: *tree, translation_unit: *ast_node) { @@ -889,6 +887,9 @@ obj ast_transformation (Object) { ast_node::if_comp(backing) { return find_closed_variables(func, backing.statement) } + ast_node::cast(backing) { + return find_closed_variables(func, backing.value) + } } return set<*ast_node>() } @@ -910,7 +911,8 @@ obj ast_transformation (Object) { search_type::function(type_vec) possible_value = find_or_instantiate_template_function(concat_symbol_tree(node->children[0]), null>(), scope, type_vec, template_replacements, map()); } if (!possible_value) - error(node, concat_symbol_tree(node) + ": HAS NO POSSIBLE FUNCTION OR FUNCTION TEMPLATE SOLUTIONS") + error(node, concat_symbol_tree(node) + ": HAS NO POSSIBLE FUNCTION OR FUNCTION TEMPLATE SOLUTIONS\nlooking for: " + + concat_symbol_tree(node->children[0]) + "(" + searching_for.function.reduce(fun(n:*type, s:string):string return s+","+n->to_string();, string()) + ")") return possible_value } else if (node->children.size == 2) { var template_inst = get_node("template_inst", node) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index d529155..092bf83 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -204,8 +204,9 @@ obj c_generator (Object) { parameters += ", ..." } var possibly_static = string() - if (!backing.is_extern && decorated_name != "main") - possibly_static = "static " + // commented out to fix phantom crash + /*if (!backing.is_extern && decorated_name != "main")*/ + /*possibly_static = "static "*/ return make_pair(possibly_static + type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameter_types + ");\n", possibly_static + type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ")") } diff --git a/stdlib/ctce_lower.krak b/stdlib/ctce_lower.krak index 02bb831..48cc1f8 100644 --- a/stdlib/ctce_lower.krak +++ b/stdlib/ctce_lower.krak @@ -14,6 +14,7 @@ import pass_common:* fun ctce_lower(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>) { var globals = setup_globals(*name_ast_map) + var ctce_passes = vector<*ast_node>() name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree,*ast_node>) { var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { match(*node) { @@ -21,11 +22,24 @@ fun ctce_lower(name_ast_map: *map,*ast_node>>, ast_to if (backing.intrinsic == "ctce") { var result = evaluate_with_globals(backing.parameters[0], &globals) *node = *unwrap_value(result) + } else if (backing.intrinsic == "ctce_pass") { + ctce_passes.add(backing.parameters[0]) + remove(node, parent_chain) } } } } run_on_tree(helper_before, empty_pass_second_half, syntax_ast_pair.second) }) + ctce_passes.for_each(fun(func: *ast_node) { + // don't want to pick up the ast_node::value + var params = vector() + // easier to pick up types from the function itself + if (!is_function(func)) error(string("trying to CTCE pass with non function") + get_ast_name(func)) + error("what") + /*params.add(interpreter::value::pointer(make_pair((name_ast_map) cast *void, func->function.type->parameter_types[0])))*/ + /*params.add(interpreter::value::pointer(make_pair((ast_to_syntax) cast *void, func->function.type->parameter_types[1])))*/ + /*call_function(func, params, &globals)*/ + }) } diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 39cadd8..fabe63e 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -234,6 +234,13 @@ fun do_basic_op(func_name: string, a: value, b: value): value { error(":/") } return value::boolean(av.first == real_b.pointer.first) + } else if (func_name == "!=") { + if (!is_pointer(real_b)) { + print("inequality between pointer and not pointer: ") + print_value(real_b) + error(":/") + } + return value::boolean(av.first != real_b.pointer.first) } var inc_in_bytes = cast_value(b, type_ptr(base_type::ulong_int())).ulong_int * type_size(av.second->clone_with_decreased_indirection()) var ptr = null() @@ -242,9 +249,9 @@ fun do_basic_op(func_name: string, a: value, b: value): value { } else if (func_name == "-") { ptr = ((av.first) cast *char - inc_in_bytes) cast *void } else { - println(string("pointer arithmatic is not +, -, or ==: ") + func_name + ", b is: ") + println(string("pointer arithmatic is not +, -, ==, or !=: ") + func_name + ", b is: ") print_value(b) - error(string("pointer arithmatic is not +, -, or ==: ") + func_name) + error(string("pointer arithmatic is not +, -, ==, or !=: ") + func_name) } return value::pointer(make_pair(ptr, av.second)) } @@ -575,10 +582,7 @@ fun call_main(name_ast_map: ref map,*ast_node>>) { if (results.size != 1) error(string("wrong number of mains to call: ") + results.size) var globals = setup_globals(name_ast_map) - var var_stack = stack>() - var_stack.push(map<*ast_node,value>()) - var result = call_function(results[0], vector(), vector<*ast_node>(), &var_stack, map<*ast_node,value>(), value::void_nothing(), value::void_nothing(), null(), &globals) - pop_and_free(&var_stack) + var result = call_function(results[0], vector(), &globals) } fun evaluate_constant_expression(node: *ast_node): value return interpret(node, null>>(), value::void_nothing(), null(), null>()).first @@ -717,6 +721,14 @@ fun interpret_function_call(func_call: *ast_node, var_stack: *stack, globals: *map<*ast_node, value>): value { + var var_stack = stack>() + var_stack.push(map<*ast_node,value>()) + var result = call_function(func, parameters, vector<*ast_node>(), &var_stack, map<*ast_node,value>(), value::void_nothing(), value::void_nothing(), null(), globals) + pop_and_free(&var_stack) + return result +} // call_function can be called with either parameter values in parameters or ast expressions in parameter_sources // this is to allow easy function calling if we already have the values (for main, say, or to make our job if it's not // an operator easier), but we need to be able to be called with ast_expressions too so we can properly copy_construct once diff --git a/stdlib/node_counter.krak b/stdlib/node_counter.krak new file mode 100644 index 0000000..0215c5a --- /dev/null +++ b/stdlib/node_counter.krak @@ -0,0 +1,34 @@ +import symbol:* +import tree:* +import vector:* +import map:* +import util:* +import string:* +import mem:* +import io:* +import ast_nodes:* +import ast_transformation:* + +import pass_common:* + +fun node_counter(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>) { + var counter = node_counter_helper(name_ast_map, ast_to_syntax) + println(string("Number of nodes touched: ") + counter) +} +fun node_counter_test(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>) { + var counter = node_counter_helper(name_ast_map, ast_to_syntax) + if (counter > 10000) + println("more than 10000 nodes!") +} +fun node_counter_helper(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>): int { + var counter = 0 + name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree,*ast_node>) { + var helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { + counter++ + } + run_on_tree(helper, empty_pass_second_half, syntax_ast_pair.second) + }) + return counter +} + + diff --git a/tests/test_ctce_pass.expected_results b/tests/test_ctce_pass.expected_results new file mode 100644 index 0000000..32cf98b --- /dev/null +++ b/tests/test_ctce_pass.expected_results @@ -0,0 +1 @@ +more than 10000 nodes! diff --git a/tests/test_ctce_pass.krak b/tests/test_ctce_pass.krak new file mode 100644 index 0000000..fb6ce2d --- /dev/null +++ b/tests/test_ctce_pass.krak @@ -0,0 +1,12 @@ +import node_counter: * + +#ctce_pass(node_counter::node_counter_test) + +fun small_func() { + println("hello") +} + +fun main(): int { + return 0 +} +