90 lines
2.3 KiB
Text
90 lines
2.3 KiB
Text
% Read numbers from a stream
|
|
read_nums = iter (s: stream) yields (int)
|
|
while true do
|
|
c: char := stream$getc(s)
|
|
while c~='-' & ~(c>='0' & c<='9') do
|
|
c := stream$getc(s)
|
|
end
|
|
acc: int := 0
|
|
neg: bool
|
|
if c='-' then
|
|
neg := true
|
|
c := stream$getc(s)
|
|
else
|
|
neg := false
|
|
end
|
|
while c>='0' & c<='9' do
|
|
acc := acc*10 + char$c2i(c) - char$c2i('0')
|
|
c := stream$getc(s)
|
|
except when end_of_file: break end
|
|
end
|
|
if neg then acc := -acc end
|
|
yield(acc)
|
|
end except when end_of_file: end
|
|
end read_nums
|
|
|
|
% Auto-resizing array
|
|
mem = cluster is new, load, fetch, store
|
|
rep = array[int]
|
|
|
|
new = proc () returns (cvt)
|
|
return(rep$predict(0,2**9))
|
|
end new
|
|
|
|
fill_to = proc (a: rep, lim: int)
|
|
while rep$high(a) < lim do rep$addh(a,0) end
|
|
end fill_to
|
|
|
|
fetch = proc (a: cvt, n: int) returns (int) signals (bounds)
|
|
fill_to(a,n)
|
|
return(a[n]) resignal bounds
|
|
end fetch
|
|
|
|
store = proc (a: cvt, n: int, v: int) signals (bounds)
|
|
fill_to(a,n)
|
|
a[n] := v resignal bounds
|
|
end store
|
|
|
|
load = proc (a: cvt, s: stream)
|
|
i: int := 0
|
|
for n: int in read_nums(s) do
|
|
up(a)[i] := n
|
|
i := i + 1
|
|
end
|
|
end load
|
|
end mem
|
|
|
|
% Run a Subleq program
|
|
subleq = proc (m: mem, si, so: stream)
|
|
ip: int := 0
|
|
while ip >= 0 do
|
|
a: int := m[ip]
|
|
b: int := m[ip+1]
|
|
c: int := m[ip+2]
|
|
ip := ip + 3
|
|
if a=-1 then m[b] := char$c2i(stream$getc(si))
|
|
elseif b=-1 then stream$putc(so,char$i2c(m[a] // 256))
|
|
else
|
|
m[b] := m[b] - m[a]
|
|
if m[b] <= 0 then ip := c end
|
|
end
|
|
end
|
|
end subleq
|
|
|
|
start_up = proc ()
|
|
pi: stream := stream$primary_input()
|
|
po: stream := stream$primary_output()
|
|
|
|
args: sequence[string] := get_argv()
|
|
if sequence[string]$size(args) ~= 1 then
|
|
stream$putl(stream$error_output(), "Usage: subleq file_name")
|
|
return
|
|
end
|
|
|
|
fname: file_name := file_name$parse(sequence[string]$bottom(args))
|
|
file: stream := stream$open(fname, "read")
|
|
m: mem := mem$new()
|
|
mem$load(m, file)
|
|
stream$close(file)
|
|
subleq(m, pi, po)
|
|
end start_up
|