Sebastian: 1 Scan module instead of reading from stdin 1 files changed, 83 insertions(+), 17 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~smlavine/hareimports-dev/patches/32557/mbox | git am -3Learn more about email & git
To add imports, the program needs to be able to distinguish between module identifiers and local enum identifiers. Enums may be declared in other source files within the module, so knowledge of the entire module is required to make this distinction. Signed-off-by: Sebastian <sebastian@sebsite.pw> --- main.ha | 100 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 17 deletions(-) diff --git a/main.ha b/main.ha index 22e734b..d6938ad 100644 --- a/main.ha +++ b/main.ha @@ -14,34 +14,100 @@ // along with this program. If not, see http://www.gnu.org/licenses/. use fmt; +use getopt; use hare::ast; use hare::lex; +use hare::module; use hare::parse; +use hare::unparse; +use io; use os; -use strings; export fn main() void = { - const lexer = lex::init(os::stdin, "<stdin>", lex::flags::NONE); + const help: []getopt::help = [ + "Hare import manager", + ('T', "tags...", "set tags"), + "[<path>]" + ]; + const cmd = getopt::parse(os::args, help...); + defer getopt::finish(&cmd); - const subunit = match (parse::subunit(&lexer)) { - case let s: ast::subunit => - yield s; - case let e: parse::error => - fmt::fatalf(parse::strerror(e)); + let tags: []module::tag = []; + defer module::tags_free(tags); + for (let i = 0z; i < len(cmd.opts); i += 1) { + const opt = cmd.opts[i]; + // XXX: should accept multiple -T options, and maybe also -X + // See addtags and deltags in cmd/hare/subcmds.ha + switch (opt.0) { + case 'T' => + // This flag is needed for hareimports to know whether + // an indentifier refers to a remote module/enum or a + // local enum only defined within a tagset. + + if (len(tags) > 0) { + getopt::printusage(os::stderr, + "hareimports", help); + os::exit(1); + }; + tags = match (module::parsetags(opt.1)) { + case void => + fmt::fatal("Invalid tag set"); + case let t: []module::tag => + yield t; + }; + case => abort(); // unreachable + }; + }; + + const path = switch (len(cmd.args)) { + case 0 => + yield "."; + case 1 => + yield cmd.args[0]; + case => + getopt::printusage(os::stderr, "hareimports", help); + os::exit(1); + }; + + const mctx = module::context_init(tags, [], ""); + defer module::context_finish(&mctx); + + const ver = match (module::scan(&mctx, path)) { + case let v: module::version => + yield v; + case let e: module::error => + fmt::fatal(module::strerror(e)); }; - defer ast::subunit_finish(subunit); - for (let i = 0z; i < len(subunit.imports); i += 1) { - const m = &subunit.imports[i]; + for (let i = 0z; i < len(ver.inputs); i += 1) { + const input = ver.inputs[i]; + if (input.ft != module::filetype::HARE) { + continue; + }; + const f = os::open(input.path)!; + defer io::close(f)!; + + const lexer = lex::init(f, input.path); + const subunit = match (parse::subunit(&lexer)) { + case let s: ast::subunit => + yield s; + case let e: parse::error => + fmt::fatal(parse::strerror(e)); + }; + defer ast::subunit_finish(subunit); - const joined_ident = strings::join("::", m.ident...); - defer free(joined_ident); + fmt::printfln("{}:", input.path)!; + for (let i = 0z; i < len(subunit.imports); i += 1) { + const m = &subunit.imports[i]; - switch (m.mode) { - case ast::import_mode::ALIAS => - fmt::printfln("{} (= {})", m.alias, joined_ident)!; - case => - fmt::println(joined_ident)!; + const s = unparse::identstr(m.ident); + defer free(s); + switch (m.mode) { + case ast::import_mode::ALIAS => + fmt::printfln("{} (= {})", m.alias, s)!;
Didn't catch on v1, but nice on using unparse::identstr; that's exactly what I was looking for but didn't know that it existed.
+ case => + fmt::println(s)!; + }; }; }; }; -- 2.35.1
Looks good to me! Thank you for your additions and fixes. Applied as a6fd83e6cc38e6104ea4e733589f9e1213d19b7c. Because of the substantial nature of your patch, I'd like to add your name and email to the copyright header at the top of main.ha. Would that be alright with you?