~smlavine/hareimports-dev

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
3 2

[PATCH v2] Scan module instead of reading from stdin

Details
Message ID
<20220528022145.5048-1-sebastian@sebsite.pw>
DKIM signature
pass
Download raw message
Patch: +83 -17
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
Details
Message ID
<CKBK7MPTTE4M.1RYRJZB45O9UM@archlinux-x220>
In-Reply-To
<20220528022145.5048-1-sebastian@sebsite.pw> (view parent)
DKIM signature
fail
Download raw message
DKIM signature: fail
On Fri May 27, 2022 at 10:21 PM EDT, Sebastian wrote:
> 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?
Details
Message ID
<0ae89ca3-3e4a-4657-9b18-0c2d81f7dd06@sebsite.pw>
In-Reply-To
<CKBK7MPTTE4M.1RYRJZB45O9UM@archlinux-x220> (view parent)
DKIM signature
pass
Download raw message
> 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?

Sure! I normally don't use my last name online, but if you'd like to use 
it to distinguish between us, then my last name is "Hudak".
- Sebastian
Details
Message ID
<CKBM143HSOTM.38E8YFGWCPEET@archlinux-x220>
In-Reply-To
<0ae89ca3-3e4a-4657-9b18-0c2d81f7dd06@sebsite.pw> (view parent)
DKIM signature
fail
Download raw message
DKIM signature: fail
On Sat May 28, 2022 at 2:11 PM EDT, Sebastian wrote:
> > 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?
>
> Sure! I normally don't use my last name online, but if you'd like to use 
> it to distinguish between us, then my last name is "Hudak".
> - Sebastian

I'll use just your first name, for consistency with the copyright
headers in Hare. Feel free to change it of course.

https://git.sr.ht/~smlavine/hareimports/commit/f134161
Reply to thread Export thread (mbox)