hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 066afc4a432fa935705b157827e49aaa388712d1
parent 7e89859138660adc267f51de1a9ca05a39c953cd
Author: Alexey Yerin <yyp@disroot.org>
Date:   Wed, 30 Mar 2022 14:12:09 +0300

cmd/haredoc: resolve enum members

Signed-off-by: Alexey Yerin <yyp@disroot.org>

Diffstat:
Mcmd/haredoc/html.ha | 8++++++++
Mcmd/haredoc/resolver.ha | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+), 0 deletions(-)

diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha @@ -339,6 +339,14 @@ fn htmlref(ctx: *context, ref: ast::ident) (void | io::error) = { defer free(ipath); fmt::fprintf(ctx.out, "<a href='/{}#{}' class='ref'>{}</a>", ipath, id[len(id) - 1], ident)?; + case symkind::ENUM_LOCAL => + fmt::fprintf(ctx.out, "<a href='#{}' class='ref'>{}</a>", + id[len(id) - 2], ident)?; + case symkind::ENUM_REMOTE => + let ipath = module::identpath(id[..len(id) - 2]); + defer free(ipath); + fmt::fprintf(ctx.out, "<a href='/{}#{}' class='ref'>{}</a>", + ipath, id[len(id) - 2], ident)?; }; free(ident); }; diff --git a/cmd/haredoc/resolver.ha b/cmd/haredoc/resolver.ha @@ -1,13 +1,18 @@ // License: GPL-3.0 // (c) 2021 Drew DeVault <sir@cmpwn.com> // (c) 2021 Eyal Sawady <ecs@d2evs.net> +// (c) 2022 Alexey Yerin <yyp@disroot.org> +use fmt; use hare::ast; use hare::module; +use path; type symkind = enum { LOCAL, MODULE, SYMBOL, + ENUM_LOCAL, + ENUM_REMOTE, }; // Resolves a reference. Given an identifier, determines if it refers to a local @@ -28,6 +33,20 @@ fn resolve(ctx: *context, what: ast::ident) ((ast::ident, symkind) | void) = { case module::error => void; }; }; + if (len(what) == 2) { + match (lookup_local_enum(ctx, what)) { + case let id: ast::ident => + return (id, symkind::ENUM_LOCAL); + case => void; + }; + }; + if (len(what) > 2) { + match (lookup_remote_enum(ctx, what)) { + case let id: ast::ident => + return (id, symkind::ENUM_REMOTE); + case => void; + }; + }; match (module::lookup(ctx.mctx, what)) { case let ver: module::version => @@ -77,3 +96,83 @@ fn is_local(ctx: *context, what: ast::ident) bool = { return false; }; + +fn lookup_local_enum(ctx: *context, what: ast::ident) (ast::ident | void) = { + for (let i = 0z; i < len(ctx.summary.types); i += 1) { + const decl = ctx.summary.types[i]; + const name = decl_ident(decl)[0]; + if (name == what[0]) { + const t = (decl.decl as []ast::decl_type)[0]; + const e = match (t._type.repr) { + case let e: ast::enum_type => + yield e; + case => + return; + }; + for (let i = 0z; i < len(e.values); i += 1) { + if (e.values[i].name == what[1]) { + return what; + }; + }; + }; + }; +}; + +fn lookup_remote_enum(ctx: *context, what: ast::ident) (ast::ident | void) = { + // mod::decl_name::member + const mod = what[..len(what) - 2]; + const decl_name = what[len(what) - 2]; + const member = what[len(what) - 1]; + + const version = match (module::lookup(ctx.mctx, mod)) { + case let ver: module::version => + yield ver; + case module::error => + abort(); + }; + + // This would take a lot of memory to load + let decls: []ast::decl = []; + defer { + for (let i = 0z; i < len(decls); i += 1) { + ast::decl_free(decls[i]); + }; + free(decls); + }; + for (let i = 0z; i < len(version.inputs); i += 1) { + const in = version.inputs[i]; + const ext = path::extension(in.path); + if (ext.1 != ".ha") { + continue; + }; + match (scan(in.path)) { + case let u: ast::subunit => + append(decls, u.decls...); + case let err: error => + fmt::fatal("Error: {}", strerror(err)); + }; + }; + + for (let i = 0z; i < len(decls); i += 1) { + const decl = match (decls[i].decl) { + case let t: []ast::decl_type => + yield t; + case => continue; + }; + for (let i = 0z; i < len(decl); i += 1) { + if (decl[i].ident[0] == decl_name) { + const e = match (decl[i]._type.repr) { + case let e: ast::enum_type => + yield e; + case => + abort(); + }; + for (let i = 0z; i < len(e.values); i += 1) { + if (e.values[i].name == member) { + return what; + }; + }; + }; + }; + }; +};