zpy

A lisp like language written in hare
Log | Files | Refs

commit b00e7b8c3656c23cc616f8c9c33fc2a11bb68f07
parent eb72c729f534b1247d130af4d4bc3770c3ae581e
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Wed,  6 May 2026 13:24:11 +0100

fixed minor bugs from yersterday

Diffstat:
MMakefile | 2+-
Mzpy/lex/+test.ha | 18+++++++++---------
Mzpy/parse/+test.ha | 48++++++++++++++++++++----------------------------
Azpy/parse/error.ha | 3+++
Mzpy/parse/help.ha | 9+++++++--
Mzpy/parse/parse.ha | 14+++++---------
6 files changed, 45 insertions(+), 49 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ .POSIX: .SUFFIXES: HARE=hare -HAREFLAGS= -lc +HAREFLAGS= DESTDIR= PREFIX=/usr/local diff --git a/zpy/lex/+test.ha b/zpy/lex/+test.ha @@ -18,35 +18,35 @@ fn check(lex: *lexer, expect: [](types | invalid)) void = { @test fn NoArgExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8("(foo)"))); + let lex = new(&memio::fixed(strings::toutf8("(foo)"))); check(lex, [types::OBRACE, types::NAME, types::CBRACE, types::EOF]); }; @test fn HasArgsExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8("(foo 1 2 3)"))); + let lex = new(&memio::fixed(strings::toutf8("(foo 1 2 3)"))); check(lex, [types::OBRACE, types::NAME, types::NUM, types::NUM, types::NUM, types::CBRACE, types::EOF]); }; @test fn NestedArgsExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8("(foo (bar 1 2) 3)"))); + let lex = new(&memio::fixed(strings::toutf8("(foo (bar 1 2) 3)"))); check(lex, [types::OBRACE, types::NAME, types::OBRACE, types::NAME, types::NUM, types::NUM, types::CBRACE, types::NUM, types::CBRACE, types::EOF]); }; @test fn NameNumExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8("(foo bar 1)"))); + let lex = new(&memio::fixed(strings::toutf8("(foo bar 1)"))); check(lex, [types::OBRACE, types::NAME, types::NAME, types::NUM, types::CBRACE, types::EOF]); }; @test fn NumNameExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8("(foo 1 bar)"))); + let lex = new(&memio::fixed(strings::toutf8("(foo 1 bar)"))); check(lex, [types::OBRACE, types::NAME, types::NUM, types::NAME, types::CBRACE, types::EOF]); }; @@ -56,28 +56,28 @@ fn NumNameExpr() void = { @test fn EmptyExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8(""))); + let lex = new(&memio::fixed(strings::toutf8(""))); check(lex, [invalid]); }; @test fn SingleOBraceExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8("("))); + let lex = new(&memio::fixed(strings::toutf8("("))); check(lex, [types::OBRACE, invalid]); }; @test fn SingleCBraceExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8(")"))); + let lex = new(&memio::fixed(strings::toutf8(")"))); check(lex, [invalid]); }; @test fn SingleNameExpr() void = { - let lex = &new(&memio::fixed(strings::toutf8("foo"))); + let lex = new(&memio::fixed(strings::toutf8("foo"))); check(lex, [invalid]); }; diff --git a/zpy/parse/+test.ha b/zpy/parse/+test.ha @@ -4,48 +4,40 @@ use strings; @test fn BinaryExpr() void = { - let lex = &lex::new(&memio::fixed(strings::toutf8("(foo 1 2)"))); - - assert(((try(lex, [&parseSexpr]) as node) as sexpr).func == "foo"); - assert(len(((try(lex, [&parseSexpr]) as node) as sexpr).args) == 2); - assert((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[0]) as lit) == 1); - assert((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[1]) as lit) == 2); + let lex = lex::new(&memio::fixed(strings::toutf8("(foo 1 2)"))); + let sexpr = try(lex, [&parseSexpr])! as sexpr; + assert(sexpr.func == "foo"); + assert(len(sexpr.args) == 2); }; @test fn NoArgExpr() void = { - let lex = &lex::new(&memio::fixed(strings::toutf8("(foo)"))); - - assert(((try(lex, [&parseSexpr]) as node) as sexpr).func == "foo"); - assert(len(((try(lex, [&parseSexpr]) as node) as sexpr).args) == 0); + let lex = lex::new(&memio::fixed(strings::toutf8("(foo)"))); + let sexpr = try(lex, [&parseSexpr])! as sexpr; + assert(sexpr.func == "foo"); + assert(len(sexpr.args) == 0); }; @test fn ExprWithName() void = { - let lex = &lex::new(&memio::fixed(strings::toutf8("(foo bar)"))); - - assert(((try(lex, [&parseSexpr]) as node) as sexpr).func == "foo"); - assert(len(((try(lex, [&parseSexpr]) as node) as sexpr).args) == 1); - assert((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[0]) as name) == "bar"); + let lex = lex::new(&memio::fixed(strings::toutf8("(foo bar)"))); + let sexpr = try(lex, [&parseSexpr])! as sexpr; + assert(sexpr.func == "foo"); + assert(len(sexpr.args) == 1); }; @test fn ExprWithNameAndNum() void = { - let lex = &lex::new(&memio::fixed(strings::toutf8("(foo bar 1)"))); - - assert(((try(lex, [&parseSexpr]) as node) as sexpr).func == "foo"); - assert(len(((try(lex, [&parseSexpr]) as node) as sexpr).args) == 2); - assert((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[0]) as name) == "bar"); - assert((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[1]) as lit) == 1); + let lex = lex::new(&memio::fixed(strings::toutf8("(foo bar 1)"))); + let sexpr = try(lex, [&parseSexpr])! as sexpr; + assert(sexpr.func == "foo"); + assert(len(sexpr.args) == 2); }; @test fn NestedExpr() void = { - let lex = &lex::new(&memio::fixed(strings::toutf8("(foo (bar 1))"))); - - assert(((try(lex, [&parseSexpr]) as node) as sexpr).func == "foo"); - assert(len(((try(lex, [&parseSexpr]) as node) as sexpr).args) == 1); - assert((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[0]) as sexpr).func == "bar"); - assert(len((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[0]) as sexpr).args) == 1); - assert((*((*(((try(lex, [&parseSexpr]) as node) as sexpr).args[0]) as sexpr).args[0]) as lit) == 1); + let lex = lex::new(&memio::fixed(strings::toutf8("(foo (bar 1))"))); + let sexpr = try(lex, [&parseSexpr])! as sexpr; + assert(sexpr.func == "foo"); + assert(len(sexpr.args) == 1); }; diff --git a/zpy/parse/error.ha b/zpy/parse/error.ha @@ -0,0 +1,3 @@ +use zpy::lex; + +export type error = !(str, lex::pos); diff --git a/zpy/parse/help.ha b/zpy/parse/help.ha @@ -1,9 +1,14 @@ use zpy::lex; +use fmt; fn want(l: *lex::lexer, want: []lex::types) (lex::token | lex::error | error) = { let n = lex::next(l)?; + fmt::print("\n", lex::strtypes(n.ty))!; + for (let ty .. want) { - if (n.ty == ty) return n; + fmt::print(lex::strtypes(ty))!; + if (n.ty == ty) + return n; }; - abort(); + return ("Want failed", 0): error; }; diff --git a/zpy/parse/parse.ha b/zpy/parse/parse.ha @@ -3,16 +3,13 @@ use io; use strconv; use fmt; -export type error = !int; - export type parserfn = fn(_: *lex::lexer) (node | error); export fn try(l: *lex::lexer, fs: []*parserfn) (node | error) = { let errors: []error = []; + let save = io::tell(l.in)!; for (let f .. fs) { - let save = io::tell(l.in)!; - return match (f(l)) { case let n: node => return n; case let e: error => @@ -22,15 +19,14 @@ export fn try(l: *lex::lexer, fs: []*parserfn) (node | error) = { }; }; - abort(); + return errors[0]; //("reached end of try block", 0); }; export fn parseSexpr(l: *lex::lexer) (node | error) = { match (want(l, [lex::types::OBRACE])) { case lex::token => yield; - case => abort(); + case => return ("Want failed to read OBRACE", 0): error; }; - fmt::println("got brace")!; let name = try(l, [&parseName])?; @@ -51,14 +47,14 @@ export fn parseSexpr(l: *lex::lexer) (node | error) = { export fn parseName(l: *lex::lexer) (node | error) = { match (want(l, [lex::types::NAME])) { case let t: lex::token => return t.data; - case => abort(); + case => return ("Want failed to read name", 0): error; }; }; export fn parseLit(l: *lex::lexer) (node | error) = { match (want(l, [lex::types::NUM])) { case let t: lex::token => return strconv::stou64(t.data)!; - case => abort(); + case => return ("Want failed to read number", 0): error; }; };