More clean up; need to add return type checking pass so that can clean up c_generator more.
This commit is contained in:
@@ -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") {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user