Basic support for templates in ast, rest will come with types
This commit is contained in:
35
k.krak
35
k.krak
@@ -166,24 +166,34 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>): *tree<ast> {
|
||||
if (syntax->data.name == "import") {
|
||||
return _import(from_vector(syntax->children.slice(2,-1).filter(fun(s:*tree<symbol>):bool {
|
||||
return s->data.name == "identifier" || s->data.data == "*"
|
||||
}).map(fun(s: *tree<symbol>): str {
|
||||
return concat(s)
|
||||
})), vec(syntax_to_ast_helper(syntax->children[1])))
|
||||
}).map(concat)), vec(syntax_to_ast_helper(syntax->children[1])))
|
||||
} else if (syntax->data.name == "function")
|
||||
return _function(concat(get_node("func_identifier", syntax)), null<type>(),
|
||||
(get_nodes("typed_parameter", syntax) +
|
||||
get_nodes("statement", syntax)).map(syntax_to_ast_helper))
|
||||
else if (syntax->data.name == "typed_parameter")
|
||||
return _identifier(concat(get_node("identifier", syntax)), null<type>())
|
||||
else if (syntax->data.name == "type_def")
|
||||
return _type_def(concat(get_node("identifier", syntax)),
|
||||
else if (syntax->data.name == "type_def") {
|
||||
var n = _type_def(concat(get_node("identifier", syntax)),
|
||||
get_nodes("declaration_statement", syntax).map(syntax_to_ast_helper))
|
||||
else if (syntax->data.name == "adt_def")
|
||||
return _type_def(concat(get_node("identifier", syntax)),
|
||||
var template = get_node("template_dec", 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> {
|
||||
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])
|
||||
else if (syntax->data.name == "code_block")
|
||||
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[2])))
|
||||
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])
|
||||
}))
|
||||
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) {
|
||||
return syntax_to_ast_helper(syntax->children[0])
|
||||
} 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>>()),
|
||||
syntax_to_ast_helper(syntax->children[1])))
|
||||
} else {
|
||||
|
||||
@@ -91,7 +91,7 @@ traits = "\(" WS trait_list WS "\)" ;
|
||||
trait_list = trait_list WS "," WS scoped_identifier | scoped_identifier ;
|
||||
|
||||
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 = identifier | identifier WS dec_type ;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ adt ast {
|
||||
_translation_unit: str,
|
||||
_import: set<str>,
|
||||
_identifier: pair<str, *type>,
|
||||
_binding: pair<str, *tree<ast>>,
|
||||
_binding: triple<str, vec<*type>, *tree<ast>>,
|
||||
_type_def: str,
|
||||
_adt_def: str,
|
||||
_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::_adt_def(b) return str("_adt_def(") + b + ")"
|
||||
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::_assignment() return str("_assignment")
|
||||
ast::_block() return str("_block")
|
||||
@@ -78,8 +78,11 @@ fun _cast(p: *type): *tree<ast> {
|
||||
fun _identifier(p1: str, p2: *type): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_identifier(make_pair(p1, p2)))
|
||||
}
|
||||
fun _binding(p1: str, p2: *tree<ast>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_binding(make_pair(p1, p2)))
|
||||
fun _binding(p1: str, p3: *tree<ast>): *tree<ast> {
|
||||
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> {
|
||||
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> {
|
||||
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> {
|
||||
return new<tree<ast>>()->construct(ast::_binding(make_pair(p1, p2)), c)
|
||||
fun _binding(p1: str, p3: *tree<ast>, c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
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> {
|
||||
return new<tree<ast>>()->construct(ast::_function(make_pair(p1, p2)), c)
|
||||
|
||||
@@ -70,13 +70,13 @@ fun make_pair<T,U>(first: T, second: U): pair<T,U> {
|
||||
}
|
||||
|
||||
// little ugly, but it works
|
||||
fun unpack<T,U>(first: ref T, second: ref U): unpack_dummy<T,U> {
|
||||
var toRet: unpack_dummy<T,U>
|
||||
fun unpack<T,U>(first: ref T, second: ref U): unpack_dummy_pair<T,U> {
|
||||
var toRet: unpack_dummy_pair<T,U>
|
||||
toRet.first = &first
|
||||
toRet.second = &second
|
||||
return toRet
|
||||
}
|
||||
obj unpack_dummy<T,U> {
|
||||
obj unpack_dummy_pair<T,U> {
|
||||
var first: *T
|
||||
var second: *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 {
|
||||
var toRet.construct(0, end, 1): range
|
||||
return toRet
|
||||
|
||||
@@ -289,12 +289,24 @@ obj vec<T> (Object, Serializable) {
|
||||
newVec.addEnd(func(data[i]))
|
||||
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> {
|
||||
var newVec.construct(size): vec<U>
|
||||
for (var i = 0; i < size; i++;)
|
||||
newVec.addEnd(func(data[i]))
|
||||
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> {
|
||||
var newVec.construct(size): vec<U>
|
||||
for (var i = 0; i < size; i++;) {
|
||||
|
||||
Reference in New Issue
Block a user