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:
Nathan Braswell
2016-07-09 15:08:57 -07:00
parent ddd250e7f3
commit fb63eee9e8
8 changed files with 100 additions and 23 deletions

View File

@@ -140,6 +140,7 @@ fun main(argc: int, argv: **char):int {
defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)*/ /*node_counter(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)*/
// Lowers #ctce and the current #ctce_pass
printlnerr("Lowering CTCE") printlnerr("Lowering CTCE")
ctce_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) ctce_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/

View File

@@ -128,8 +128,6 @@ obj ast_transformation (Object) {
} else if (child->data.name == "declaration_statement") { } 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?)... // 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>())) 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 // 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);) parameters.for_each(fun(parameter: *ast_node) add_to_scope(parameter->identifier.name, parameter, function_node);)
return 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) { fun third_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
/*println(string("Third Pass for ") + translation_unit->translation_unit.name)*/ /*println(string("Third Pass for ") + translation_unit->translation_unit.name)*/
translation_unit->translation_unit.children.for_each(fun(node: *ast_node) { translation_unit->translation_unit.children.for_each(fun(node: *ast_node) {
match(*node) { match(*node) {
ast_node::type_def(backing) { ast_node::type_def(backing) {
// make sure not a template? or the method not a template?
// also same body problem as below // also same body problem as below
if (!is_template(node)) { backing.methods.for_each(fun(method: *ast_node) {
node->type_def.methods.for_each(fun(method: *ast_node) { if (!is_template(method))
if (!is_template(method)) method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map<string, *type>())
method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map<string, *type>()) })
})
}
} }
ast_node::function(backing) { ast_node::function(backing) {
// make sure not a template // make sure not a template
// huh, I guess I can't actually assign to the backing. if (!backing.is_extern)
// This is actually a little bit of a problem, maybe these should be pointers also. All the pointers! backing.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map<string, *type>())
if (!node->function.is_extern)
node->function.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 // 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) { fun fourth_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
@@ -889,6 +887,9 @@ obj ast_transformation (Object) {
ast_node::if_comp(backing) { ast_node::if_comp(backing) {
return find_closed_variables(func, backing.statement) return find_closed_variables(func, backing.statement)
} }
ast_node::cast(backing) {
return find_closed_variables(func, backing.value)
}
} }
return set<*ast_node>() 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>()); 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) 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 return possible_value
} else if (node->children.size == 2) { } else if (node->children.size == 2) {
var template_inst = get_node("template_inst", node) var template_inst = get_node("template_inst", node)

View File

@@ -204,8 +204,9 @@ obj c_generator (Object) {
parameters += ", ..." parameters += ", ..."
} }
var possibly_static = string() var possibly_static = string()
if (!backing.is_extern && decorated_name != "main") // commented out to fix phantom crash
possibly_static = "static " /*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", 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 + ")") possibly_static + type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ")")
} }

View File

@@ -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>>) { 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 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>) { 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>) { var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
match(*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") { if (backing.intrinsic == "ctce") {
var result = evaluate_with_globals(backing.parameters[0], &globals) var result = evaluate_with_globals(backing.parameters[0], &globals)
*node = *unwrap_value(result) *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) 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)*/
})
} }

View File

@@ -234,6 +234,13 @@ fun do_basic_op(func_name: string, a: value, b: value): value {
error(":/") error(":/")
} }
return value::boolean(av.first == real_b.pointer.first) 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 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>() var ptr = null<void>()
@@ -242,9 +249,9 @@ fun do_basic_op(func_name: string, a: value, b: value): value {
} else if (func_name == "-") { } else if (func_name == "-") {
ptr = ((av.first) cast *char - inc_in_bytes) cast *void ptr = ((av.first) cast *char - inc_in_bytes) cast *void
} else { } 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) 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)) 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) if (results.size != 1)
error(string("wrong number of mains to call: ") + results.size) error(string("wrong number of mains to call: ") + results.size)
var globals = setup_globals(name_ast_map) var globals = setup_globals(name_ast_map)
var var_stack = stack<map<*ast_node, value>>() var result = call_function(results[0], vector<value>(), &globals)
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)
} }
fun evaluate_constant_expression(node: *ast_node): value 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 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()) 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 // 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 // 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 // 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
View 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
}

View File

@@ -0,0 +1 @@
more than 10000 nodes!

12
tests/test_ctce_pass.krak Normal file
View 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
}