git @ Cat's Eye Technologies Robin / 0.3 stdlib / eval.robin
0.3

Tree @0.3 (Download .tar.gz)

eval.robin @0.3raw · history · blame

;'<<SPEC'

### `eval` ###

    -> Tests for functionality "Interpret core Robin Program"

`eval` evaluates its first argument to obtain an environment, then
evaluates its second argument to obtain an S-expression; it then
evaluates that S-expression in the given environment.

    | (define literal (macro (s a e) (head a)))
    | (define env (macro (s a e) e))
    | (display
    |   (eval (env) (literal
    |     (prepend (literal a)
    |               (prepend (literal b) ())))))
    = (a b)

    | (define literal (macro (s a e) (head a)))
    | (display
    |   (eval () (literal
    |     (prepend (literal a)
    |               (prepend (literal b) ())))))
    ? uncaught exception: (unbound-identifier prepend)

Something fairly complicated that uses `bind`...?

    | (define literal (macro (s a e) (head a)))
    | (define bind (macro (self args env)
    |   (eval
    |     (prepend (prepend (head args) (prepend (eval env (head (tail args))) ())) env)
    |     (head (tail (tail args))))))
    | (display
    |   (bind bindings (prepend
    |                    (prepend (literal same) (prepend equal? ()))
    |                    (prepend
    |                      (prepend (literal x) (prepend #f ()))
    |                      ()))
    |     (eval bindings (literal (same x x)))))
    = #t

If two bindings for the same identifier are supplied in the environment
alist passed to `eval`, the one closer to the front of the alist takes
precedence.

    | (define literal (macro (s a e) (head a)))
    | (define bind (macro (self args env)
    |   (eval
    |     (prepend (prepend (head args) (prepend (eval env (head (tail args))) ())) env)
    |     (head (tail (tail args))))))
    | (display
    |   (bind bindings (prepend
    |                    (prepend (literal foo) (prepend (literal yes) ()))
    |                    (prepend
    |                       (prepend (literal foo) (prepend (literal no) ()))
    |                       ()))
    |     (eval bindings (literal foo))))
    = yes

`eval` will happily use whatever type of value you like as the
environment, however, subsequent evaluation will fail when it
tries to look up things in that environment.

    | (define literal (macro (s a e) (head a)))
    | (display
    |   (eval 103 (literal
    |     (prepend (literal a)
    |              (prepend (literal b) ())))))
    ? uncaught exception: (expected-env-alist 103)

Evaluation expects the contents of the list which makes up the
environment to be two-element lists.

    | (define literal (macro (s a e) (head a)))
    | (display
    |   (eval (prepend #f ()) (literal
    |     (prepend (literal a)
    |              (prepend (literal b) ())))))
    ? uncaught exception: (expected-env-entry #f)

Evaluation expects the head of each sublist in the list which makes up the
environment to be a symbol.

    | (define literal (macro (s a e) (head a)))
    | (display
    |   (eval (prepend (prepend 7 (prepend #f ())) ()) (literal
    |     (prepend (literal a)
    |              (prepend (literal b) ())))))
    ? uncaught exception: (expected-symbol 7)

`eval` expects exactly two arguments.

    | (display
    |   (eval))
    ? uncaught exception: (illegal-arguments ())

    | (display
    |   (eval 4 5 6))
    ? uncaught exception: (illegal-arguments (4 5 6))

'<<SPEC'