Added in basic transformation and generation for functions
This commit is contained in:
@@ -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(¶meters_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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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(¶meter_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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user