diff options
Diffstat (limited to 'asm.myr')
| -rw-r--r-- | asm.myr | 166 |
1 files changed, 96 insertions, 70 deletions
@@ -1,97 +1,123 @@ use bio use std +const strdup = {s + var buf = std.slalloc(s.len) + std.slcp(buf, s) + -> buf +} + +const upcase = {s + var i + var buf = std.mksb() + for i = 0; i < s.len; i++ + std.sbputc(buf, std.toupper((s[i] : char))) + ;; + -> std.sbfin(buf) +} + const readline = {line - var cmt = std.strfind(line, ";") + var cmt = std.strfind(line, ";") - match cmt - | `std.Some (pos): line = line[:pos] - | `std.None: - ;; + match cmt + | `std.Some (pos): line = line[:pos] + | `std.None: + ;; - var parts = std.strtok(line) - if std.isspace((line[0] : char)) - -> (`std.None, parts) - else - -> (`std.Some(parts[0]), parts[1:]) - ;; -} + if line.len == 0 + -> (`std.None, [][:]) + ;; -const upcase = {s - var i - var buf = std.mksb() - for i = 0; i < s.len; i++ - std.sbputc(buf, std.toupper((s[i] : char))) - ;; - -> std.sbfin(buf) + var parts = std.strtok(line) + if std.isspace((line[0] : char)) + -> (`std.None, parts) + else + -> (`std.Some(parts[0]), parts[1:]) + ;; } const parsehex = {s - if s[0] == ('#' : byte) - -> std.intparsebase((s[1:] : byte[:]), 16) - else - -> `std.None - ;; + if s[0] == ('#' : byte) + -> std.intparsebase((s[1:] : byte[:]), 16) + else + -> `std.None + ;; } const emitinstr = {p - var b - var mark = `std.None + var b = `std.None + var mark = `std.None - if p.len < 1 - -> `std.Ok([][:], mark) - ;; + if p.len < 1 + -> `std.Ok(b, mark) + ;; - match upcase(p[0]) - | "CLS": - b = [0x00, 0xe0][:] - | "SYS": - if p.len < 2 - -> `std.Err("SYS missing subroutine address") - ;; - match parsehex(p[1]) - | `std.Some(n): b = [0x20 | (n & 0x0f00), (n & 0xff)][:] - | `std.None: b = [0x2f, 0xff][:] - mark = `std.Some(p[1]) - ;; - | _: - -> `std.Err("unrecognized instruction") + match upcase(p[0]) + | "CLS": + b = `std.Some([0x00, 0xe0]) + | "SYS": + if p.len < 2 + -> `std.Err("SYS missing subroutine address") + ;; + match parsehex(p[1]) + | `std.Some(n): b = `std.Some([0x20 | (n & 0x0f00), (n & 0xff)]) + | `std.None: b = `std.Some([0x20, 0x00]) + mark = `std.Some(strdup(p[1])) ;; + | _: + -> `std.Err("unrecognized instruction") + ;; - -> `std.Ok((b, mark)) + -> `std.Ok((b, mark)) } const main = { - var fd = bio.mkfile(std.In, bio.Rd) - var src = bio.byline(fd) - var lc = 0 + var fd = bio.mkfile(std.In, bio.Rd) + var src = bio.byline(fd) + var lc = 0 - var offset = 0 - var queue = [][:] - var buf = [][:] - var labels = std.mkht() - var res + var offset = 0 + var queue = [][:] + var buf = [][:] + var labels = std.mkht() + var res - for line : src ; - match readline(line) - | (`std.None, i): res = emitinstr(i) - | (`std.Some (label), i): res = emitinstr(i) - std.htput(labels, label, offset) - ;; + for line : src ; + match readline(line) + | (`std.None, i): res = emitinstr(i) + | (`std.Some (label), i): res = emitinstr(i) + std.htput(labels, strdup(label), offset) + ;; + + match res + | `std.Err(msg): std.die(std.fmt("{} on line {}\n", msg, lc)) + | `std.Ok((bytes, marker)): + match marker + | `std.Some(label): queue = std.slpush(&queue, (label, offset, lc)) + | `std.None: + ;; + match bytes + | `std.Some(arr): buf = std.sljoin(&buf, arr[:]) + offset += 2 + | `std.None: + ;; + ;; - match res - | `std.Err(msg): std.die(std.fmt("{} at {}", msg, lc)) - | `std.Ok((bytes, marker)): buf = std.sljoin(&buf, bytes) - offset += bytes.len - match marker - | `std.Some(label): queue = std.slpush(&queue, label) - | `std.None: - ;; - ;; + lc++ + ;; - lc++ + for replacement : queue ; + match replacement + | (l, buf_pos, src_pos): + match std.htget(labels, l) + | `std.None: std.die(std.fmt("reference to undefined label '{}' on line {}\n", l, src_pos)) + | `std.Some(addr): buf[buf_pos] |= addr & 0x0f00 + buf[buf_pos + 1] |= addr & 0xff + ;; ;; - std.put("{}", buf) + ;; + + std.write(std.Out, buf) - bio.free(fd) + bio.free(fd) } |