1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
use bio
use std
const readline = {line
var cmt = std.strfind(line, ";")
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:])
;;
}
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 parsehex = {s
if s[0] == ('#' : byte)
-> std.intparsebase((s[1:] : byte[:]), 16)
else
-> `std.None
;;
}
const emitinstr = {p
var b
var mark = `std.None
if p.len < 1
-> `std.Ok([][:], 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")
;;
-> `std.Ok((b, mark))
}
const main = {
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
for line : src ;
match readline(line)
| (`std.None, i): res = emitinstr(i)
| (`std.Some (label), i): res = emitinstr(i)
std.htput(labels, label, offset)
;;
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++
;;
std.put("{}", buf)
bio.free(fd)
}
|