very basic groundwork for bytecode

This commit is contained in:
Nathan Braswell
2018-02-02 00:26:31 -05:00
parent c0209118e5
commit 7850f11297
4 changed files with 235 additions and 10 deletions

View File

@@ -8,6 +8,7 @@ import symbol:*
import tree:* import tree:*
import serialize:* import serialize:*
import interpreter:* import interpreter:*
import bytecode_generator:*
import os:* import os:*
import ast_transformation:* import ast_transformation:*
import importer:* import importer:*
@@ -25,6 +26,7 @@ import vector:*
import set:* import set:*
fun main(argc: int, argv: **char):int { fun main(argc: int, argv: **char):int {
var curr_time = get_time()
// delay construction until we either load it or copy construct it // delay construction until we either load it or copy construct it
var gram: grammer var gram: grammer
var base_dir = string("/").join(string(argv[0]).split('/').slice(0,-2)) var base_dir = string("/").join(string(argv[0]).split('/').slice(0,-2))
@@ -103,6 +105,7 @@ fun main(argc: int, argv: **char):int {
println("calculated, writing out") println("calculated, writing out")
write_file_binary(compiled_name, serialize(compiled_version) + serialize(file_contents) + serialize(gram)) write_file_binary(compiled_name, serialize(compiled_version) + serialize(file_contents) + serialize(gram))
println("done writing") println("done writing")
curr_time = split(curr_time, "Grammer regen")
} }
var lex = lexer(gram.terminals) var lex = lexer(gram.terminals)
@@ -140,57 +143,71 @@ fun main(argc: int, argv: **char):int {
var executable_name = string(".").join(kraken_file_name.split('.').slice(0,-2)) var executable_name = string(".").join(kraken_file_name.split('.').slice(0,-2))
if (positional_args.size > 1) if (positional_args.size > 1)
executable_name = positional_args[1] executable_name = positional_args[1]
curr_time = split(curr_time, "Finish setup")
var name_ast_map = import(kraken_file_name, parsers, ast_pass, vector(string(), base_dir + "/stdlib/")) var name_ast_map = import(kraken_file_name, parsers, ast_pass, vector(string(), base_dir + "/stdlib/"))
curr_time = split(curr_time, "Import")
// Passes // Passes
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/ /*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/
printlnerr("Lowering ADTs") /*printlnerr("Lowering ADTs")*/
adt_lower(&name_ast_map, &ast_pass.ast_to_syntax) adt_lower(&name_ast_map, &ast_pass.ast_to_syntax)
curr_time = split(curr_time, "Lowering ADTs")
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/ /*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/
printlnerr("Lowering Objects") /*printlnerr("Lowering Objects")*/
obj_lower(&name_ast_map, &ast_pass.ast_to_syntax) obj_lower(&name_ast_map, &ast_pass.ast_to_syntax)
curr_time = split(curr_time, "Lowering Objects")
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/ /*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/
printlnerr("Lowering Defer") /*printlnerr("Lowering Defer")*/
defer_lower(&name_ast_map, &ast_pass.ast_to_syntax) defer_lower(&name_ast_map, &ast_pass.ast_to_syntax)
curr_time = split(curr_time, "Lowering Defer")
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/ /*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/
// Should come after lowering of ADTs and before lowering of Refs // Should come after lowering of ADTs and before lowering of Refs
printlnerr("Lowering Function Values (Lambdas, etc)") /*printlnerr("Lowering Function Values (Lambdas, etc)")*/
function_value_lower(&name_ast_map, &ast_pass.ast_to_syntax) function_value_lower(&name_ast_map, &ast_pass.ast_to_syntax)
curr_time = split(curr_time, "Lowering Function Values (Lambdas, etc)")
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/ /*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/
printlnerr("Lowering Ref") /*printlnerr("Lowering Ref")*/
ref_lower(&name_ast_map, &ast_pass.ast_to_syntax) ref_lower(&name_ast_map, &ast_pass.ast_to_syntax)
curr_time = split(curr_time, "Lowering Ref")
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/ /*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/
// Lowers #ctce and the current #ctce_pass // Lowers #ctce and the current #ctce_pass
printlnerr("Lowering CTCE") /*printlnerr("Lowering CTCE")*/
ctce_lower(&name_ast_map, &ast_pass.ast_to_syntax) ctce_lower(&name_ast_map, &ast_pass.ast_to_syntax)
curr_time = split(curr_time, "Lowering CTCE")
/*printlnerr("Counting Nodes")*/ /*printlnerr("Counting Nodes")*/
/*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/ /*node_counter(&name_ast_map, &ast_pass.ast_to_syntax)*/
// Makes sure that & always takes reference to a variable // Makes sure that & always takes reference to a variable
printlnerr("Lowering & to always have variable") /*printlnerr("Lowering & to always have variable")*/
address_of_ensure_variable_lower(&name_ast_map, &ast_pass.ast_to_syntax) address_of_ensure_variable_lower(&name_ast_map, &ast_pass.ast_to_syntax)
curr_time = split(curr_time, "Lowering & to always have variable")
if (interpret_instead) { if (interpret_instead) {
printlnerr("Interpreting!") /*printlnerr("Interpreting!")*/
call_main(name_ast_map) /*call_main(name_ast_map)*/
printlnerr("Generating bytecode!")
var bytecode = generate_bytecode(name_ast_map, ast_pass.ast_to_syntax)
printlnerr(bytecode_to_string(bytecode))
} else { } else {
if (line_ctrl) { if (line_ctrl) {
printlnerr("running C-specific passes") printlnerr("running C-specific passes")
printlnerr("running #line") printlnerr("running #line")
c_line_control(&name_ast_map, &ast_pass.ast_to_syntax) c_line_control(&name_ast_map, &ast_pass.ast_to_syntax)
} }
printlnerr("Generating C") /*printlnerr("Generating C")*/
var c_generator.construct(): c_generator var c_generator.construct(): c_generator
var c_output_pair = c_generator.generate_c(name_ast_map, ast_pass.ast_to_syntax) var c_output_pair = c_generator.generate_c(name_ast_map, ast_pass.ast_to_syntax)
var kraken_c_output_name = kraken_file_name + ".c" var kraken_c_output_name = kraken_file_name + ".c"
write_file(kraken_c_output_name, c_output_pair.first) write_file(kraken_c_output_name, c_output_pair.first)
curr_time = split(curr_time, "Generating C")
if (compile_c) { if (compile_c) {
var compile_string = "cc -g " + opt_str + " -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Wno-incompatible-pointer-types -std=c99 " + c_output_pair.second + " " + kraken_c_output_name + " -o " + executable_name var compile_string = "cc -g " + opt_str + " -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Wno-incompatible-pointer-types -std=c99 " + c_output_pair.second + " " + kraken_c_output_name + " -o " + executable_name
printlnerr(compile_string) printlnerr(compile_string)
system(compile_string) system(compile_string)
curr_time = split(curr_time, "Compiling C")
} }
} }

View File

@@ -0,0 +1,189 @@
import io:*
import mem:*
import map:*
import hash_map:*
import stack:*
import string:*
import util:*
import tree:*
import symbol:*
import ast_nodes:*
// for error with syntax tree
import pass_common:*
import poset:*
adt byte_inst {
nop
}
fun bytecode_to_string(bytecode: ref vector<byte_inst>): string {
var res = string()
bytecode.for_each(fun(b: byte_inst) {
match (b) {
byte_inst::nop() res += "nop"
}
res += "\n"
})
return res
}
fun generate_bytecode(name_ast_map: ref map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax_in: ref map<*ast_node, *tree<symbol>> ): vector<byte_inst> {
var generator.construct(): bytecode_generator
return generator.generate_bytecode(name_ast_map, ast_to_syntax_in)
}
obj bytecode_generator (Object) {
var id_counter: int
var ast_name_map: hash_map<*ast_node, string>
var bytecode: vector<byte_inst>
fun construct(): *bytecode_generator {
id_counter = 0
ast_name_map.construct()
bytecode.construct()
return this
}
fun copy_construct(old: *bytecode_generator) {
id_counter = old->id_counter
ast_name_map.copy_construct(&old->ast_name_map)
bytecode.copy_construct(&old->bytecode)
}
fun operator=(other: ref bytecode_generator) {
destruct()
copy_construct(&other)
}
fun destruct() {
ast_name_map.destruct()
bytecode.destruct()
}
fun get_id(): string return to_string(id_counter++);
fun generate_bytecode(name_ast_map: map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax_in: map<*ast_node, *tree<symbol>> ): vector<byte_inst> {
// iterate through asts
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>,*ast_node>) {
// iterate through children for each ast
// do lambdas seperatly, so we can reconstitute the enclosing object if it has one
tree_pair.second->translation_unit.lambdas.for_each(fun(child: *ast_node) {
generate_function_definition(child)
})
tree_pair.second->translation_unit.children.for_each(fun(child: *ast_node) {
match (*child) {
ast_node::declaration_statement(backing) generate_declaration_statement(child)
ast_node::compiler_intrinsic(backing) generate_compiler_intrinsic(child)
ast_node::function(backing) generate_function_definition(child)
ast_node::template(backing) {
backing.instantiated.for_each(fun(node: *ast_node) {
match (*node) {
ast_node::function(backing) generate_function_definition(node)
ast_node::type_def(backing) {
backing.methods.for_each(fun(method: *ast_node) {
if (is_template(method))
method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m);)
else
generate_function_definition(method)
})
}
}
})
}
ast_node::type_def(backing) {
backing.methods.for_each(fun(method: *ast_node) {
if (is_template(method))
method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m);)
else
generate_function_definition(method)
})
}
}
})
})
return bytecode
}
fun generate_function_definition(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_declaration_statement(node: *ast_node) {
var identifier = node->declaration_statement.identifier
var ident_type = identifier->identifier.type
if (identifier->identifier.is_extern)
bytecode.add(byte_inst::nop())
if (node->declaration_statement.expression) {
bytecode.add(byte_inst::nop())
}
}
fun generate_assignment_statement(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_if_statement(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_while_loop(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_for_loop(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_identifier(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_return_statement(node: *ast_node) {
if (node->return_statement.return_value)
bytecode.add(byte_inst::nop())
else
bytecode.add(byte_inst::nop())
}
fun generate_branching_statement(node: *ast_node) {
match(node->branching_statement.b_type) {
branching_type::break_stmt() bytecode.add(byte_inst::nop())
branching_type::continue_stmt() bytecode.add(byte_inst::nop())
}
}
fun generate_cast(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_value(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_code_block(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
// this generates the function as a value, not the actual function
fun generate_function(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_function_call(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate_compiler_intrinsic(node: *ast_node) {
bytecode.add(byte_inst::nop())
}
fun generate(node: *ast_node) {
match (*node) {
ast_node::declaration_statement(backing) generate_declaration_statement(node)
ast_node::assignment_statement(backing) generate_assignment_statement(node)
ast_node::if_statement(backing) generate_if_statement(node)
ast_node::while_loop(backing) generate_while_loop(node)
ast_node::for_loop(backing) generate_for_loop(node)
ast_node::function(backing) generate_function(node)
ast_node::function_call(backing) generate_function_call(node)
ast_node::compiler_intrinsic(backing) generate_compiler_intrinsic(node)
ast_node::code_block(backing) generate_code_block(node)
ast_node::return_statement(backing) generate_return_statement(node)
ast_node::branching_statement(backing) generate_branching_statement(node)
ast_node::cast(backing) generate_cast(node)
ast_node::value(backing) generate_value(node)
ast_node::identifier(backing) generate_identifier(node)
}
}
fun get_name(node: *ast_node): string {
var maybe_it = ast_name_map.get_ptr_or_null(node);
if (maybe_it)
return *maybe_it
var result = "name" + get_id()
ast_name_map.set(node, result)
return result
}
}

View File

@@ -10,6 +10,7 @@ import io:*
import ast_nodes:* import ast_nodes:*
import ast_transformation:* import ast_transformation:*
import hash_set:* import hash_set:*
import os:*
import pass_common:* import pass_common:*
@@ -88,6 +89,7 @@ fun in_scope_chain(node: *ast_node, high_scope: *ast_node): bool {
} }
fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) { fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
var curr_time = get_time()
var visited = hash_set<*ast_node>() var visited = hash_set<*ast_node>()
var lambdas = set<*ast_node>() var lambdas = set<*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>) {
@@ -135,6 +137,7 @@ fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node
} }
run_on_tree(helper_before, empty_pass_second_half(), syntax_ast_pair.second, &visited) run_on_tree(helper_before, empty_pass_second_half(), syntax_ast_pair.second, &visited)
}) })
curr_time = split(curr_time, "\tclosed_over_uses + function_value_call_points")
var void_ptr = type_ptr(base_type::void_return(), 1) var void_ptr = type_ptr(base_type::void_return(), 1)
var lambda_type_to_struct_type_and_call_func = map<type, pair<*type, *ast_node>>(); //freaking vexing parse moved var lambda_type_to_struct_type_and_call_func = map<type, pair<*type, *ast_node>>(); //freaking vexing parse moved
@@ -144,6 +147,7 @@ fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node
return set<*type>() return set<*type>()
}) })
var all_type_values = all_types.map(fun(t: *type): type return *t;) var all_type_values = all_types.map(fun(t: *type): type return *t;)
curr_time = split(curr_time, "\tall types/all type values")
all_type_values.for_each(fun(t: type) { all_type_values.for_each(fun(t: type) {
if (t.is_function() && t.indirection == 0 && !t.is_raw && !lambda_type_to_struct_type_and_call_func.contains_key(t)) { if (t.is_function() && t.indirection == 0 && !t.is_raw && !lambda_type_to_struct_type_and_call_func.contains_key(t)) {
var cleaned = t.clone() var cleaned = t.clone()
@@ -197,6 +201,7 @@ fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node
name_ast_map->values.first().second->translation_unit.children.add(lambda_call_function) name_ast_map->values.first().second->translation_unit.children.add(lambda_call_function)
} }
}) })
curr_time = split(curr_time, "\tall type values forEach")
var lambda_creation_funcs = map<*ast_node, *ast_node>() var lambda_creation_funcs = map<*ast_node, *ast_node>()
// create the closure type for each lambda // create the closure type for each lambda
@@ -258,12 +263,14 @@ fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node
lambda_creation_funcs[l]->function.body_statement = body lambda_creation_funcs[l]->function.body_statement = body
name_ast_map->values.first().second->translation_unit.children.add(lambda_creation_funcs[l]) name_ast_map->values.first().second->translation_unit.children.add(lambda_creation_funcs[l])
}) })
curr_time = split(curr_time, "\tlambdas forEach")
function_value_call_points.for_each(fun(p: function_parent_block) { function_value_call_points.for_each(fun(p: function_parent_block) {
// parent is the function call // parent is the function call
var function_struct = p.function var function_struct = p.function
p.parent->function_call.func = lambda_type_to_struct_type_and_call_func[*get_ast_type(p.function)].second p.parent->function_call.func = lambda_type_to_struct_type_and_call_func[*get_ast_type(p.function)].second
p.parent->function_call.parameters.add(0, function_struct) p.parent->function_call.parameters.add(0, function_struct)
}) })
curr_time = split(curr_time, "\tfunction_value_call_points.forEach")
function_value_creation_points.for_each(fun(p: function_parent_block) { function_value_creation_points.for_each(fun(p: function_parent_block) {
var lambda_creation_params = vector<*ast_node>() var lambda_creation_params = vector<*ast_node>()
// add the declaration of the closure struct to the enclosing code block // add the declaration of the closure struct to the enclosing code block
@@ -284,11 +291,13 @@ fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node
var func_call = ast_function_call_ptr(lambda_creation_funcs[p.function], lambda_creation_params) var func_call = ast_function_call_ptr(lambda_creation_funcs[p.function], lambda_creation_params)
replace_with_in(p.function, func_call, p.parent) replace_with_in(p.function, func_call, p.parent)
}) })
curr_time = split(curr_time, "\tfunction_value_creation_points.forEach")
lambdas.for_each(fun(l: *ast_node) l->function.type = l->function.type->clone();) lambdas.for_each(fun(l: *ast_node) l->function.type = l->function.type->clone();)
all_types.for_each(fun(t: *type) { all_types.for_each(fun(t: *type) {
if (lambda_type_to_struct_type_and_call_func.contains_key(*t)) if (lambda_type_to_struct_type_and_call_func.contains_key(*t))
*t = *lambda_type_to_struct_type_and_call_func[*t].first *t = *lambda_type_to_struct_type_and_call_func[*t].first
}) })
curr_time = split(curr_time, "\tlambdas.for_each")
closed_over_uses.for_each(fun(p: pair<*ast_node, pair<*ast_node, *ast_node>>) { closed_over_uses.for_each(fun(p: pair<*ast_node, pair<*ast_node, *ast_node>>) {
var variable = p.first var variable = p.first
var parent = p.second.first var parent = p.second.first
@@ -296,9 +305,11 @@ fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node
var closure_param = lambda->function.parameters[0] var closure_param = lambda->function.parameters[0]
replace_with_in(variable, make_operator_call("*", vector(access_expression(closure_param, variable->identifier.name))), parent) replace_with_in(variable, make_operator_call("*", vector(access_expression(closure_param, variable->identifier.name))), parent)
}) })
curr_time = split(curr_time, "\tclosed_over_uses")
// now we can make them raw // now we can make them raw
lambdas.for_each(fun(l: *ast_node) { lambdas.for_each(fun(l: *ast_node) {
l->function.type->is_raw = true; l->function.type->is_raw = true;
}) })
curr_time = split(curr_time, "\tlambdas is raw")
} }

View File

@@ -22,3 +22,11 @@ fun from_system_command(command: string, line_size: int): string {
pclose(p) pclose(p)
return to_ret return to_ret
} }
fun get_time(): long { return string_to_num<long>(from_system_command(string("date +%s"), 50)); }
fun split(time: long, split_label: *char): long {
var new_time = get_time()
print(string(split_label) + ": ")
println(new_time - time)
return new_time
}