7 More builtins
This small library of builtins provides enough functionality
to implement this top-level loop
and add more builtins from within a Worst program.
If you’re using this as a guide to implement Worst yourself,
feel free to add as many builtins as you see fit.
You may like to skim this section. It’s mostly boilerplate.
(define-builtin (symbol? s [a #t]) (cons (symbol? a) s)) |
(define-builtin (eof-object? s [a #t]) (cons (eof-object? a) s)) |
|
(define-builtin (equal? s [a #t] [b #t]) (cons (equal? a b) s)) |
|
(define-builtin (clone s [a #t]) (cons a s)) |
(define-builtin (drop s [a #t]) (cdr s)) |
(define-builtin (swap s [a #t] [b #t]) (list* b a (cddr s))) |
(define-builtin (dig s [a #t] [b #t] [c #t]) (list* c a b (cdddr s))) |
(define-builtin (bury s [a #t] [b #t] [c #t]) (list* b c a (cdddr s))) |
|
(define-builtin (and s [a #t] [b #t]) (cons (and a b) s)) |
(define-builtin (or s [a #t] [b #t]) (cons (or a b) s)) |
(define-builtin (false? s [a #t]) (cons (false? a) s)) |
(define-builtin (not s [a #t]) (cons (false? a) (cdr s))) |
|
(define-builtin (list-empty? s [a list?]) (cons (empty? a) s)) |
(define-builtin (list-length s [a list?]) (cons (length a) s)) |
(define-builtin (list-reverse s [a list?]) (cons (reverse a) (cdr s))) |
(define-builtin (list-append s [b list?] [a list?]) (cons (append a b) (cddr s))) |
(define-builtin (list-push s [v #t] [a list?]) (cons (cons v a) (cddr s))) |
(define-builtin (list-pop s [a list?]) (list* (car a) (cdr a) (cdr s))) |
(define-builtin (list-head s [a list?]) (cons (car a) s)) |
|
(define-builtin (port-read-value s [a input-port?]) (cons (read a) s)) |
(define-builtin (current-input-port s) (cons (current-input-port) s)) |
(define-builtin (current-output-port s) (cons (current-output-port) s)) |
(define-builtin (current-error-port s) (cons (current-error-port) s)) |
|
(define-builtin (open-input-file s [f string?]) |
(cons (open-input-file f) (cdr s))) |
|
«builtin-context» |
«builtin-definition» |
«builtin-racket-eval» |
7.1 Context
(define-builtin |
(current-context-root? ctx stack) |
(values ctx (cons (not (context-parent ctx)) stack))) |
(define-builtin |
(current-context-clear ctx stack) |
(values (make-context #:parent (context-parent ctx)) stack)) |
(define-builtin |
(current-context-set-code ctx stack) |
(let ([v (stack-top stack list?)]) |
(values (struct-copy context ctx [body v]) |
(cdr stack)))) |
7.2 Definitions and builtins
(define-builtin |
(definition-resolve ctx stack) |
(let ([name (stack-top stack symbol?)]) |
(values ctx (cons (context-resolve ctx name) stack)))) |
|
(define-builtin |
(definition-add ctx stack) |
(let* ([name (stack-top stack symbol?)] |
[def (stack-top (cdr stack) function?)] |
[defs (hash-set (context-definitions ctx) name def)]) |
(values (struct-copy context ctx [definitions defs]) |
(cddr stack)))) |
7.3 Using Racket code
(define-namespace-anchor *namespace-anchor*) |
(parameterize |
([current-namespace (namespace-anchor->namespace *namespace-anchor*)]) |
(namespace-set-variable-value! 'make-context make-context) |
(namespace-set-variable-value! 'context-body context-body) |
(namespace-set-variable-value! 'context-definitions context-definitions) |
(namespace-set-variable-value! 'context-children context-children) |
(namespace-set-variable-value! 'context-parent context-parent) |
(namespace-set-variable-value! 'stack-top stack-top) |
(namespace-set-variable-value! 'interp-error interp-error)) |
|
(define-builtin |
(racket-builtin s [code list?]) |
(call-with-values |
(lambda () (eval code (namespace-anchor->namespace *namespace-anchor*))) |
(case-lambda |
[([r : (Context Stack . -> . (Values Context Stack))]) |
((inst cons Builtin Stack) (Builtin r) (cdr s))] |
[_ ((inst interp-error Stack) |
'wrong-type '(lambda (stack) ... stack) code)]))) |
|
(define-builtin |
(racket-eval s [code list?]) |
(eval code (namespace-anchor->namespace *namespace-anchor*)) |
(cdr s)) |