Commit pre enabling CTCE pass (which is quite slow, but does work). Had to add walking through cast nodes for finding variables to close over. Also had to remove the static in front of functions to prevent gcc compiling it so that it segfaults (doesn't segfault if compiled with clang, but wanted to make sure.)
This commit is contained in:
@@ -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")*/
|
||||
|
||||
@@ -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<string, *type>()))
|
||||
} else if (child->data.name == "compiler_intrinsic") {
|
||||
translation_unit->translation_unit.children.add(transform_compiler_intrinsic(child, translation_unit, map<string, *type>()))
|
||||
}
|
||||
})
|
||||
// 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<symbol>, 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) {
|
||||
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<string, *type>())
|
||||
})
|
||||
}
|
||||
}
|
||||
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<string, *type>())
|
||||
if (!backing.is_extern)
|
||||
backing.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map<string, *type>())
|
||||
}
|
||||
}
|
||||
})
|
||||
parse_tree->children.for_each(fun(child: *tree<symbol>) {
|
||||
if (child->data.name == "compiler_intrinsic") {
|
||||
translation_unit->translation_unit.children.add(transform_compiler_intrinsic(child, translation_unit, map<string, *type>()))
|
||||
}
|
||||
})
|
||||
}
|
||||
// The fourth pass generates the class templates that have not yet been generated in a worklist loop
|
||||
fun fourth_pass(parse_tree: *tree<symbol>, 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<tree<symbol>>(), scope, type_vec, template_replacements, map<string, *type>());
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -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 + ")")
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import pass_common:*
|
||||
|
||||
fun ctce_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
||||
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<symbol>,*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<string, pair<*tree<symbol>,*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<interpreter::value>()
|
||||
// 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)*/
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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<void>()
|
||||
@@ -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<string, pair<*tree<symbol>,*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<map<*ast_node, value>>()
|
||||
var_stack.push(map<*ast_node,value>())
|
||||
var result = call_function(results[0], vector<value>(), vector<*ast_node>(), &var_stack, map<*ast_node,value>(), value::void_nothing(), value::void_nothing(), null<ast_node>(), &globals)
|
||||
pop_and_free(&var_stack)
|
||||
var result = call_function(results[0], vector<value>(), &globals)
|
||||
}
|
||||
fun evaluate_constant_expression(node: *ast_node): value
|
||||
return interpret(node, null<stack<map<*ast_node, value>>>(), value::void_nothing(), null<ast_node>(), null<map<*ast_node, value>>()).first
|
||||
@@ -717,6 +721,14 @@ fun interpret_function_call(func_call: *ast_node, var_stack: *stack<map<*ast_nod
|
||||
}
|
||||
return make_pair(call_function(func_call_func, parameters, parameter_sources, var_stack, possible_closure_map, enclosing_object, new_enclosing_object, enclosing_func, globals), control_flow::nor())
|
||||
}
|
||||
|
||||
fun call_function(func: *ast_node, parameters: vector<value>, globals: *map<*ast_node, value>): value {
|
||||
var var_stack = stack<map<*ast_node, value>>()
|
||||
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<ast_node>(), 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
|
||||
|
||||
34
stdlib/node_counter.krak
Normal file
34
stdlib/node_counter.krak
Normal file
@@ -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<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
||||
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<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
||||
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<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>): int {
|
||||
var counter = 0
|
||||
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*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
|
||||
}
|
||||
|
||||
|
||||
1
tests/test_ctce_pass.expected_results
Normal file
1
tests/test_ctce_pass.expected_results
Normal file
@@ -0,0 +1 @@
|
||||
more than 10000 nodes!
|
||||
12
tests/test_ctce_pass.krak
Normal file
12
tests/test_ctce_pass.krak
Normal file
@@ -0,0 +1,12 @@
|
||||
import node_counter: *
|
||||
|
||||
#ctce_pass(node_counter::node_counter_test)
|
||||
|
||||
fun small_func() {
|
||||
println("hello")
|
||||
}
|
||||
|
||||
fun main(): int {
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user