commit 604e3cd5743a715569158203c8ccc9ba2f738a50
parent db2bc4377d8181d64ed461c9cb971bd2ee5311eb
Author: Lou Woell <lou.woell@posteo.de>
Date:   Fri, 10 Oct 2025 03:28:53 +0200

[locate] integrate locate_module into locate_symbol

I'm honestly not sure if this is better than what I had before but it does
improve test coverage.

Diffstat:
Mcmd/harehelper/+test/locate_test.ha | 29++++++++++++++++-------------
Mcmd/harehelper/locate.ha | 76++++++++++++++++++++++++++++++++++------------------------------------------
2 files changed, 50 insertions(+), 55 deletions(-)

diff --git a/cmd/harehelper/+test/locate_test.ha b/cmd/harehelper/+test/locate_test.ha @@ -1,16 +1,17 @@ use dirs; use fmt; -use hare::ast; use hare::lex; use hare::module; use hare::parse; use os; +use test; use strings; def q = 1, w = 2; const s = 1, d = 2; fn loc_test_fn (in: str, out: lex::location) void = { + const ctx = module::context { harepath = harepath(), harecache = match (os::getenv("HARECACHE")) { @@ -23,19 +24,9 @@ fn loc_test_fn (in: str, out: lex::location) void = { }; let (id, trailing) = identstr_trailing(in)!; - defer ast::ident_free(id); - - let loc: (lex::location | void) = void; - if (!trailing) { - loc = locate_symbol(&ctx, id); - }; - - if(loc is void){ - loc = locate_module(&ctx, id); - }; + defer strings::freeall(id); - match(loc) { - case void => abort(); + match(locate_symbol(&ctx, id, trailing)) { case let l: lex::location => defer free(l.path); fmt::errorfln("path: {}, expected: {}", l.path, out.path)!; @@ -44,6 +35,8 @@ fn loc_test_fn (in: str, out: lex::location) void = { assert(l.line == out.line); fmt::errorfln("col: {}, expected: {}", l.col, out.col)!; assert(l.col == out.col); + case let e: module::error => + fmt::fatalf("Error: {}", strerror(e)); }; }; @@ -167,3 +160,13 @@ fn loc_test_fn (in: str, out: lex::location) void = { ... }); }; + +@test fn locate_not_found() void = { + test::expectabort(); + loc_test_fn("nothing", lex::location { + path = "foo.ha", + line = 111, + col = 111, + ... + }); +}; diff --git a/cmd/harehelper/locate.ha b/cmd/harehelper/locate.ha @@ -13,7 +13,7 @@ // this program. If not, see <https://www.gnu.org/licenses/>. use fmt; -use getopt::{command}; +use getopt; use hare::ast; use hare::lex; use hare::module; @@ -22,7 +22,7 @@ use os; use path; use strings; -fn locate (cmd: command, ctx: *module::context) void = { +fn locate (cmd: getopt::command, ctx: *module::context) void = { if(len(cmd.args) == 0) fmt::fatal("Expected Argument"); @@ -34,50 +34,25 @@ fn locate (cmd: command, ctx: *module::context) void = { }; defer ast::ident_free(id); - let loc: (lex::location | void) = void; - if (!trailing) { - loc = locate_symbol(ctx, id); - }; - - if(loc is void){ - loc = locate_module(ctx, id); - }; - - match (loc) { - case void=> void; + match (locate_symbol(ctx, id, trailing)) { + case let e: module::error => + fmt::fatalf("Error: {}", strerror(e)); case let d: lex::location => fmt::printfln("{}:{}:{}", d.path, d.line, d.col)!; free(d.path); }; }; -fn locate_module ( - ctx: *module::context, - id: ast::ident -) (lex::location | void) = { - match (module::find(ctx, id)) { - case let e: module::error => - module::finish_error(e); - return void; - case let r: (str, module::srcset) => - defer module::finish_srcset(&r.1); - return lex::location { - path = strings::dup(r.0)!, - line = 0, - col = 0, - off = 0, - }; - }; -}; - fn locate_symbol ( ctx: *module::context, - id: ast::ident -) (lex::location | void) = { + id: ast::ident, + module: bool = false, +) (lex::location | error) = { - let ns: module::location = ident_ns(id); // if no namespace prefix is present look for a declaration in the cwd. - if (len(id) <= 1) { + let ns: module::location = if (module) { + yield id; + } else if (len(id) <= 1) { let p = path::init(os::getcwd())!; let dirname = path::peek(&p) as str; @@ -86,21 +61,31 @@ fn locate_symbol ( strings::hasprefix(dirname, '-')) { path::pop(&p); }; - ns = &p; + yield &p; + } else { + yield ident_ns(id); }; - let (path, src) = match (module::find(ctx, ns)) { - case let e: module::error => - module::finish_error(e); - return void; + let (path, src) = match :module (module::find(ctx, ns)) { case let r: (str, module::srcset) => yield r; + case let e: module::error => + match (module::unwrap_error(e)) { + case module::not_found => + // free error and try finding id as module. + module::finish_error(e); + module = true; + yield :module, module::find(ctx, id)?; + case => + return e; + }; }; defer module::finish_srcset(&src); id = ident_last(id); - for (let s .. src.ha) { + if (!module) for (let s .. src.ha) { + let decls = match (scan(s)) { case let e: error => fmt::errorfln("Error reading {}: {}", s, strerror(e))!; @@ -144,4 +129,11 @@ fn locate_symbol ( }; }; }; + + if (module) return lex::location { + path = strings::dup(path)!, + line = 0, + col = 0, + off = 0, + } else return module::not_found; };