hare

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

commit 82f8c418578bf8004975bf7ddfd218ba20f08cad
parent e4b13d5c8f052980a6457e044fdfbeffafb00525
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon, 19 Apr 2021 10:04:06 -0400

cmd/haredoc: initial commit

This is only at a proof-of-concept level of sophistication.

Diffstat:
Acmd/haredoc/errors.ha | 13+++++++++++++
Acmd/haredoc/main.ha | 37+++++++++++++++++++++++++++++++++++++
Acmd/haredoc/unparse.ha | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+), 0 deletions(-)

diff --git a/cmd/haredoc/errors.ha b/cmd/haredoc/errors.ha @@ -0,0 +1,13 @@ +use hare::lex; +use hare::parse; + +type eof = void; +type syntaxerr = void; +type error = (lex::error | parse::error | syntaxerr | eof)!; + +fn strerror(err: error) str = match (err) { + err: lex::error => lex::strerror(err), + err: parse::error => parse::strerror(err), + eof => "Unexpected EOF", + syntaxerr => "Syntax error", +}; diff --git a/cmd/haredoc/main.ha b/cmd/haredoc/main.ha @@ -0,0 +1,37 @@ +use fmt; +use hare::ast; +use hare::lex; +use hare::parse; +use io; +use os; +use strings; + +export fn main() void = { + const lexer = lex::init(os::stdin, "<stdin>", lex::flags::COMMENTS); + const unit = match (parse::subunit(&lexer)) { + u: ast::subunit => u, + err: parse::error => fmt::fatal(parse::strerror(err)), + }; + for (let i = 0z; i < len(unit.decls); i += 1) { + const decl = unit.decls[i]; + if (!decl.exported || decl.docs == "") { + continue; + }; + + let iter = strings::tokenize(decl.docs, "\n"); + for (true) match (strings::next_token(&iter)) { + s: str => if (len(s) != 0) { + fmt::printfln("//{}", s); + }, + void => break, + }; + + match (unparse_decl(os::stdout, decl)) { + err: io::error => fmt::fatal(io::strerror(err)), + size => void, + }; + + fmt::println(); + fmt::println(); + }; +}; diff --git a/cmd/haredoc/unparse.ha b/cmd/haredoc/unparse.ha @@ -0,0 +1,90 @@ +use io; +use fmt; +use hare::ast; +use hare::lex; +use hare::unparse; +use strio; + +// Forked from [hare::unparse] to reformat the output in a more suitable form +// for documentation. +fn unparse_decl(out: *io::stream, d: ast::decl) (size | io::error) = { + let n = 0z; + match (d.decl) { + g: []ast::decl_global => { + n += fmt::fprint(out, + if (g[0].is_const) "def " else "let ")?; + for (let i = 0z; i < len(g); i += 1) { + if (len(g[i].symbol) != 0) { + n += fmt::fprintf(out, + "@symbol(\"{}\") ", g[i].symbol)?; + }; + n += unparse::ident(out, g[i].ident)?; + n += fmt::fprint(out, ": ")?; + n += unparse::_type(out, 0, g[i]._type)?; + if (i + 1 < len(g)) { + n += fmt::fprint(out, ", ")?; + }; + }; + }, + t: []ast::decl_type => { + n += fmt::fprint(out, "type ")?; + for (let i = 0z; i < len(t); i += 1) { + n += unparse::ident(out, t[i].ident)?; + n += fmt::fprint(out, " = ")?; + n += unparse::_type(out, 0, t[i]._type)?; + if (i + 1 < len(t)) { + n += fmt::fprint(out, ", ")?; + }; + }; + }, + f: ast::decl_func => { + n += fmt::fprint(out, switch (f.attrs) { + ast::fndecl_attrs::NONE => "", + ast::fndecl_attrs::FINI => "@fini ", + ast::fndecl_attrs::INIT => "@init ", + ast::fndecl_attrs::TEST => "@test ", + })?; + let p = f.prototype._type as ast::func_type; + if (p.attrs & ast::func_attrs::NORETURN != 0) { + n += fmt::fprint(out, "@noreturn ")?; + }; + if (len(f.symbol) != 0) { + n += fmt::fprintf(out, "@symbol(\"{}\") ", + f.symbol)?; + }; + n += fmt::fprint(out, "fn ")?; + n += unparse::ident(out, f.ident)?; + n += prototype(out, 0, f.prototype._type as ast::func_type)?; + }, + }; + n += fmt::fprint(out, ";")?; + return n; +}; + +fn prototype( + out: *io::stream, + indent: size, + t: ast::func_type, +) (size | io::error) = { + let n = 0z; + n += fmt::fprint(out, "(")?; + for (let i = 0z; i < len(t.params); i += 1) { + let param = t.params[i]; + n += fmt::fprintf(out, "{}: ", + if (len(param.name) == 0) "_" else param.name)?; + n += unparse::_type(out, indent, *param._type)?; + if (i + 1 == len(t.params) + && t.variadism == ast::variadism::HARE) { + n += fmt::fprintf(out, "...")?; + }; + if (i + 1 < len(t.params)) { + n += fmt::fprint(out, ", ")?; + }; + }; + if (t.variadism == ast::variadism::C) { + n += fmt::fprint(out, ", ...")?; + }; + n += fmt::fprint(out, ") ")?; + n += unparse::_type(out, indent, *t.result)?; + return n; +};