5 This is a Lazy K interpreter - basically a rewrite of lazy.cpp in PIR.
6 Lazy K is a pure functional programming language following the SKI calculus.
14 L<http://en.wikipedia.org/wiki/Lazy_K_programming_language>
20 - chained commandline args and -e, -b
22 And a lot of comments in the source - sorry.
33 # define constants for he various kinds of expressions
34 .globalconst int expA = 1
35 .globalconst int expI = 2
36 .globalconst int expI1 = 3
37 .globalconst int expK = 4
38 .globalconst int expK1 = 5
39 .globalconst int expS = 6
40 .globalconst int expS1 = 7
41 .globalconst int expS2 = 8
42 .globalconst int expLR = 9
43 .globalconst int expInc = 10
44 .globalconst int expNum = 11
47 # TODO -e, chained arguments
48 if argc > 1 goto open_file
56 printerr "can't open '"
58 printerr "' for reading."
66 ## _dumper( prog, "prog" )
71 lr = new_expr(expLR, NUL, NUL)
76 # convert results from a list of church numbers to 8-bit chars
77 # cchar >= 256 means exit = ccchar - 256
90 # append expressions so that they are run in sequence
97 k1f = new_expr(expK1, f, NUL)
99 .return new_expr(expS2, k1f, g)
106 .return run_in_sequence(n, old)
109 # convert expression (which sould be a churn numeral to a native int
110 # this is done by evaluating lambda (n) (Inc n 0)
114 .local pmc e, Zero, Inc, result
117 e = new_apply(church, Inc)
118 e = new_apply(e, Zero)
120 $I0 = to_number(result)
121 if $I0 == -1 goto err
124 printerr "invalid output format - not a number\n"
133 .return new_apply(list, k)
141 .return new_apply(list, ki)
144 # create globals for commonly used expressions and
145 # initialize the first 2 church numerals
147 .local pmc e, NUL, K, S, KS, I, KI
149 K = new_expr(expK, NUL, NUL)
151 S = new_expr(expS, NUL, NUL)
153 I = new_expr(expI, NUL, NUL)
155 KI = new_expr(expK1, I, NUL)
157 e = new_expr(expS1, I, NUL)
159 KS = new_expr(expK1, S, NUL)
161 e = new_expr(expK1, K, NUL)
163 e = new_expr(expS2, KS, K)
165 e = new_expr(expS2, I, KS)
168 e = new_expr(expInc, NUL, NUL)
171 e = new_expr(expNum, $P0, NUL)
175 cache = new 'FixedPMCArray'
179 global "church_cache" = cache
183 # create a new expression of the given type
190 expr = new 'FixedPMCArray'
199 # create a new apply expr
204 .return new_expr(expA, lhs, rhs)
207 # parse from an IO handle
208 # only 'ski currently
213 .local pmc op, arg, NUL
221 unless ch == '`' goto not_bq
224 .return new_apply(op, arg)
226 unless ch == 'i' goto not_i
229 unless ch == 'k' goto not_k
232 unless ch == 's' goto not_s
235 unless ch == '#' goto not_comment
238 if ch != "\n" goto swallow
241 if ch == ' ' goto loop
242 if ch == "\t" goto loop
243 if ch == "\n" goto loop
244 if ch == "\r" goto loop
245 printerr "unrecogniced char in program '"
251 # apply identy which just returns it's rhs
252 # this can be done in a loop, if we have a sequence of I1
258 if type != expI1 goto ret_e
265 # convert a native int to a church numeral expression
266 # the first 2 are pregenerated, the next ones are created
267 # recursively by prepending ``s``s`ksk
268 # we could of course create short sequences with multiplication
274 cached = global "church_cache"
283 .local pmc sksk, e, cm1
286 cm1 = int2church($I0)
287 e = new_expr(expS2, sksk, cm1)
293 # return native integer of a Num expression or -1 on error
299 if type != expNum goto ret1
308 # this works inplace using the fact of referential integrity of Lazy-k
312 .local pmc lhs, rhs, arg1, arg2, NUL
320 unless type == expK goto not_k
326 unless type == expK1 goto not_k1
333 unless type == expI goto not_i
339 unless type == expS goto not_s
345 unless type == expS1 goto not_s1
352 unless type == expLR goto not_lr
354 .local pmc cc, k1c, s2ik1, i, io
365 k1c = new_expr(expK1, cc, NUL)
366 s2ik1 = new_expr(expS2, i, k1c)
368 $P0 = new_expr(expLR, NUL, NUL)
369 $P1 = new_expr(expK1, $P0, NUL)
373 unless type == expS2 goto not_s2
377 $P1 = new_apply( $P0, rhs)
380 $P2 = new_apply( $P0, rhs)
384 unless type == expInc goto not_inc
389 printerr "invalid Inc of non-number\n"
399 unless type == expNum goto not_num
400 printerr "invalid apply of number\n"
403 printerr "unknown expression: '"
410 # evaluate expression
411 # this works inplace using the fact of referential integrity of Lazy-k
414 .local pmc cur, arg1, next, prev, NUL
424 if type != expA goto not_a
432 unless_null prev, isnt_nul
444 # debug helper - print string rep of expr
447 .local pmc arg1, arg2
450 unless type == expA goto not_a
460 unless type == expK goto not_k
464 unless type == expI goto not_i
468 unless type == expK1 goto not_k1
475 unless type == expI1 goto not_i1
482 unless type == expS goto not_s
486 unless type == expS1 goto not_s1
494 unless type == expS2 goto not_s2
504 unless type == expLR goto not_lr
508 unless type == expInc goto not_inc
512 unless type == expNum goto not_num
517 printerr "unknown expression: '"
524 # debug print string rep of expr
531 .include "library/dumper.pir"
537 # vim: expandtab shiftwidth=4 ft=pir: