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:
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;
};