More clean up; need to add return type checking pass so that can clean up c_generator more.

This commit is contained in:
Nathan Braswell
2017-10-23 01:08:25 -04:00
parent 6964df5ac8
commit 13f1e9df89
4 changed files with 93 additions and 143 deletions

View File

@@ -44,7 +44,7 @@ obj ast_transformation (Object) {
fourth_pass_worklist.destruct()
}
// first pass defines all type_defs (objects and aliases), ADTs, and top-level if-comps/passthroughs
fun first_pass(file_name: string, parse_tree: *tree<symbol>, importer: *importer): pair<*ast_node, vector<*ast_node>> {
fun first_pass(file_name: string, parse_tree: *tree<symbol>): pair<*ast_node, vector<*ast_node>> {
var translation_unit = ast_translation_unit_ptr(file_name)
parse_tree->children.for_each(fun(child: *tree<symbol>) {
if (child->data.name == "type_def") {

View File

@@ -165,7 +165,7 @@ obj c_generator (Object) {
if (!backing.is_extern)
function_definitions += prototype_and_header.second
if (backing.body_statement) {
function_definitions += " {\n" + generate(backing.body_statement, enclosing_object, child, false)
function_definitions += " {\n" + generate(backing.body_statement, enclosing_object, child)
function_definitions += ";\n}\n"
} else if (!backing.is_extern) {
error("Empty function statement and not extern - no ADTs anymore!")
@@ -190,7 +190,7 @@ obj c_generator (Object) {
tree_pair.second->translation_unit.children.for_each(fun(child: *ast_node) {
match (*child) {
ast_node::if_comp(backing) error("if_comp not currently supported")
ast_node::simple_passthrough(backing) error("simple_passthrough deprecated")
ast_node::simple_passthrough(backing) error("simple_passthrough removed")
ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null<ast_node>(), null<ast_node>()) + ";\n" // false - don't do defer
// shouldn't need to do anything with return, as the intrinsic should be something like link
ast_node::compiler_intrinsic(backing) generate_compiler_intrinsic(child)
@@ -221,9 +221,7 @@ obj c_generator (Object) {
type_poset.add_relationship(child, var_type->type_def)
})
}
ast_node::adt_def(backing) {
error("ADT remaining!")
}
ast_node::adt_def(backing) error("ADT remaining!")
}
})
})
@@ -257,57 +255,48 @@ obj c_generator (Object) {
fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
var identifier = node->declaration_statement.identifier
var ident_type = identifier->identifier.type
// we do the declaration in the pre now so that we can take it's address to close over it for things like recursive closures
// we only make it first if it's a function type though, so that global levels still work
var to_ret = type_to_c(identifier->identifier.type) + " " + get_name(identifier)
if (identifier->identifier.is_extern)
to_ret = "extern " + to_ret
if (node->declaration_statement.expression) {
if (ident_type->is_function()) {
to_ret += ";\n"
to_ret += get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, false)
} else {
// some shifting around to get it to work in all cases
// what cases?
to_ret += " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, false)
}
// in case of recursive closures, make sure variable is declared before assignment
to_ret += ";\n"
to_ret += get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func)
}
if (node->declaration_statement.init_method_call) {
to_ret += ";\n"
to_ret += generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, false)
to_ret += generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func)
}
return to_ret
}
fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
return generate(node->assignment_statement.to, enclosing_object, enclosing_func, false) + " = " + generate(node->assignment_statement.from, enclosing_object, enclosing_func, false)
return generate(node->assignment_statement.to, enclosing_object, enclosing_func) + " = " + generate(node->assignment_statement.from, enclosing_object, enclosing_func)
}
fun generate_if_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
var if_str = "if (" + generate(node->if_statement.condition, enclosing_object, enclosing_func, false) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func, false) + "}"
var if_str = "if (" + generate(node->if_statement.condition, enclosing_object, enclosing_func) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func) + "}"
if (node->if_statement.else_part)
if_str += " else {\n" + generate(node->if_statement.else_part, enclosing_object, enclosing_func, false) + "}"
if_str += " else {\n" + generate(node->if_statement.else_part, enclosing_object, enclosing_func) + "}"
return if_str + "\n"
}
fun generate_while_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
return "while (" + generate(node->while_loop.condition, enclosing_object, enclosing_func, false) + ")\n" + generate(node->while_loop.statement, enclosing_object, enclosing_func, false)
return "while (" + generate(node->while_loop.condition, enclosing_object, enclosing_func) + ")\n" + generate(node->while_loop.statement, enclosing_object, enclosing_func)
}
fun generate_for_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
// gotta take off last semicolon
var init = string(";")
if (node->for_loop.init)
init = generate(node->for_loop.init, enclosing_object, enclosing_func, false)
init = generate(node->for_loop.init, enclosing_object, enclosing_func)
var cond = string(";")
if (node->for_loop.condition)
cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, false)
cond = generate(node->for_loop.condition, enclosing_object, enclosing_func)
// gotta take off last semicolon
var update = string()
if (node->for_loop.update) {
update = generate(node->for_loop.update, enclosing_object, enclosing_func, false)
update = generate(node->for_loop.update, enclosing_object, enclosing_func)
if (update.length() < 2)
error("update less than 2! Likely legal, but need easy compiler mod here")
update = update.slice(0,-2)
}
var to_ret = string("for (") + init + cond + "; " + update + ")\n" +
generate(node->for_loop.body, enclosing_object, enclosing_func, false)
return to_ret
return "for (" + init + cond + "; " + update + ")\n" + generate(node->for_loop.body, enclosing_object, enclosing_func)
}
fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
if (get_ast_type(node)->is_ref)
@@ -326,7 +315,7 @@ obj c_generator (Object) {
error("still exsisting ref in return")
if (return_value)
return "return " + generate(return_value, enclosing_object, enclosing_func, false)
return "return " + generate(return_value, enclosing_object, enclosing_func)
return string("return")
}
fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
@@ -342,7 +331,7 @@ obj c_generator (Object) {
error("remaining match")
}
fun generate_cast(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
return "((" + type_to_c(node->cast.to_type) + ")(" + generate(node->cast.value, enclosing_object, enclosing_func, false) + "))"
return "((" + type_to_c(node->cast.to_type) + ")(" + generate(node->cast.value, enclosing_object, enclosing_func) + "))"
}
fun generate_value(node: *ast_node): string {
var value = node->value.string_value
@@ -370,14 +359,14 @@ obj c_generator (Object) {
}
fun generate_code_block(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
var to_ret = string("{\n")
node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, false) + ";\n";)
node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func) + ";\n";)
return to_ret + "}"
}
// this generates the function as a value, not the actual function
fun generate_function(node: *ast_node): string {
return get_name(node)
}
fun generate_function_call(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, need_variable: bool): string {
fun generate_function_call(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
var func_name = string()
var call_string = string()
var func_return_type = get_ast_type(node)
@@ -390,9 +379,9 @@ obj c_generator (Object) {
if (node->function_call.func->function_call.func->function.name == ".")
call_string += "&"
call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, true)
call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func)
} else {
func_name = generate(node->function_call.func, enclosing_object, enclosing_func, false)
func_name = generate(node->function_call.func, enclosing_object, enclosing_func)
// handle method call from inside method of same object
if (enclosing_object && method_in_object(node->function_call.func, enclosing_object)) {
@@ -406,25 +395,22 @@ obj c_generator (Object) {
|| func_name == "==" || func_name == "!=" || func_name == "%" || func_name == "^"
|| func_name == "|" || func_name == "&" || func_name == ">>" || func_name == "<<"
))
return "(" + generate(parameters[0], enclosing_object, enclosing_func, false) + func_name + generate(parameters[1], enclosing_object, enclosing_func, false) + ")"
if ( parameters.size == 2 && (func_name == "||" || func_name == "&&")) {
return "(" + generate(parameters[0], enclosing_object, enclosing_func) + func_name + generate(parameters[1], enclosing_object, enclosing_func) + ")"
if ( parameters.size == 2 && (func_name == "||" || func_name == "&&"))
error("Remaining || or &&")
}
// don't propegate enclosing function down right of access
// XXX what about enclosing object? should it be the thing on the left?
if (func_name == "." || func_name == "->") {
return "(" + generate(parameters[0], enclosing_object, enclosing_func, false) + func_name + generate(parameters[1], null<ast_node>(), null<ast_node>(), false) + ")"
}
if (func_name == "." || func_name == "->")
return "(" + generate(parameters[0], enclosing_object, enclosing_func) + func_name + generate(parameters[1], null<ast_node>(), null<ast_node>()) + ")"
if (func_name == "[]")
return "(" + generate(parameters[0], enclosing_object, enclosing_func, false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, false) + "])"
return "(" + generate(parameters[0], enclosing_object, enclosing_func) + "[" + generate(parameters[1], enclosing_object, enclosing_func) + "])"
// the post ones need to be post-ed specifically, and take the p off
if (func_name == "++p" || func_name == "--p")
return "(" + generate(parameters[0], enclosing_object, enclosing_func, false) + ")" + func_name.slice(0,-2)
return "(" + generate(parameters[0], enclosing_object, enclosing_func) + ")" + func_name.slice(0,-2)
// So we don't end up copy_constructing etc, we just handle the unary operators right here
// note also the passing down need_variable for &
if (func_name == "*" || func_name == "&")
return "(" + func_name + generate(parameters[0], enclosing_object, enclosing_func, func_name == "&") + ")"
return "(" + func_name + generate(parameters[0], enclosing_object, enclosing_func) + ")"
var func_type = get_ast_type(node->function_call.func)
// regular parameter generation
@@ -443,8 +429,7 @@ obj c_generator (Object) {
error(string("problem :") + (node->function_call.func) cast int + " " + get_fully_scoped_name(node->function_call.func) + ": still ref in function calling, func_type: " + func_type->to_string())
}
var param_type = get_ast_type(param)
call_string += generate(param, enclosing_object, enclosing_func, false)
call_string += generate(param, enclosing_object, enclosing_func)
}
call_string = func_name + "(" + call_string + ")"
return call_string
@@ -466,7 +451,7 @@ obj c_generator (Object) {
}
// for now, anyway
fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, need_variable: bool): string {
fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): string {
if (!node) return string("/*NULL*/")
match (*node) {
ast_node::declaration_statement(backing) return generate_declaration_statement(node, enclosing_object, enclosing_func)
@@ -475,7 +460,7 @@ obj c_generator (Object) {
ast_node::while_loop(backing) return generate_while_loop(node, enclosing_object, enclosing_func)
ast_node::for_loop(backing) return generate_for_loop(node, enclosing_object, enclosing_func)
ast_node::function(backing) return generate_function(node)
ast_node::function_call(backing) return generate_function_call(node, enclosing_object, enclosing_func, need_variable)
ast_node::function_call(backing) return generate_function_call(node, enclosing_object, enclosing_func)
ast_node::compiler_intrinsic(backing) return generate_compiler_intrinsic(node)
ast_node::code_block(backing) return generate_code_block(node, enclosing_object, enclosing_func)
ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func)

View File

@@ -11,76 +11,49 @@ import ast_nodes:*
import ast_transformation:*
import parser:*
obj importer (Object) {
var parsers: vector<parser>
var ast_pass: ast_transformation
var name_ast_map: map<string, pair<*tree<symbol>,*ast_node>>
var import_paths: vector<string>
fun construct(parsersIn: ref vector<parser>, ast_passIn: ref ast_transformation, import_paths_in: vector<string>): *importer {
parsers.copy_construct(&parsersIn)
ast_pass.copy_construct(&ast_passIn)
name_ast_map.construct()
import_paths.copy_construct(&import_paths_in)
return this
}
fun copy_construct(old: *importer) {
parsers.copy_construct(&old->parsers)
ast_pass.copy_construct(&old->ast_pass)
name_ast_map.copy_construct(&old->name_ast_map)
import_paths.copy_construct(&old->import_paths)
}
fun operator=(old: ref importer) {
destruct()
copy_construct(&old)
}
fun destruct() {
parsers.destruct()
ast_pass.destruct()
name_ast_map.destruct()
import_paths.destruct()
}
fun import(file_name: string) {
// lambda closes over our fix-up list
var imports_to_fix = vector<*ast_node>()
var import_first_pass = fun(file_name_idx: pair<string,int>) {
var file_name = file_name_idx.first
var file = string()
import_paths.for_each(fun(path: string) {
if (file_exists(path + file_name)) {
file = read_file(path + file_name)
} else {
}
})
printerr(file_name + ", ")
var parse_tree = parsers[file_name_idx.second].parse_input(file, file_name)
trim(parse_tree)
var ast_and_imports = ast_pass.first_pass(file_name, parse_tree, this)
imports_to_fix += ast_and_imports.second
name_ast_map[file_name] = make_pair(parse_tree, ast_and_imports.first)
}
printlnerr("**First Pass**")
printerr("parsing: ")
import_first_pass(make_pair(file_name,0))
for (var i = 0; i < imports_to_fix.size; i++;) {
var import_name = imports_to_fix[i]->import.name
var file_name = import_name + ".krak"
if (!name_ast_map.contains_key(file_name)) {
import_first_pass(make_pair(file_name,0))
fun import(file_name: string, parsers: ref vector<parser>, ast_pass: ref ast_transformation, import_paths: vector<string>): map<string, pair<*tree<symbol>,*ast_node>> {
var name_ast_map = map<string, pair<*tree<symbol>,*ast_node>>()
// lambda closes over our fix-up list
var imports_to_fix = vector<*ast_node>()
var import_first_pass = fun(file_name_idx: pair<string,int>) {
var file_name = file_name_idx.first
var file = string()
import_paths.for_each(fun(path: string) {
if (file_exists(path + file_name)) {
file = read_file(path + file_name)
} else {
}
var im = imports_to_fix[i]
var file_name = import_name + ".krak"
im->import.translation_unit = name_ast_map[file_name].second
add_to_scope(import_name, im->import.translation_unit, im->import.containing_translation_unit)
}
printlnerr()
printlnerr("**Second Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.second_pass(tree_pair.first, tree_pair.second);)
printlnerr("**Third Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.third_pass(tree_pair.first, tree_pair.second);)
// this needs to be modified to do chaotic iteration on instantiating template classes, based on what I see in the C++ version
printlnerr("**Fourth Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.fourth_pass(tree_pair.first, tree_pair.second);)
})
printerr(file_name + ", ")
var parse_tree = parsers[file_name_idx.second].parse_input(file, file_name)
trim(parse_tree)
var ast_and_imports = ast_pass.first_pass(file_name, parse_tree)
imports_to_fix += ast_and_imports.second
name_ast_map[file_name] = make_pair(parse_tree, ast_and_imports.first)
}
printlnerr("**First Pass**")
printerr("parsing: ")
import_first_pass(make_pair(file_name,0))
for (var i = 0; i < imports_to_fix.size; i++;) {
var import_name = imports_to_fix[i]->import.name
var file_name = import_name + ".krak"
if (!name_ast_map.contains_key(file_name)) {
import_first_pass(make_pair(file_name,0))
}
var im = imports_to_fix[i]
var file_name = import_name + ".krak"
im->import.translation_unit = name_ast_map[file_name].second
add_to_scope(import_name, im->import.translation_unit, im->import.containing_translation_unit)
}
printlnerr()
printlnerr("**Second Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.second_pass(tree_pair.first, tree_pair.second);)
printlnerr("**Third Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.third_pass(tree_pair.first, tree_pair.second);)
printlnerr("**Fourth Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.fourth_pass(tree_pair.first, tree_pair.second);)
return name_ast_map
}
fun trim(parse_tree: *tree<symbol>): *tree<symbol> {
@@ -134,17 +107,9 @@ fun remove_node(remove: symbol, parse_tree: *tree<symbol>) {
var node = to_process.pop()
for (var i = 0; i < node->children.size; i++;) {
if (!node->children[i] || node->children[i]->data.equal_wo_data(remove)) {
/*
if (!node->children[i])
println("not because null")
else {
print("not because "); println(remove.name)
}
*/
node->children.remove(i)
i--;
} else {
/*println(remove.to_string() + " not equal " + node->children[i]->data.to_string())*/
to_process.push(node->children[i])
}
}