hare

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

commit dc4f509f414ae5c0d621ee56f3785b92fa630e0f
parent 3360dd77e0dcc6484b29dde9ab0942f57b37212b
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  2 Sep 2021 11:06:45 +0200

cmd/harec: basic qtypes

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

Diffstat:
Mcmd/harec/gen.ha | 3++-
Mcmd/harec/genutil.ha | 106-------------------------------------------------------------------------------
Mcmd/harec/qbe.ha | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmd/harec/qtype.ha | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 187 insertions(+), 107 deletions(-)

diff --git a/cmd/harec/gen.ha b/cmd/harec/gen.ha @@ -49,7 +49,8 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = { * => true, }; if (has_rval) { - abort(); // TODO: Return type + const qrtype = qtype_lookup(ctx, rtype, false); + fmt::printf(" {}", qtype_repr(qrtype))!; }; fmt::printf(" ${}(", ident)!; assert(len(fntype.params) == 0); // TODO diff --git a/cmd/harec/genutil.ha b/cmd/harec/genutil.ha @@ -1,111 +1,5 @@ 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 @@ -1,3 +1,4 @@ +use fmt; use hare::types; type global = str; @@ -16,6 +17,112 @@ const vvoid: value = value { _type = &types::builtin_void, }; +fn emit( + ctx: *context, + out: (value | void), + instr: qinstr, + args: (value | qval | qtype)... +) 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)!; +}; + type qinstr = enum { ADD, ALLOC16, diff --git a/cmd/harec/qtype.ha b/cmd/harec/qtype.ha @@ -0,0 +1,78 @@ +use fmt; +use hare::types; +use hare::types::{builtin}; + +type stype = enum { + BYTE = 'b', + HALF = 'h', + WORD = 'w', + LONG = 'l', + SINGLE = 's', + DOUBLE = 'd', +}; + +type qcompound = struct { + name: str, + fields: []qtype_field, + base: const *types::_type, +}; + +type qtype = (stype | qcompound | void); + +type qtype_field = struct { + qtype: const *qtype, + count: size, +}; + +// Singletons +const qbyte: qtype = stype::BYTE; +const qhalf: qtype = stype::HALF; +const qword: qtype = stype::WORD; +const qlong: qtype = stype::LONG; +const qsingle: qtype = stype::SINGLE; +const qdouble: qtype = stype::DOUBLE; + +fn qtype_lookup( + ctx: *context, + _type: const *types::_type, + extype: bool, +) const *qtype = match (_type.repr) { + bi: builtin => switch (bi) { + builtin::CHAR => + if (extype) &qbyte else &qword, + builtin::I8, builtin::U8 => + if (extype) &qbyte else &qword, + builtin::I16, builtin::U16 => + if (extype) &qhalf else &qword, + builtin::BOOL => &qword, + builtin::F32 => &qsingle, + builtin::F64 => &qdouble, + builtin::I32, builtin::U32, builtin::RUNE => &qword, + builtin::I64, builtin::U64 => &qlong, + builtin::INT, builtin::UINT, + builtin::NULL, builtin::UINTPTR, + builtin::SIZE => switch (_type.sz) { + 4 => &qword, + 8 => &qlong, + * => abort(), + }, + builtin::STR => qtype_aggregate(ctx, _type), + builtin::VOID => abort(), + }, + * => abort(), +}; + +fn qtype_aggregate(ctx: *context, _type: const *types::_type) const *qtype = { + abort(); // TODO +}; + +// XXX: This dereference should not be necessary after the match +// overhaul +fn qtype_repr(qtype: const *qtype) const str = match (*qtype) { + st: stype => { + static let buf: [1]u8 = [0...]; + yield fmt::bsprintf(buf, "{}", st: rune); + }, + qc: qcompound => abort(), // TODO + void => "", +};