~smlavine/hareimports-dev

Scan module instead of reading from stdin v2 APPLIED

Sebastian: 1
 Scan module instead of reading from stdin

 1 files changed, 83 insertions(+), 17 deletions(-)
Export patchset (mbox)
How do I use this?

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 -3
Learn more about email & git

[PATCH v2] Scan module instead of reading from stdin Export this patch

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)!;
			case =>
				fmt::println(s)!;
			};
		};
	};
};
-- 
2.35.1