~smlavine/hareimports

af870432bd4540efd9b9d0c7141519f58f1ed422 — Sebastian LaVine 2 months ago 78d66b3
Add path field, newimport() helper constructor

path will be the field used to refer to the module, whether or not there
is an import alias.
1 files changed, 29 insertions(+), 16 deletions(-)

M main.ha
M main.ha => main.ha +29 -16
@@ 24,8 24,10 @@ use strings;
export type import = struct {
	// location of the first token in import after the use keyword
	location: lex::location,
	module: str,
	name: str,
	alias: str,
	// borrows the alias if there is one, otherwise borrows the name
	path: str,
	// TODO: handle second and third (unqualified) types of imports.
};



@@ 33,8 35,9 @@ export type import = struct {
export fn imports_freeall(imports: []import) void = {
	for (let i = 0z; i < len(imports); i += 1) {
		// TODO: imports[i].location?
		free(imports[i].module);
		free(imports[i].name);
		free(imports[i].alias);
		// DON'T free .path; it is a borrow
	};
	free(imports);
};


@@ 43,11 46,20 @@ export fn imports_freeall(imports: []import) void = {
// of the provided token.
fn badtoken(t: lex::token) lex::syntax = (t.2, lex::tokstr(t));

// Returns a [[import]] constructed from the provided parameters.
fn newimport(loc: lex::location, name: str, alias: str) import =
	import {
		location = loc,
		name = name,
		alias = alias,
		path = if (alias == "") name else alias,
	};

// Parses a single import statement from the provided [[hare::lex::lexer]].
// Precondition: the use keyword MUST have already been lexed.
// Only allow an alias to be parsed if the alias parameter is empty.
// An alias will only be lexed if recursive_alias is void.
// Returns an [[import]] on success, or [[hare::lex::error]] on failure.
fn getimport(lexp: *lex::lexer, alias: str) (import | lex::error) = {
fn getimport(lexp: *lex::lexer, recursive_alias: str) (import | lex::error) = {
	// The first token has to be a name: either the beginning of
	// an import-alias or the beginning of an identifier.
	// See also §6.4 (Identifiers).


@@ 55,12 67,6 @@ fn getimport(lexp: *lex::lexer, alias: str) (import | lex::error) = {
	if (first.0 != lex::ltok::NAME)
		return badtoken(first);

	let import = import {
		location = first.2,
		module = "",
		alias = alias,
	};

	let module_builder = strio::dynamic();
	defer io::close(&module_builder)!;



@@ 68,11 74,14 @@ fn getimport(lexp: *lex::lexer, alias: str) (import | lex::error) = {
	switch (second.0) {
	case lex::ltok::SEMICOLON =>
		// top-level (i.e. not a submodule) import
		import.module = strings::dup(lex::tokstr(first));
		return import;
		return newimport(
			first.2, // location
			strings::dup(lex::tokstr(first)),
			recursive_alias,
		);
	case lex::ltok::EQUAL =>
		// Import alias
		if (alias == "") {
		if (recursive_alias == "") {
			return getimport(lexp,
				strings::dup(lex::tokstr(first)));
		};


@@ 117,8 126,11 @@ fn getimport(lexp: *lex::lexer, alias: str) (import | lex::error) = {
		};
	};

	import.module = strings::dup(strio::string(&module_builder));
	return import;
	return newimport(
		first.2,
		strings::dup(strio::string(&module_builder)),
		recursive_alias,
	);
};

// Returns a slice of [[import]]s or a [[hare::lex::error]]. The slice must be


@@ 147,5 159,6 @@ export fn main() void = {
	defer imports_freeall(imports);

	for (let i = 0z; i < len(imports); i += 1)
		fmt::printfln("{} {}", imports[i].module, imports[i].alias)!;
		fmt::printfln("{} (= {})",
			imports[i].name, imports[i].path)!;
};