hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 1e3eccc3ec9aabd16f29bdb148bef3b6eae4c559
parent 93b292a28e6e17912eadc093661e0692fbfab704
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 16 Apr 2021 10:27:52 -0400

hare::parse: implement slicing expressions

Diffstat:
Mhare/parse/+test/expr.ha | 7+++++++
Mhare/parse/expr.ha | 41++++++++++++++++++++++++++++++++---------
Mhare/unparse/expr.ha | 16+++++++++++++++-
3 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -33,6 +33,13 @@ "export fn main() void = x[10 + 10][20];\n"); }; +@test fn slice() void = { + roundtrip("export fn main() void = x[..];\n" + "export fn main() void = x[123..];\n" + "export fn main() void = x[123..321];\n" + "export fn main() void = x[..321];\n"); +}; + @test fn unarithm() void = { // TODO: object selectors/addr operator roundtrip("export fn main() void = +void;\n" diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -164,6 +164,37 @@ fn expression_list(lexer: *lex::lexer) (ast::expr | error) = { return items; }; +fn indexing(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = { + let is_slice = false; + let start: nullable *ast::expr = null, end: nullable *ast::expr = null; + + match (try(lexer, ltok::SLICE)?) { + void => start = alloc(expression(lexer)?), + lex::token => is_slice = true, + }; + if (!is_slice) match (try(lexer, ltok::SLICE)?) { + void => void, + lex::token => is_slice = true, + }; + if (is_slice) match (peek(lexer, ltok::RBRACKET)?) { + lex::token => void, + void => end = alloc(expression(lexer)?), + }; + + want(lexer, ltok::RBRACKET)?; + return if (is_slice) ast::slice_expr { + object = alloc(lvalue), + start = start, + end = end, + } else ast::access_index { + object = alloc(lvalue), + index = { + assert(start != null && end == null); + start: *ast::expr; + }, + }; +}; + fn objsel(lexer: *lex::lexer) (ast::expr | error) = { abort(); // TODO }; @@ -213,15 +244,7 @@ fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = tok: lex::token => switch (tok.0) { ltok::LPAREN => call(lexer, lvalue)?, ltok::DOT => postfix_dot(lexer, lvalue)?, - ltok::LBRACKET => { - // TODO: Slicing expressions - let expr = ast::access_index { - object = alloc(lvalue), - index = alloc(expression(lexer)?), - }; - want(lexer, ltok::RBRACKET)?; - expr; - }, + ltok::LBRACKET => indexing(lexer, lvalue)?, ltok::QUESTION => alloc(lvalue): ast::propagate_expr, * => abort(), }, diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -103,7 +103,21 @@ export fn expr( z + fmt::fprintf(out, "?")?; }, e: ast::return_expr => abort(), - e: ast::slice_expr => abort(), + e: ast::slice_expr => { + let z = expr(out, indent, *e.object)?; + z += fmt::fprint(out, "[")?; + z += match (e.start) { + null => 0z, + e: *ast::expr => expr(out, indent, *e)?, + }; + z += fmt::fprint(out, "..")?; + z += match (e.end) { + null => 0z, + e: *ast::expr => expr(out, indent, *e)?, + }; + z += fmt::fprint(out, "]")?; + z; + }, e: ast::switch_expr => abort(), e: ast::unarithm_expr => { let z = fmt::fprintf(out, "{}", switch (e.op) {