Basic support for templates in ast, rest will come with types

This commit is contained in:
Nathan Braswell
2018-06-22 09:02:30 -04:00
parent a8d4b4eb7f
commit 6ffe7aee46
5 changed files with 130 additions and 20 deletions

35
k.krak
View File

@@ -166,24 +166,34 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>): *tree<ast> {
if (syntax->data.name == "import") { if (syntax->data.name == "import") {
return _import(from_vector(syntax->children.slice(2,-1).filter(fun(s:*tree<symbol>):bool { return _import(from_vector(syntax->children.slice(2,-1).filter(fun(s:*tree<symbol>):bool {
return s->data.name == "identifier" || s->data.data == "*" return s->data.name == "identifier" || s->data.data == "*"
}).map(fun(s: *tree<symbol>): str { }).map(concat)), vec(syntax_to_ast_helper(syntax->children[1])))
return concat(s)
})), vec(syntax_to_ast_helper(syntax->children[1])))
} else if (syntax->data.name == "function") } else if (syntax->data.name == "function")
return _function(concat(get_node("func_identifier", syntax)), null<type>(), return _function(concat(get_node("func_identifier", syntax)), null<type>(),
(get_nodes("typed_parameter", syntax) + (get_nodes("typed_parameter", syntax) +
get_nodes("statement", syntax)).map(syntax_to_ast_helper)) get_nodes("statement", syntax)).map(syntax_to_ast_helper))
else if (syntax->data.name == "typed_parameter") else if (syntax->data.name == "typed_parameter")
return _identifier(concat(get_node("identifier", syntax)), null<type>()) return _identifier(concat(get_node("identifier", syntax)), null<type>())
else if (syntax->data.name == "type_def") else if (syntax->data.name == "type_def") {
return _type_def(concat(get_node("identifier", syntax)), var n = _type_def(concat(get_node("identifier", syntax)),
get_nodes("declaration_statement", syntax).map(syntax_to_ast_helper)) get_nodes("declaration_statement", syntax).map(syntax_to_ast_helper))
else if (syntax->data.name == "adt_def") var template = get_node("template_dec", syntax)
return _type_def(concat(get_node("identifier", syntax)), if (template == null<tree<symbol>>()) {
return n
} else {
return _template(n->data._type_def, from_vector(get_nodes("template_param", template).map(concat)), vec(n))
}
} else if (syntax->data.name == "adt_def") {
var n = _adt_def(concat(get_node("identifier", syntax)),
get_nodes("adt_option", syntax).map(fun(s: *tree<symbol>): *tree<ast> { get_nodes("adt_option", syntax).map(fun(s: *tree<symbol>): *tree<ast> {
return _identifier(concat(get_node("identifier", s)), null<type>()) return _identifier(concat(get_node("identifier", s)), null<type>())
})) }))
else if (syntax->data.name == "statement") var template = get_node("template_dec", syntax)
if (template == null<tree<symbol>>()) {
return n
} else {
return _template(n->data._adt_def, from_vector(get_nodes("template_param", template).map(concat)), vec(n))
}
} else if (syntax->data.name == "statement")
return syntax_to_ast_helper(syntax->children[0]) return syntax_to_ast_helper(syntax->children[0])
else if (syntax->data.name == "code_block") else if (syntax->data.name == "code_block")
return _block(syntax->children.map(syntax_to_ast_helper)) return _block(syntax->children.map(syntax_to_ast_helper))
@@ -205,7 +215,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>): *tree<ast> {
syntax_to_ast_helper(syntax->children[0]), syntax_to_ast_helper(syntax->children[0]),
syntax_to_ast_helper(syntax->children[2]))) syntax_to_ast_helper(syntax->children[2])))
else if (syntax->data.name == "function_call") else if (syntax->data.name == "function_call")
return _call(syntax->children.map(fun(s: *tree<symbol>): *tree<ast> { return _call(vec(syntax_to_ast_helper(syntax->children[0])) + get_nodes("parameter", syntax).map(fun(s: *tree<symbol>): *tree<ast> {
return syntax_to_ast_helper(s->children[0]) return syntax_to_ast_helper(s->children[0])
})) }))
else if (syntax->data.name == "boolean_expression" || else if (syntax->data.name == "boolean_expression" ||
@@ -223,7 +233,12 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>): *tree<ast> {
if (syntax->children.size == 1) { if (syntax->children.size == 1) {
return syntax_to_ast_helper(syntax->children[0]) return syntax_to_ast_helper(syntax->children[0])
} else if (syntax->children.size == 2) { } else if (syntax->children.size == 2) {
if (syntax->children[0]->data.terminal) { var template_inst = get_node("template_inst", syntax)
if (template_inst != null<tree<symbol>>()) {
if (syntax->children[0]->data.name != "scoped_identifier")
error(syntax, "Unexpected template instantiation (not on an identifier)")
return _binding(concat(syntax->children[0]) + "<somin>", vec<*type>(), null<tree<ast>>())
} else if (syntax->children[0]->data.terminal) {
return _call(vec(_binding(concat(syntax->children[0]), null<tree<ast>>()), return _call(vec(_binding(concat(syntax->children[0]), null<tree<ast>>()),
syntax_to_ast_helper(syntax->children[1]))) syntax_to_ast_helper(syntax->children[1])))
} else { } else {

View File

@@ -91,7 +91,7 @@ traits = "\(" WS trait_list WS "\)" ;
trait_list = trait_list WS "," WS scoped_identifier | scoped_identifier ; trait_list = trait_list WS "," WS scoped_identifier | scoped_identifier ;
adt_nonterm = "adt" ; adt_nonterm = "adt" ;
adt_def = adt_nonterm WS identifier WS "{" WS adt_option_list WS "}" ; adt_def = adt_nonterm WS identifier WS "{" WS adt_option_list WS "}" | adt_nonterm WS identifier WS template_dec WS "{" WS adt_option_list WS "}" ;
adt_option_list = adt_option | adt_option WS "," WS adt_option_list ; adt_option_list = adt_option | adt_option WS "," WS adt_option_list ;
adt_option = identifier | identifier WS dec_type ; adt_option = identifier | identifier WS dec_type ;

View File

@@ -10,7 +10,7 @@ adt ast {
_translation_unit: str, _translation_unit: str,
_import: set<str>, _import: set<str>,
_identifier: pair<str, *type>, _identifier: pair<str, *type>,
_binding: pair<str, *tree<ast>>, _binding: triple<str, vec<*type>, *tree<ast>>,
_type_def: str, _type_def: str,
_adt_def: str, _adt_def: str,
_function: pair<str, *type>, _function: pair<str, *type>,
@@ -41,7 +41,7 @@ fun to_string(a: ref ast): str {
ast::_type_def(b) return str("_type_def(") + b + ")" ast::_type_def(b) return str("_type_def(") + b + ")"
ast::_adt_def(b) return str("_adt_def(") + b + ")" ast::_adt_def(b) return str("_adt_def(") + b + ")"
ast::_function(b) return str("_function(") + b.first + ")" ast::_function(b) return str("_function(") + b.first + ")"
ast::_template(b) return str("_template(") + b.first + ")" ast::_template(b) return str("_template(") + b.first + "[" + str(",").join(b.second.data) + "])"
ast::_declaration() return str("_declaration") ast::_declaration() return str("_declaration")
ast::_assignment() return str("_assignment") ast::_assignment() return str("_assignment")
ast::_block() return str("_block") ast::_block() return str("_block")
@@ -78,8 +78,11 @@ fun _cast(p: *type): *tree<ast> {
fun _identifier(p1: str, p2: *type): *tree<ast> { fun _identifier(p1: str, p2: *type): *tree<ast> {
return new<tree<ast>>()->construct(ast::_identifier(make_pair(p1, p2))) return new<tree<ast>>()->construct(ast::_identifier(make_pair(p1, p2)))
} }
fun _binding(p1: str, p2: *tree<ast>): *tree<ast> { fun _binding(p1: str, p3: *tree<ast>): *tree<ast> {
return new<tree<ast>>()->construct(ast::_binding(make_pair(p1, p2))) return new<tree<ast>>()->construct(ast::_binding(make_triple(p1, vec<*type>(), p3)))
}
fun _binding(p1: str, p2: vec<*type>, p3: *tree<ast>): *tree<ast> {
return new<tree<ast>>()->construct(ast::_binding(make_triple(p1, p2, p3)))
} }
fun _function(p1: str, p2: *type): *tree<ast> { fun _function(p1: str, p2: *type): *tree<ast> {
return new<tree<ast>>()->construct(ast::_function(make_pair(p1, p2))) return new<tree<ast>>()->construct(ast::_function(make_pair(p1, p2)))
@@ -153,8 +156,11 @@ fun _cast(p: *type, c: ref vec<*tree<ast>>): *tree<ast> {
fun _identifier(p1: str, p2: *type, c: ref vec<*tree<ast>>): *tree<ast> { fun _identifier(p1: str, p2: *type, c: ref vec<*tree<ast>>): *tree<ast> {
return new<tree<ast>>()->construct(ast::_identifier(make_pair(p1, p2)), c) return new<tree<ast>>()->construct(ast::_identifier(make_pair(p1, p2)), c)
} }
fun _binding(p1: str, p2: *tree<ast>, c: ref vec<*tree<ast>>): *tree<ast> { fun _binding(p1: str, p3: *tree<ast>, c: ref vec<*tree<ast>>): *tree<ast> {
return new<tree<ast>>()->construct(ast::_binding(make_pair(p1, p2)), c) return new<tree<ast>>()->construct(ast::_binding(make_triple(p1, vec<*type>(), p3)), c)
}
fun _binding(p1: str, p2: vec<*type>, p3: *tree<ast>, c: ref vec<*tree<ast>>): *tree<ast> {
return new<tree<ast>>()->construct(ast::_binding(make_triple(p1, p2, p3)), c)
} }
fun _function(p1: str, p2: *type, c: ref vec<*tree<ast>>): *tree<ast> { fun _function(p1: str, p2: *type, c: ref vec<*tree<ast>>): *tree<ast> {
return new<tree<ast>>()->construct(ast::_function(make_pair(p1, p2)), c) return new<tree<ast>>()->construct(ast::_function(make_pair(p1, p2)), c)

View File

@@ -70,13 +70,13 @@ fun make_pair<T,U>(first: T, second: U): pair<T,U> {
} }
// little ugly, but it works // little ugly, but it works
fun unpack<T,U>(first: ref T, second: ref U): unpack_dummy<T,U> { fun unpack<T,U>(first: ref T, second: ref U): unpack_dummy_pair<T,U> {
var toRet: unpack_dummy<T,U> var toRet: unpack_dummy_pair<T,U>
toRet.first = &first toRet.first = &first
toRet.second = &second toRet.second = &second
return toRet return toRet
} }
obj unpack_dummy<T,U> { obj unpack_dummy_pair<T,U> {
var first: *T var first: *T
var second: *U var second: *U
fun operator=(p: ref pair<T,U>) { fun operator=(p: ref pair<T,U>) {
@@ -131,6 +131,83 @@ obj pair<T,U> (Object, Serializable, Hashable) {
} }
} }
fun make_triple<T,U,V>(first: T, second: U, third: V): triple<T,U,V> {
var it.construct(first, second, third): triple<T,U,V>
return it
}
// little ugly, but it works
fun unpack<T,U,V>(first: ref T, second: ref U, third: ref V): unpack_dummy_triple<T,U,V> {
var toRet: unpack_dummy_triple<T,U>
toRet.first = &first
toRet.second = &second
toRet.third = &third
return toRet
}
obj unpack_dummy_triple<T,U,V> {
var first: *T
var second: *U
var third: *V
fun operator=(p: ref triple<T,U,V>) {
*first = p.first
*second = p.second
*third = p.third
}
}
obj triple<T,U,V> (Object, Serializable, Hashable) {
var first: T
var second: U
var third: V
fun construct(firstIn: ref T, secondIn: ref U, thirdIn: ref V): *triple<T,U,V> {
mem::maybe_copy_construct(&first, &firstIn)
mem::maybe_copy_construct(&second, &secondIn)
mem::maybe_copy_construct(&third, &thirdIn)
return this
}
fun construct(): *triple<T,U,V> {
mem::maybe_construct(&first)
mem::maybe_construct(&second)
mem::maybe_construct(&third)
return this
}
fun copy_construct(old: *triple<T,U,V>):void {
mem::maybe_copy_construct(&first, &old->first)
mem::maybe_copy_construct(&second, &old->second)
mem::maybe_copy_construct(&third, &old->third)
}
fun destruct():void {
mem::maybe_destruct(&first)
mem::maybe_destruct(&second)
mem::maybe_destruct(&third)
}
fun serialize(): vec::vec<char> {
return serialize::serialize(first) + serialize::serialize(second) + serialize::serialize(third)
}
fun unserialize(it: ref vec::vec<char>, pos: int): int {
// can't use unpack :( (b/c we can't make an already constructed empty one)
var first_pair = serialize::unserialize<T>(it, pos)
var second_pair = serialize::unserialize<U>(it, first_pair.second)
var third_pair = serialize::unserialize<V>(it, second_pair.second)
mem::maybe_copy_construct(&first, &first_pair.first)
mem::maybe_copy_construct(&second, &second_pair.first)
mem::maybe_copy_construct(&third, &third_pair.first)
return third_pair.second
}
fun hash():ulong return hash(first) ^ hash(second) ^ hash(third)
// the old unnecessary template to prevent generation
// if not used trick (in this case, changing out V with X)
fun operator==<X>(other: ref triple<T,U,X>): bool {
return first == other.first && second == other.second && third == other.third
}
}
fun range(end:int): range { fun range(end:int): range {
var toRet.construct(0, end, 1): range var toRet.construct(0, end, 1): range
return toRet return toRet

View File

@@ -289,12 +289,24 @@ obj vec<T> (Object, Serializable) {
newVec.addEnd(func(data[i])) newVec.addEnd(func(data[i]))
return newVec return newVec
} }
fun map<U>(func: run(ref T):U):vec<U> {
var newVec.construct(size): vec<U>
for (var i = 0; i < size; i++;)
newVec.addEnd(func(data[i]))
return newVec
}
fun map<U>(func: fun(T):U):vec<U> { fun map<U>(func: fun(T):U):vec<U> {
var newVec.construct(size): vec<U> var newVec.construct(size): vec<U>
for (var i = 0; i < size; i++;) for (var i = 0; i < size; i++;)
newVec.addEnd(func(data[i])) newVec.addEnd(func(data[i]))
return newVec return newVec
} }
fun map<U>(func: run(T):U):vec<U> {
var newVec.construct(size): vec<U>
for (var i = 0; i < size; i++;)
newVec.addEnd(func(data[i]))
return newVec
}
fun flatten_map<U>(func: fun(T):vec<U>):vec<U> { fun flatten_map<U>(func: fun(T):vec<U>):vec<U> {
var newVec.construct(size): vec<U> var newVec.construct(size): vec<U>
for (var i = 0; i < size; i++;) { for (var i = 0; i < size; i++;) {