From 6ffe7aee468e3a5aad6f387e543aa5bb1846c25d Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Fri, 22 Jun 2018 09:02:30 -0400 Subject: [PATCH] Basic support for templates in ast, rest will come with types --- k.krak | 35 ++++++++++++++------ krakenGrammer.kgm | 2 +- stdlib/ast.krak | 18 ++++++---- stdlib/util.krak | 83 +++++++++++++++++++++++++++++++++++++++++++++-- stdlib/vec.krak | 12 +++++++ 5 files changed, 130 insertions(+), 20 deletions(-) diff --git a/k.krak b/k.krak index 10140a5..6255e7d 100644 --- a/k.krak +++ b/k.krak @@ -166,24 +166,34 @@ fun syntax_to_ast(file_name: str, syntax: *tree): *tree { if (syntax->data.name == "import") { return _import(from_vector(syntax->children.slice(2,-1).filter(fun(s:*tree):bool { return s->data.name == "identifier" || s->data.data == "*" - }).map(fun(s: *tree): 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(), (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()) - 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>()) { + 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): *tree { return _identifier(concat(get_node("identifier", s)), null()) })) - else if (syntax->data.name == "statement") + var template = get_node("template_dec", syntax) + if (template == null>()) { + 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): *tree { 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): *tree { + return _call(vec(syntax_to_ast_helper(syntax->children[0])) + get_nodes("parameter", syntax).map(fun(s: *tree): *tree { 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): *tree { 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>()) { + if (syntax->children[0]->data.name != "scoped_identifier") + error(syntax, "Unexpected template instantiation (not on an identifier)") + return _binding(concat(syntax->children[0]) + "", vec<*type>(), null>()) + } else if (syntax->children[0]->data.terminal) { return _call(vec(_binding(concat(syntax->children[0]), null>()), syntax_to_ast_helper(syntax->children[1]))) } else { diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index d7f26b1..c534855 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -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 ; diff --git a/stdlib/ast.krak b/stdlib/ast.krak index 74c9de5..ab89db6 100644 --- a/stdlib/ast.krak +++ b/stdlib/ast.krak @@ -10,7 +10,7 @@ adt ast { _translation_unit: str, _import: set, _identifier: pair, - _binding: pair>, + _binding: triple, *tree>, _type_def: str, _adt_def: str, _function: pair, @@ -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 { fun _identifier(p1: str, p2: *type): *tree { return new>()->construct(ast::_identifier(make_pair(p1, p2))) } -fun _binding(p1: str, p2: *tree): *tree { - return new>()->construct(ast::_binding(make_pair(p1, p2))) +fun _binding(p1: str, p3: *tree): *tree { + return new>()->construct(ast::_binding(make_triple(p1, vec<*type>(), p3))) +} +fun _binding(p1: str, p2: vec<*type>, p3: *tree): *tree { + return new>()->construct(ast::_binding(make_triple(p1, p2, p3))) } fun _function(p1: str, p2: *type): *tree { return new>()->construct(ast::_function(make_pair(p1, p2))) @@ -153,8 +156,11 @@ fun _cast(p: *type, c: ref vec<*tree>): *tree { fun _identifier(p1: str, p2: *type, c: ref vec<*tree>): *tree { return new>()->construct(ast::_identifier(make_pair(p1, p2)), c) } -fun _binding(p1: str, p2: *tree, c: ref vec<*tree>): *tree { - return new>()->construct(ast::_binding(make_pair(p1, p2)), c) +fun _binding(p1: str, p3: *tree, c: ref vec<*tree>): *tree { + return new>()->construct(ast::_binding(make_triple(p1, vec<*type>(), p3)), c) +} +fun _binding(p1: str, p2: vec<*type>, p3: *tree, c: ref vec<*tree>): *tree { + return new>()->construct(ast::_binding(make_triple(p1, p2, p3)), c) } fun _function(p1: str, p2: *type, c: ref vec<*tree>): *tree { return new>()->construct(ast::_function(make_pair(p1, p2)), c) diff --git a/stdlib/util.krak b/stdlib/util.krak index ecea4a3..2933f97 100644 --- a/stdlib/util.krak +++ b/stdlib/util.krak @@ -70,13 +70,13 @@ fun make_pair(first: T, second: U): pair { } // little ugly, but it works -fun unpack(first: ref T, second: ref U): unpack_dummy { - var toRet: unpack_dummy +fun unpack(first: ref T, second: ref U): unpack_dummy_pair { + var toRet: unpack_dummy_pair toRet.first = &first toRet.second = &second return toRet } -obj unpack_dummy { +obj unpack_dummy_pair { var first: *T var second: *U fun operator=(p: ref pair) { @@ -131,6 +131,83 @@ obj pair (Object, Serializable, Hashable) { } } +fun make_triple(first: T, second: U, third: V): triple { + var it.construct(first, second, third): triple + return it +} + +// little ugly, but it works +fun unpack(first: ref T, second: ref U, third: ref V): unpack_dummy_triple { + var toRet: unpack_dummy_triple + toRet.first = &first + toRet.second = &second + toRet.third = &third + return toRet +} +obj unpack_dummy_triple { + var first: *T + var second: *U + var third: *V + fun operator=(p: ref triple) { + *first = p.first + *second = p.second + *third = p.third + } +} + +obj triple (Object, Serializable, Hashable) { + var first: T + var second: U + var third: V + + fun construct(firstIn: ref T, secondIn: ref U, thirdIn: ref V): *triple { + mem::maybe_copy_construct(&first, &firstIn) + mem::maybe_copy_construct(&second, &secondIn) + mem::maybe_copy_construct(&third, &thirdIn) + return this + } + + fun construct(): *triple { + mem::maybe_construct(&first) + mem::maybe_construct(&second) + mem::maybe_construct(&third) + return this + } + + fun copy_construct(old: *triple):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 { + return serialize::serialize(first) + serialize::serialize(second) + serialize::serialize(third) + } + fun unserialize(it: ref vec::vec, pos: int): int { + // can't use unpack :( (b/c we can't make an already constructed empty one) + var first_pair = serialize::unserialize(it, pos) + var second_pair = serialize::unserialize(it, first_pair.second) + var third_pair = serialize::unserialize(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==(other: ref triple): 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 diff --git a/stdlib/vec.krak b/stdlib/vec.krak index 16daf7e..ae7db3a 100644 --- a/stdlib/vec.krak +++ b/stdlib/vec.krak @@ -289,12 +289,24 @@ obj vec (Object, Serializable) { newVec.addEnd(func(data[i])) return newVec } + fun map(func: run(ref T):U):vec { + var newVec.construct(size): vec + for (var i = 0; i < size; i++;) + newVec.addEnd(func(data[i])) + return newVec + } fun map(func: fun(T):U):vec { var newVec.construct(size): vec for (var i = 0; i < size; i++;) newVec.addEnd(func(data[i])) return newVec } + fun map(func: run(T):U):vec { + var newVec.construct(size): vec + for (var i = 0; i < size; i++;) + newVec.addEnd(func(data[i])) + return newVec + } fun flatten_map(func: fun(T):vec):vec { var newVec.construct(size): vec for (var i = 0; i < size; i++;) {