precursor language interpreter

Select a sample program from the menu below to edit and run it! Information about the Precursor language and this project (github)

;; A quick tour of Precursor. ; ; Precursor is a simple language. ; Every program is one expression so ; programs of any use will probably start ; with a *recursive let-binding.* (letrec ( ; Begin list of bindings. ; Name Definition ( five 5 ) ; Functions consist of a '\', a list of 0 ; or more parameter names, and a body ; expression. ( id (\ (x) x) ) ; The above binds a function term to the ; name 'id'. ; Note that 'id' can see itself and any ; other term defined in this 'letrec' - ; this is how recursive functions are ; supported. ; Functions are *not* values in Precursor. ; Instead, think of a \ as a verb meaning ; "pop these arguments off the stack." (my-square-function (\ (n) (op:mul n n))) ; A name starting with 'op:' denotes an ; *operation* performed by the underlying ; virtual machine. The language itself ; prescribes no specific operations, but ; this instance has been equipped with a ; number of basic arithmetic and string ; manipulation operations, which you may ; see used throughout the various examples. ; Operations have a few caveats for safety, ; namely: ; - they are **not** first-class. You may ; only reference an op when invoking it ; with its arguments. ; Eg, '(op:mul 2 3)' is good, ; '(foo op:mul)' is always wrong ; - its arguments must be *fully evaluated* ; - operations consume and produce fully ; evaluated terms so you may nest them, ; eg '(op:add (op:mul 2 3) 5)' ; Okay on to something fun. (twenty-five (let _five ((? id) 5) ; complex term (let _five (? _five) ; fully evaluated ((? my-square-function) _five)))) ; The '?' operator *resumes* a *suspended* ; term. Complex, non-value expressions - ; such as a function definition, application, ; let-binding, or control flow expression - ; may be suspended with the '!' operator. ; All names bound let/letrec definitions are ; suspended automatically. ; 'twenty-five' above is a complex expression ; which does not execute until is resumed below. ; I don't want to overwhelm you so I will ; leave it to the other examples to show ; you 'shift' and 'reset'. ) ; end bindings ; Next is the letrec body expression. ; All symbols defined above are visible in ; the body below, which is what the letrec will ; evaluate to. (let _25 (? twenty-five) (let _625 ((? my-square-function) _25) (op:writeln (op:concat (op:num->str _25) (op:concat " squared is " (op:concat (op:num->str _625) ".")))) )) ; end letrec body ) ; end letrec