;; 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