RosettaCodeData/Task/Subleq/BCPL/subleq.bcpl

80 lines
1.6 KiB
Plaintext

get "libhdr"
// Read a string
let reads(v) be
$( let ch = ?
v%0 := 0
ch := rdch()
until ch = '*N' do
$( v%0 := v%0 + 1
v%(v%0) := ch
ch := rdch()
$)
$)
// Try to read a number, fail on EOF
// (Alas, the included READN just returns 0 and that's a valid number)
let readnum(n) = valof
$( let neg, ch = false, ?
!n := 0
$( ch := rdch()
if ch = endstreamch then resultis false
$) repeatuntil ch = '-' | '0' <= ch <= '9'
if ch = '-' then
$( neg := true
ch := rdch()
$)
while '0' <= ch <= '9' do
$( !n := !n * 10 + ch - '0'
ch := rdch()
$)
if neg then !n := -!n
resultis true
$)
// Read SUBLEQ code
let readfile(file, v) = valof
$( let i, oldin = 0, input()
selectinput(file)
while readnum(v+i) do i := i + 1
endread()
selectinput(oldin)
resultis i
$)
// Run SUBLEQ code
let run(v) be
$( let ip = 0
until ip < 0 do
$( let a, b, c = v!ip, v!(ip+1), v!(ip+2)
ip := ip + 3
test a=-1
then v!b := rdch()
else test b=-1
then wrch(v!a)
else
$( v!b := v!b - v!a
if v!b <= 0 then ip := c
$)
$)
$)
let start() be
$( let filename = vec 64
let file = ?
writes("Filename? ")
reads(filename)
file := findinput(filename)
test file = 0 then
writes("Cannot open file.*N")
else
$( let top = maxvec()
let mem = getvec(top)
let progtop = readfile(file, mem)
for i = progtop to top do mem!i := 0
run(mem)
freevec(mem)
$)
$)