hare

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

commit 0320abd4ee79c4139786cb01be1a09be72b93b0e
parent 2e83970d123e177196e7ea3571f7bcab399a18e8
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 22 Aug 2021 11:59:35 +0200

cmd/harec: add some meat to these bones

A brief stop is called for to implement some of these TODOs elsewhere.
Most importantly:

- Add a constant called valvoid
- Implement tagged unions (and their casts) in harec eval
- Add builtin type globals in hare::types like &types::builtin_void

Bonus points: update genutil.ha:emit's out parameter to
(...value | void) and gen breaks, should be investigated.

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mcmd/harec/gen.ha | 14++++++++++++--
Mcmd/harec/genutil.ha | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmd/harec/qbe.ha | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 217 insertions(+), 2 deletions(-)

diff --git a/cmd/harec/gen.ha b/cmd/harec/gen.ha @@ -1,5 +1,6 @@ use bufio; use fmt; +use hare::ast; use hare::module; use hare::types; use hare::unit; @@ -64,7 +65,16 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = { fmt::println("}\n")!; }; -fn gen_expr(ctx: *context, expr: *unit::expr) void = { +fn gen_expr(ctx: *context, expr: *unit::expr) value = { // TODO - fmt::fprintfln(ctx.out, "\tret")!; + emit(ctx, void, qinstr::RET); + + // TODO: + // - Make this a constant called valvoid + // - Implement tagged unions (and their casts) in eval + // - Add builtin type globals in hare::types like &types::builtin_void + return value { + value = qvoid, + _type = types::lookup_builtin(ctx.store, ast::builtin_type::VOID), + }; }; diff --git a/cmd/harec/genutil.ha b/cmd/harec/genutil.ha @@ -1,5 +1,111 @@ use fmt; +fn emit( + ctx: *context, + out: (value | void), + instr: qinstr, + args: value... +) void = { + fmt::fprintf(ctx.out, "\t")!; + match (out) { + val: value => abort(), // TODO + void => void, + }; + // TODO: The langauge should provide a means of converting enums to + // strings without this + fmt::fprint(ctx.out, switch (instr) { + qinstr::ADD => "add", + qinstr::ALLOC16 => "alloc16", + qinstr::ALLOC4 => "alloc4", + qinstr::ALLOC8 => "alloc8", + qinstr::AND => "and", + qinstr::CALL => "call", + qinstr::CAST => "cast", + qinstr::CEQD => "ceqd", + qinstr::CEQL => "ceql", + qinstr::CEQS => "ceqs", + qinstr::CEQW => "ceqw", + qinstr::CGED => "cged", + qinstr::CGES => "cges", + qinstr::CGTD => "cgtd", + qinstr::CGTS => "cgts", + qinstr::CLED => "cled", + qinstr::CLES => "cles", + qinstr::CLTD => "cltd", + qinstr::CLTS => "clts", + qinstr::CNED => "cned", + qinstr::CNEL => "cnel", + qinstr::CNES => "cnes", + qinstr::CNEW => "cnew", + qinstr::COD => "cod", + qinstr::COPY => "copy", + qinstr::COS => "cos", + qinstr::CSGEL => "csgel", + qinstr::CSGEW => "csgew", + qinstr::CSGTL => "csgtl", + qinstr::CSGTW => "csgtw", + qinstr::CSLEL => "cslel", + qinstr::CSLEW => "cslew", + qinstr::CSLTL => "csltl", + qinstr::CSLTW => "csltw", + qinstr::CUGEL => "cugel", + qinstr::CUGEW => "cugew", + qinstr::CUGTL => "cugtl", + qinstr::CUGTW => "cugtw", + qinstr::CULEL => "culel", + qinstr::CULEW => "culew", + qinstr::CULTL => "cultl", + qinstr::CULTW => "cultw", + qinstr::CUOD => "cuod", + qinstr::CUOS => "cuos", + qinstr::DIV => "div", + qinstr::DTOSI => "dtosi", + qinstr::EXTS => "exts", + qinstr::EXTSB => "extsb", + qinstr::EXTSH => "extsh", + qinstr::EXTSW => "extsw", + qinstr::EXTUB => "extub", + qinstr::EXTUH => "extuh", + qinstr::EXTUW => "extuw", + qinstr::JMP => "jmp", + qinstr::JNZ => "jnz", + qinstr::LOADD => "loadd", + qinstr::LOADL => "loadl", + qinstr::LOADS => "loads", + qinstr::LOADSB => "loadsb", + qinstr::LOADSH => "loadsh", + qinstr::LOADSW => "loadsw", + qinstr::LOADUB => "loadub", + qinstr::LOADUH => "loaduh", + qinstr::LOADUW => "loaduw", + qinstr::MUL => "mul", + qinstr::OR => "or", + qinstr::REM => "rem", + qinstr::RET => "ret", + qinstr::SAR => "sar", + qinstr::SHL => "shl", + qinstr::SHR => "shr", + qinstr::SLTOF => "sltof", + qinstr::STOREB => "storeb", + qinstr::STORED => "stored", + qinstr::STOREH => "storeh", + qinstr::STOREL => "storel", + qinstr::STORES => "stores", + qinstr::STOREW => "storew", + qinstr::STOSI => "stosi", + qinstr::SUB => "sub", + qinstr::SWTOF => "swtof", + qinstr::TRUNCD => "truncd", + qinstr::UDIV => "udiv", + qinstr::UREM => "urem", + qinstr::XOR => "xor", + })!; + for (let i = 0z; i < len(args); i += 1) { + abort(); // TODO + }; + fmt::fprintln(ctx.out)!; +}; + fn mklabel(ctx: *context, name: str) str = { static let buf: [1024]u8 = [0...]; let serial = ctx.serial; diff --git a/cmd/harec/qbe.ha b/cmd/harec/qbe.ha @@ -0,0 +1,99 @@ +use hare::types; + +type global = str; +type temporary = str; +type qvoid = void; +type constant = (u32 | u64 | f32 | f64 | str | qvoid); + +type value = struct { + value: (global | temporary | constant), + _type: const *types::_type, +}; + +type qinstr = enum { + ADD, + ALLOC16, + ALLOC4, + ALLOC8, + AND, + CALL, + CAST, + CEQD, + CEQL, + CEQS, + CEQW, + CGED, + CGES, + CGTD, + CGTS, + CLED, + CLES, + CLTD, + CLTS, + CNED, + CNEL, + CNES, + CNEW, + COD, + COPY, + COS, + CSGEL, + CSGEW, + CSGTL, + CSGTW, + CSLEL, + CSLEW, + CSLTL, + CSLTW, + CUGEL, + CUGEW, + CUGTL, + CUGTW, + CULEL, + CULEW, + CULTL, + CULTW, + CUOD, + CUOS, + DIV, + DTOSI, + EXTS, + EXTSB, + EXTSH, + EXTSW, + EXTUB, + EXTUH, + EXTUW, + JMP, + JNZ, + LOADD, + LOADL, + LOADS, + LOADSB, + LOADSH, + LOADSW, + LOADUB, + LOADUH, + LOADUW, + MUL, + OR, + REM, + RET, + SAR, + SHL, + SHR, + SLTOF, + STOREB, + STORED, + STOREH, + STOREL, + STORES, + STOREW, + STOSI, + SUB, + SWTOF, + TRUNCD, + UDIV, + UREM, + XOR, +};