Added in basic transformation and generation for functions

This commit is contained in:
Nathan Braswell
2016-01-06 02:46:42 -05:00
parent f29fdcd463
commit 337bc424ee
7 changed files with 180 additions and 34 deletions

View File

@@ -7,6 +7,7 @@ import util:*
import string:*
import mem:*
import io:*
import type:*
adt ast_node {
@@ -127,11 +128,11 @@ obj import (Object) {
return imported == other.imported && name == other.name
}
}
fun ast_identifier_ptr(name: *char): *ast_node {
return ast_identifier_ptr(string(name))
fun ast_identifier_ptr(name: *char, type: *type): *ast_node {
return ast_identifier_ptr(string(name), type)
}
fun ast_identifier_ptr(name: string): *ast_node {
var to_ret.construct(name): identifier
fun ast_identifier_ptr(name: string, type: *type): *ast_node {
var to_ret.construct(name, type): identifier
var ptr = new<ast_node>()
ptr->copy_construct(&ast_node::identifier(to_ret))
return ptr
@@ -145,14 +146,17 @@ fun is_identifier(node: *ast_node): bool {
obj identifier (Object) {
var name: string
var scope: map<string, vector<*ast_node>>
fun construct(nameIn: string): *identifier {
name.copy_construct(&nameIn)
var type: *type
fun construct(name_in: string, type_in: *type): *identifier {
name.copy_construct(&name_in)
scope.construct()
type = type_in
return this
}
fun copy_construct(old: *identifier) {
name.copy_construct(&old->name)
scope.copy_construct(&old->scope)
type = old->type
}
fun destruct() {
name.destruct()
@@ -163,7 +167,7 @@ obj identifier (Object) {
copy_construct(&other)
}
fun operator==(other: ref identifier): bool {
return name == other.name
return name == other.name && type == other.type
}
}
fun ast_type_def_ptr(name: string): *ast_node {
@@ -238,8 +242,8 @@ obj adt_def (Object) {
return name == other.name
}
}
fun ast_function_ptr(): *ast_node {
var to_ret.construct(): function
fun ast_function_ptr(name: string, type: *type, parameters: vector<*ast_node>): *ast_node {
var to_ret.construct(name, type, parameters): function
var ptr = new<ast_node>()
ptr->copy_construct(&ast_node::function(to_ret))
return ptr
@@ -251,15 +255,26 @@ fun is_function(node: *ast_node): bool {
return false
}
obj function (Object) {
var name: string
var type: *type
var parameters: vector<*ast_node>
var scope: map<string, vector<*ast_node>>
fun construct(): *function {
fun construct(name_in: string, type_in: *type, parameters_in: vector<*ast_node>): *function {
name.copy_construct(&name_in)
parameters.copy_construct(&parameters_in)
scope.construct()
type = type_in
return this
}
fun copy_construct(old: *function) {
name.copy_construct(&old->name)
type = old->type
parameters.copy_construct(&old->parameters)
scope.copy_construct(&old->scope)
}
fun destruct() {
name.destruct()
parameters.destruct()
scope.destruct()
}
fun operator=(other: ref function) {
@@ -267,7 +282,7 @@ obj function (Object) {
copy_construct(&other)
}
fun operator==(other: ref function): bool {
return true
return name == name && type == other.type && parameters == other.parameters
}
}
fun ast_code_block_ptr(): *ast_node {
@@ -858,10 +873,10 @@ fun get_ast_name(node: *ast_node): string {
match (*node) {
ast_node::translation_unit(backing) return string("translation_unit: ") + backing.name
ast_node::import(backing) return string("import: ") + backing.name + "; [" + backing.imported.reduce(fun(name: string, acc: string): string return acc + " " + name;, string()) + " ]"
ast_node::identifier(backing) return string("identifier: ") + backing.name
ast_node::identifier(backing) return string("identifier: ") + backing.name + ": " + backing.type->to_string()
ast_node::type_def(backing) return string("type_def: ") + backing.name
ast_node::adt_def(backing) return string("adt_def: ") + backing.name
ast_node::function(backing) return string("function")
ast_node::function(backing) return string("function: ") + backing.name + ": " + backing.type->to_string()
ast_node::code_block(backing) return string("code_block")
ast_node::statement(backing) return string("statement")
ast_node::if_statement(backing) return string("if_statement")

View File

@@ -86,8 +86,28 @@ obj ast_transformation (Object) {
}
})
}
fun second_pass_function(parse_tree: *tree<symbol>, translation_unit: *ast_node, template_replacements: map<string, *type>): *ast_node {
return ast_function_ptr()
fun second_pass_function(node: *tree<symbol>, translation_unit: *ast_node, template_replacements: map<string, *type>): *ast_node {
var function_name = concat_symbol_tree(get_node("func_identifier", node))
// check to see if it is a template
// figure out return type
var typed_return_node = get_node("typed_return", node)
// darn no ternary yet
var return_type = null<type>()
if (typed_return_node) return_type = transform_type(get_node("type", typed_return_node), translation_unit, template_replacements)
else return_type = type_ptr(base_type::void_return())
// transform parameters
var parameters = vector<*ast_node>()
get_nodes("typed_parameter", node).for_each(fun(child: *tree<symbol>) {
parameters.add(ast_identifier_ptr(concat_symbol_tree(get_node("identifier", child)), transform_type(get_node("type", child), translation_unit, template_replacements)))
})
// figure out function type and make function_node
var function_node = ast_function_ptr(function_name, type_ptr(parameters.map(fun(parameter: *ast_node): *type return parameter->identifier.type;), return_type), parameters)
// add to scope (translation_unit)
add_to_scope(function_name, function_node, translation_unit)
add_to_scope("~enclosing_scope", translation_unit, function_node)
// add parameters to scope of function
parameters.for_each(fun(parameter: *ast_node) add_to_scope(parameter->identifier.name, parameter, function_node);)
return function_node
}
fun third_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
println(string("Third Pass for ") + translation_unit->translation_unit.name)
@@ -95,6 +115,32 @@ obj ast_transformation (Object) {
fun fourth_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
println(string("Fourth Pass for ") + translation_unit->translation_unit.name)
}
fun transform_type(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *type {
// check for references and step down
// always get to pre-reffed level
var real_node = get_node("pre_reffed", node)
// check for indirection and step down
var type_syntax_str = concat_symbol_tree(real_node)
// should take into account indirection and references...
if (type_syntax_str == "void")
return type_ptr(base_type::void_return())
else if (type_syntax_str == "bool")
return type_ptr(base_type::boolean())
else if (type_syntax_str == "int")
return type_ptr(base_type::integer())
else if (type_syntax_str == "float")
return type_ptr(base_type::floating())
else if (type_syntax_str == "double")
return type_ptr(base_type::double_precision())
else if (type_syntax_str == "char")
return type_ptr(base_type::character())
else if (/* check for function type*/ true)
return type_ptr(base_type::function())
else {
// do lookup for objects, ADTs, templates, etc
return type_ptr(base_type::none())
}
}
/*NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, bool limitToFunction, std::map<std::string, Type*> templateTypeReplacements) {*/
fun transform(node: *tree<symbol>, scope: *ast_node): *ast_node {
var name = node->data.name
@@ -117,8 +163,9 @@ obj ast_transformation (Object) {
}
fun transform_identifier(node: *tree<symbol>, scope: *ast_node): *ast_node {
// for identifier we have to do scope lookup, etc, and maybe limit to function
// NOT THIS
var name = concat_symbol_tree(node)
return ast_identifier_ptr(name)
return ast_identifier_ptr(name, type_ptr(base_type::void_return()))
}
fun transform_code_block(node: *tree<symbol>, scope: *ast_node): *ast_node {
var new_block = ast_code_block_ptr()

View File

@@ -29,8 +29,9 @@ obj c_generator (Object) {
var structs: string = ""
var function_typedef_string_pre: string = ""
var function_typedef_string: string = ""
var function_prototypes: string = ""
var variable_declarations: string = ""
var function_prototypes: string = "\n/**Function Prototypes**/\n"
var function_definitions: string = "\n/**Function Definitions**/\n"
var variable_declarations: string = "\n/**Variable Declarations**/\n"
// poset generation into structs string
@@ -46,12 +47,30 @@ obj c_generator (Object) {
top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child)
}
ast_node::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child)
ast_node::function(backing) {
// make sure not a template
// or a passthrough
// check for and add to parameters if a closure
var parameter_types = string()
var parameters = string()
// also add in name decoration
backing.parameters.for_each(fun(parameter: *ast_node) {
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
parameter_types += type_to_c(parameter->identifier.type)
parameters += type_to_c(parameter->identifier.type) + " " + parameter->identifier.name
})
function_prototypes += type_to_c(backing.type->return_type) + " " + backing.name + "(" + parameter_types + ");\n"
// add parameters to destructor thingy (for returns)? Or should that be a different pass?
function_definitions += type_to_c(backing.type->return_type) + " " + backing.name + "(" + parameters + ") { " + " /* body here */ "
// emit parameter destructors?
function_definitions += "}\n"
}
}
})
})
var function_definitions: string = ""
return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string_pre+function_typedef_string+function_prototypes+variable_declarations+function_definitions, linker_string)
return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string_pre+function_typedef_string+function_prototypes+variable_declarations+function_definitions + "\n", linker_string)
}
fun generate_simple_passthrough(node: *ast_node): string {
// deal with all the passthrough params
@@ -63,6 +82,25 @@ obj c_generator (Object) {
ast_node::simple_passthrough(backing) return generate_simple_passthrough(node)
}
}
fun type_to_c(type: *type): string {
match (type->base) {
base_type::none() return string("none")
base_type::template() return string("template")
base_type::template_type() return string("template_type")
base_type::void_return() return string("void")
base_type::boolean() return string("bool")
base_type::character() return string("char")
base_type::integer() return string("int")
base_type::floating() return string("float")
base_type::double_precision() return string("double")
base_type::function() {
var temp = string("function: (")
type->parameter_types.for_each(fun(parameter_type: *type) temp += parameter_type->to_string() + " ";)
return temp + ")" + type->return_type->to_string()
}
}
return string("impossible type")
}
}

View File

@@ -1,7 +1,9 @@
import mem:*
import string:*
import vector:*
// hmm, like the ast_node, this is another candadate for being fully an ADT
// one issue is that there are properties shared between most of the options (indirection, say)
adt base_type {
none,
template,
@@ -15,27 +17,40 @@ adt base_type {
function
}
fun type(): type {
var to_ret.construct(): type
return to_ret
fun type_ptr(): *type {
return new<type>()->construct()
}
fun type(base: base_type): type {
var to_ret.construct(base): type
return to_ret
fun type_ptr(base: base_type): *type {
return new<type>()->construct(base)
}
fun type_ptr(parameters: vector<*type>, return_type: *type): *type {
return new<type>()->construct(parameters, return_type)
}
obj type (Object) {
var base: base_type
var parameter_types: vector<*type>
var return_type: *type
fun construct(): *type {
base.copy_construct(&base_type::none())
parameter_types.construct()
return this
}
fun construct(base_in: base_type): *type {
base.copy_construct(&base_in)
parameter_types.construct()
return this
}
fun construct(parameter_types_in: vector<*type>, return_type_in: *type): *type {
base.copy_construct(&base_type::function())
parameter_types.copy_construct(&parameter_types)
return_type = return_type_in
return this
}
fun copy_construct(old: *type) {
base = old->base
base.copy_construct(&old->base)
parameter_types.copy_construct(&old->parameter_types)
return_type = old->return_type
}
fun operator=(other: ref type) {
destruct()
@@ -43,6 +58,26 @@ obj type (Object) {
}
fun destruct() {
base.destruct()
parameter_types.destruct()
}
fun to_string(): string {
match (base) {
base_type::none() return string("none")
base_type::template() return string("template")
base_type::template_type() return string("template_type")
base_type::void_return() return string("void_return")
base_type::boolean() return string("boolean")
base_type::character() return string("character")
base_type::integer() return string("integer")
base_type::floating() return string("floating")
base_type::double_precision() return string("double_precision")
base_type::function() {
var temp = string("function: (")
parameter_types.for_each(fun(parameter_type: *type) temp += parameter_type->to_string() + " ";)
return temp + ")" + return_type->to_string()
}
}
return string("impossible type")
}
}