Created
July 24, 2016 13:08
-
-
Save owainlewis/ab7d54104a9183685897ce41b34811d6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(use extras) | |
;;;; Joy in Scheme, version 0.5.2 | |
;;; System-dependent but essential code (currently for Chicken) | |
(display "sysdep...") | |
;; SYSTEM-DEPENDENT: look up Joy symbol, return () if not known | |
(define (joy-get s) | |
(let ((r (get s 'joy))) | |
(if r r '()))) | |
;; SYSTEM-DEPENDENT: set value of Joy symbol | |
(define (joy-set! s v) (put! s 'joy v)) | |
;; SYSTEM-DEPENDENT: report error (accepts multiple arguments) | |
(define (joy-error . s) (error "joy code" (apply string-append s))) | |
;; SYSTEM-DEPENDENT: return an unused (or at least unusual) symbol | |
(define (joy-gensym) (gensym)) | |
;;; The user interface | |
(display "ui...") | |
;; User interface for running Joy code (supports autoput) | |
(define-syntax joy (syntax-rules () | |
((joy . code) (joy-exec-autoput 'code)))) | |
;; User interface for defining Joy symbols | |
(define-syntax joy-define (syntax-rules () | |
((joy-define name . code) (joy-set! 'name 'code)))) | |
;; User interface for defining Joy modules | |
(define-syntax joy-module (syntax-rules () | |
((joy-module name . members) (joy-module-set! 'name 'members)))) | |
;;; The main Joy interpreter | |
(display "main...") | |
;; The Joy stack | |
(define joy-stack '()) | |
;; Write a list without its outer parentheses | |
(define (joy-write-list q) | |
(cond | |
((null? q) (if #f #f)) | |
((null? (cdr q)) (write (car q)) (newline)) | |
((pair? q) | |
(write (car q)) | |
(display #\space) | |
(joy-write-list (cdr q))) | |
(else (display ". ") (write q)))) | |
;; The Joy undefined-error flag | |
(define joy-undeferror #t) | |
;; The Joy autoput code (1 = put, 2 = put stack, else nothing) | |
(define joy-autoput 2) | |
;; Push an object on the Joy stack | |
(define (joy-push! x) (set! joy-stack (cons x joy-stack))) | |
;; Pop an object from the Joy stack | |
(define (joy-pop!) | |
(if (null? joy-stack) (joy-error "Stack underflow")) | |
(let ((x (car joy-stack))) | |
(set! joy-stack (cdr joy-stack)) | |
x)) | |
;; Push a list (which must be freshly consed) onto the Joy stack | |
(define (joy-push-list! x) | |
(set! joy-stack | |
(append (reverse x) joy-stack))) | |
;; Joy predicate for truth | |
(define (joy-true? x) | |
(cond | |
((number? x) (not (zero? x))) | |
((eq? x #f) #f) | |
(else #t))) | |
;; Execute a list as Joy code | |
(define (joy-exec c) (for-each joy-exec-one c)) | |
(define (joy-exec-autoput c) | |
(joy-exec c) | |
(cond | |
((eqv? joy-autoput 1) | |
(write (car joy-stack)) (newline)) | |
((eqv? joy-autoput 2) | |
(joy-write-list joy-stack)))) | |
;; Lookup Joy symbol | |
(define (joy-lookup i) | |
(let ((p (joy-get i))) | |
(and | |
(null? p) | |
joy-undeferror | |
(joy-error "Undefined symbol " (symbol->string i))) | |
p)) | |
;; Invoke a symbol or push a datum | |
(define (joy-exec-one i) | |
(if (symbol? i) | |
(joy-invoke (joy-lookup i)) | |
(joy-push! i))) | |
;; Execute a Joy quotation or call a Scheme procedure | |
(define (joy-invoke p) | |
(cond | |
((procedure? p) (p)) | |
((pair? p) (joy-exec p)) | |
((null? p) #f) | |
(else (joy-error "Attempt to invoke non-procedure")))) | |
;;; Module definition | |
(display "modules...") | |
;; A-list for alphatizing definition names | |
(define joy-alpha '()) | |
(define joy-modstring "unknown:") | |
;; Alphatize a symbol | |
(define (joy-alphatize mode s) ; convert symbol s depending on mode | |
(case mode | |
((private) (gensym)) | |
((public) (string->symbol (string-append | |
joy-modstring | |
(symbol->string s)))) | |
((exported) s) | |
(else (joy-error (symbol-string mode) " mode unknown")))) | |
;; Add a redefinition to joy-alpha | |
(define (joy-redef! username truename) | |
(set! joy-alpha (cons (cons username truename) joy-alpha))) | |
;; Analyze the definitions and build up joy-alpha | |
(define (joy-analyze! mode defs) | |
(cond | |
((null? defs) (if #f #f)) | |
((symbol? (car defs)) (joy-analyze! (car defs) (cdr defs))) | |
(else (joy-redef! (cadar defs) (joy-alphatize mode (cadar defs))) | |
(joy-analyze! mode (cdr defs))))) | |
;; Substitute based on joy-alpha | |
(define (joy-subst t) | |
(let ((a (assq t joy-alpha))) | |
(if a (cdr a) | |
(if (pair? t) | |
(cons (joy-subst (car t)) (joy-subst (cdr t))) | |
t)))) | |
;; Install amodule definition | |
(define (joy-install! def) | |
(if (pair? def) (joy-set! (cadr def) (cddr def)))) | |
;; Install module | |
(define (joy-module-set! name members) | |
(set! joy-alpha '()) | |
(set! joy-modstring (string-append (symbol->string name) ":")) | |
(joy-analyze! 'public members) | |
(for-each joy-install! (joy-subst members))) | |
;;; Macros for defining Joy primitives | |
(display "macros...") | |
;; Push one result | |
(define-syntax joy-prim (syntax-rules () | |
((joy-prim (name . vars) . code) | |
(joy-set! 'name (lambda () | |
(joy-let vars (joy-push! (begin . code)))))))) | |
;; Push a freshly consed list of results | |
(define-syntax joy-prim-list (syntax-rules () | |
((joy-prim-list (name . vars) . code) | |
(joy-set! 'name (lambda () | |
(joy-let vars (joy-push-list! (begin . code)))))))) | |
;; Push nothing | |
(define-syntax joy-prim-void (syntax-rules () | |
((joy-prim-void (name . vars) . code) | |
(joy-set! 'name (lambda () | |
(joy-let vars (begin . code))))))) | |
;; Set up appropriate pops | |
(define-syntax joy-let (syntax-rules () | |
((joy-let () . body) | |
(begin . body)) | |
((joy-let (x1 x2 ...) . body) | |
(joy-let (x2 ...) (let ((x1 (joy-pop!))) . body))))) | |
;;; Joy non-combinator primitives | |
(display "prims...") | |
;; Simple niladic primitives | |
(joy-prim (false) #f) | |
(joy-prim (true) #t) | |
(joy-prim (maxint) #f) | |
(joy-prim (setsize) #f) | |
(joy-prim (stack) joy-stack) | |
(joy-prim (autoput) joy-autoput) | |
(joy-prim (undeferror) (if joy-undeferror 1 0)) | |
(joy-prim (stdin) (current-input-port)) | |
(joy-prim (stdout) (current-output-port)) | |
;; Simple operators | |
(joy-prim-void (id) #f) | |
(joy-prim-list (dup x) (list x x)) | |
(joy-prim-list (swap x y) (list y x)) | |
(joy-prim-list (rollup x y z) (list z x y)) | |
(joy-prim-list (rolldown x y z) (list y z x)) | |
(joy-prim-list (rotate x y z) (list z y x)) | |
(joy-prim (popd y z) z) | |
(joy-prim-list (dupd y z) (list y y z)) | |
(joy-prim-list (swapd x y z) (list y x z)) | |
(joy-prim-list (rollupd x y z w) (list z x y w)) | |
(joy-prim-list (rolldownd x y z w) (list y z x w)) | |
(joy-prim-list (rotated x y z w) (list z y x w)) | |
(joy-prim-void (pop x) #f) | |
(joy-prim (choice b t f) (if b t f)) | |
;; Logical primitives (FIXME: don't handle sets yet) | |
(joy-prim (or x y) (or x y)) | |
(joy-prim (xor x y) (eq? x (not y))) | |
(joy-prim (and x y) (and x y)) | |
(joy-prim (not x) (not x)) | |
;; Arithmetic primitives | |
(joy-prim (+ i j) (+ i j)) | |
(joy-prim (- i j) (- i j)) | |
(joy-prim (* i j) (* i j)) | |
(joy-prim (/ i j) (/ i j)) | |
(joy-prim (rem i j) (remainder i j)) | |
(joy-prim (div i j) (list (trunc (/ i j)) (remainder i j))) | |
(joy-prim (sign i) (if (negative? i) -1 (if (zero? i) 0 1))) | |
(joy-prim (neg i) (- i)) | |
(joy-prim (ord c) (char->integer c)) | |
(joy-prim (chr i) (integer->char i)) | |
(joy-prim (abs n) (abs n)) | |
(joy-prim (pred n) (- n 1)) | |
(joy-prim (succ n) (+ n 1)) | |
(joy-prim (max m n) (max m n)) | |
(joy-prim (min m n) (max m n)) | |
;; Transcendental primitives | |
(joy-prim (acos f) (acos f)) | |
(joy-prim (asin f) (asin f)) | |
(joy-prim (atan f) (atan f)) | |
(joy-prim (atan2 f g) (atan f g)) | |
(joy-prim (ceil f) (ceiling f)) | |
(joy-prim (cos f) (cos f)) | |
(joy-prim (cosh f) (cosh f)) ; SYSTEM-DEPENDENT | |
(joy-prim (exp f) (exp f)) | |
(joy-prim (floor f) (floor f)) | |
(joy-prim (log f) (log f)) | |
(joy-prim (log10 f) (/ (log f) (log 10))) | |
(joy-prim (pow f g) (expt f g)) | |
(joy-prim (sin f) (sin f)) | |
(joy-prim (sinh f) (sinh f)) ; SYSTEM-DEPENDENT | |
(joy-prim (sqrt f) (sqrt f)) | |
(joy-prim (tan f) (tan f)) | |
(joy-prim (tanh f) (tanh f)) ; SYSTEM-DEPENDENT | |
(joy-prim (trunc f) (truncate f)) | |
;; Date primitives are system-dependent and not implemented | |
;; String/numeric conversion primitives | |
(joy-prim (strtol s i) (string->number s i)) | |
(joy-prim (strtod s) (string-number s)) | |
(joy-prim (format n i) (number->string n i)) ; different from C-Joy | |
; formatf not implemented | |
;; Random number primitives are system-dependent and not implemented | |
;; Simple I/O primitives | |
(joy-prim (get) (read)) | |
(joy-prim-void (put x) (write x)) | |
(joy-prim-void (putchar c) (display (integer->char c))) | |
(joy-prim-void (putchars x) (display x)) | |
(joy-prim-void (include s) (load (string-append s ".ss"))) ; SYSTEM-DEPENDENT | |
;; Stream primitives | |
(joy-prim-void (fclose f) | |
(if (input-port? f) (close-input-port f) (close-output-port f))) | |
(joy-prim (eof x) (eof-object? x)) ; different from C-Joy | |
(joy-prim (fgetch) (read-char (car joy-stack))) | |
(joy-prim (fopen p m) | |
(cond | |
((string-equal m "r") (open-input-port p)) | |
((string-equal m "w") (open-output-port p)) | |
(else (joy-error "Invalid fopen mode " m)))) | |
(joy-prim (fput x) (write x (car joy-stack))) | |
(joy-prim (fputch c) (display c (car joy-stack))) | |
(joy-prim (fputchars s) (display s (car joy-stack))) | |
;; Replace the stack with its topmost member | |
(joy-prim-void (unstack x) (set! joy-stack x)) | |
;; Cons element onto aggregate | |
(joy-prim (cons x a) | |
(if (string? a) | |
(string-append (string x) a) | |
(cons x a))) | |
;; Swapped cons | |
(joy-prim (swons a x) | |
(if (string? a) | |
(string-append (string x) a) | |
(cons x a))) | |
;; Get first element | |
(joy-prim (first a) | |
(if (string? a) | |
(string-ref a 0) | |
(car a))) | |
;; Get remaining elements | |
(joy-prim (rest a) | |
(if (string? a) | |
(substring a 1 (string-length a)) | |
(cdr a))) | |
;; FIXME: compare not implemented | |
;; Element of aggregate at location (zero-based) | |
(joy-prim (at a i) | |
(if (string? a) | |
(string-ref a i) | |
(list-ref a i))) | |
;; Inverse of at | |
(joy-prim (of i a) | |
(if (string? a) | |
(string-ref a i) | |
(list-ref a i))) | |
;; Size of aggregate | |
(joy-prim (size a) | |
(if (string? a) | |
(string-length a) | |
(list-length a))) | |
;; FIXME: opcase not implemented | |
;; FIXME: case not implemented | |
;; Uncons an aggregate | |
(joy-prim-list (uncons a) | |
(if (string? a) | |
(list (string-ref a 0) (substring a 0 (string-length a))) | |
(list (car a) (cdr a)))) | |
;; Uncons an aggregate and swap | |
(joy-prim-list (unswons a) | |
(if (string? a) | |
(list (substring a 0 (string-length a)) (string-ref a 0)) | |
(list (cdr a) (car a)))) | |
;; Drop first n elements of an aggregate | |
(joy-prim (drop a n) | |
(if (string? a) | |
(substring a n (string-length a)) | |
(list-tail a n))) | |
;; Take first n elements of aggregate | |
(joy-prim (take a n) | |
(if (string? a) | |
(substring a 0 n) | |
(reverse (joy-reversed-head a n)))) | |
(define (joy-reversed-head a n) | |
(if (or (zero? n) (null? a)) | |
'() | |
(cons (car a) (reversed-head (cdr a) (- n 1))))) | |
;; Concatenate aggregates | |
(joy-prim (concat s t) | |
(if (string? s) (string-append s t) (append s t))) | |
;; Concatenate aggregates with an element in the middle | |
(joy-prim (enconcat x s t) | |
(if (string? s) | |
(string-append s (string x) t) | |
(append s (list x) t))) | |
;; Symbol/string conversion | |
(joy-prim (name s) (symbol->string s)) | |
(joy-prim (intern s) (string->symbol s)) | |
(joy-prim (body u) (joy-get u)) | |
;; Null aggregate or zero number | |
(joy-prim (null x) | |
(cond | |
((string? x) (zero? (string-length x))) | |
((null? x) #t) | |
(else (zero? x)))) | |
;; Small aggregate or zero or one number | |
(joy-prim (small x) | |
(cond | |
((string? x) (<= (string-length x) 1)) | |
((null? x) #t) | |
((pair? x) (null? (cdr x))) | |
(else (<= 0 x 1)))) | |
;; Relational operators | |
(joy-prim (= x y) | |
(cond | |
((symbol? x) | |
(string=? (symbol->string x) (symbol->string y))) | |
((string? x) | |
(string=? x y)) | |
(else (= x y)))) | |
(joy-prim (!= x y) | |
(cond | |
((symbol? x) | |
(not (string=? (symbol->string x) (symbol->string y)))) | |
((string? x) | |
(not (string=? x y))) | |
(else (not (= x y))))) | |
(joy-prim (< x y) | |
(cond | |
((symbol? x) | |
(string<? (symbol->string x) (symbol->string y))) | |
((string? x) | |
(string<? x y)) | |
(else (= x y)))) | |
(joy-prim (> x y) | |
(cond | |
((symbol? x) | |
(string>? (symbol->string x) (symbol->string y))) | |
((string? x) | |
(string>? x y)) | |
(else (> x y)))) | |
(joy-prim (<= x y) | |
(cond | |
((symbol? x) | |
(string<=? (symbol->string x) (symbol->string y))) | |
((string? x) | |
(string<=? x y)) | |
(else (<= x y)))) | |
(joy-prim (>= x y) | |
(cond | |
((symbol? x) | |
(string>=? (symbol->string x) (symbol->string y))) | |
((string? x) | |
(string>=? x y)) | |
(else (>= x y)))) | |
;; Tree equality | |
(joy-prim (equal t u) (equal? t u)) | |
;; Membership | |
(joy-prim (has a x) (if (string? a) (joy-stringmem a x) (memq a x))) | |
(joy-prim (in x a) (if (string? a) (joy-stringmem a x) (memq a x))) | |
(define (joy-stringmem s c) | |
(define (try i r) | |
(cond | |
((zero? r) #f) | |
((eqv? c (string-ref s i)) #t) | |
(else (stringmem (+ i 1) (- r 1))))) | |
(try 0 (string-length s))) | |
;; Type predicates | |
(joy-prim (integer x) (integer? x)) | |
(joy-prim (char x) (character? x)) | |
(joy-prim (logical x) (boolean? x)) | |
(joy-prim (set x) (list? x)) | |
(joy-prim (string x) (string? x)) | |
(joy-prim (list x) (or (pair? x) (null? x))) | |
(joy-prim (leaf x) (not (or (pair? x) (null? x)))) | |
(joy-prim (float x) (real? x)) | |
(joy-prim (user x) (and (symbol? x) (pair? (joy-get x)))) | |
(joy-prim (file x) (or (input-port? x) (output-port? x))) | |
;; Environment manipulation | |
(joy-prim-void (setundeferror n) (set! joy-undeferror (joy-true? n))) | |
(joy-prim-void (setautoput n) (set! joy-autoput n)) | |
;;; Joy combinator primitives | |
(display "combs...") | |
;; Evaluate thunk on a stabilized stack | |
(define (joy-stable p) | |
(let* | |
((s joy-stack) | |
(r (p))) | |
(set! joy-stack s) | |
r)) | |
;; Execute Joy quotation stably, return top of stack | |
(define (joy-stable-exec p) (joy-stable (lambda () (joy-exec p) (joy-pop!)))) | |
;; Return truth value of stabilized execution | |
(define (joy-yields-true? p) (joy-true? (joy-stable-exec p))) | |
;; Simple combinators | |
(joy-prim-void (i x) (joy-exec x)) | |
(joy-prim-void (x) (joy-exec (car joy-stack))) | |
(joy-prim (dip x p) (joy-exec p) x) | |
;; app1 app11 app12 | |
;; Construct combinator | |
(joy-prim-void (construct p1 p2) | |
(joy-stable (lambda () | |
(joy-exec p1) | |
(for-each (lambda (q) (joy-exec q) (joy-pop!)) p2)))) | |
;; N-ary combinators | |
(joy-prim (nullary p) (let ((r (joy-stable-exec p))) r)) | |
(joy-prim (unary p) (let ((r (joy-stable-exec p))) (joy-pop!) r)) | |
(joy-prim (binary p) (let ((r (joy-stable-exec p))) (joy-pop!) (joy-pop!) r)) | |
(joy-prim (ternary p) (let ((r (joy-stable-exec p))) (joy-pop!) (joy-pop!) (joy-pop!) r)) | |
;; Execute unary combinator twice | |
(joy-prim-list (unary2 x1 x2 p) | |
(let* | |
((r1 (begin (joy-push! x1) (joy-exec p) (joy-pop!))) | |
(r2 (begin (joy-push! x2) (joy-exec p) (joy-pop!)))) | |
(list r1 r2))) | |
(joy-set! 'app2 (joy-get 'unary2)) | |
;; Execute unary combinator three times | |
(joy-prim (unary3 x1 x2 x3 p) | |
(let* | |
((r1 (begin (joy-push! x1) (joy-exec p) (joy-pop!))) | |
(r2 (begin (joy-push! x2) (joy-exec p) (joy-pop!))) | |
(r3 (begin (joy-push! x3) (joy-exec p) (joy-pop!)))) | |
(list r1 r2 r3))) | |
(joy-set! 'app3 (joy-get 'unary3)) | |
;; Execute unary combinator four times | |
(joy-prim (unary4 x1 x2 x3 x4 p) | |
(let* | |
((r1 (begin (joy-push! x1) (joy-exec p) (joy-pop!))) | |
(r2 (begin (joy-push! x2) (joy-exec p) (joy-pop!))) | |
(r3 (begin (joy-push! x3) (joy-exec p) (joy-pop!))) | |
(r4 (begin (joy-push! x4) (joy-exec p) (joy-pop!)))) | |
(list r1 r2 r3 r4))) | |
(joy-set! 'app4 (joy-get 'unary4)) | |
;; Cleave combinator | |
(joy-prim-list (cleave p1 p2) | |
(let* | |
((r1 (joy-stable-exec p1)) | |
(r2 (joy-stable-exec p2))) | |
(joy-pop!) | |
(list r1 r2))) | |
;; Conditional combinators | |
(joy-prim-void (branch p t e) | |
(if (joy-true? p) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (ifte p t e) | |
(if (joy-yields-true? p) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (ifinteger x t e) (if (integer? x) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (ifchar x t e) (if (character? x) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (iflogical x t e) (if (boolean? x) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (ifset x t e) (if (list? x) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (ifstring x t e) (if (string? x) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (iflist x t e) | |
(if (or (pair? x) (null? x)) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (iffloat x t e) (if (real? x) (joy-exec t) (joy-exec e))) | |
(joy-prim-void (iffile x t e) | |
(if (or (input-port? x) (output-port? x)) (joy-exec t) (joy-exec e))) | |
;; Joy's version of cond | |
(joy-prim-void (cond p) (joy-cond p)) | |
(define (joy-cond p) | |
(cond | |
((null? p) #f) | |
((null? (cdr p)) (joy-exec (car p))) | |
((joy-yields-true? (caar p)) (joy-exec (cdar p))) | |
(else (joy-cond (cdr p))))) | |
;; While-do combinator | |
(joy-prim-void (while p q) (joy-while p q)) | |
(define (joy-while p q) | |
(when (joy-yields-true? p) | |
(joy-exec q) | |
(joy-while p q))) | |
;; Linear recursion combinator | |
(joy-prim-void (linrec p t r1 r2) (joy-linrec p t r1 r2)) | |
(define (joy-linrec p t r1 r2) | |
(cond | |
((joy-yields-true? p) (joy-exec t)) | |
(else (joy-exec r1) (joy-linrec p t r1 r2) (joy-exec r2)))) | |
;; Tail recursion combinator | |
(joy-prim-void (tailrec p t r) (joy-tailrec p t r)) | |
(define (joy-tailrec p t r) | |
(cond | |
((joy-yields-true? p) (joy-exec t)) | |
(else (joy-exec r) (joy-tailrec p t r)))) | |
;; Binary recursion combinator | |
(joy-prim-void (binrec p t r1 r2) (joy-binrec p t r1 r2)) | |
(define (joy-binrec p t r1 r2) | |
(cond | |
((joy-yields-true? p) (joy-exec t)) | |
(else (joy-exec r1) | |
(let* ((n2 (joy-pop!)) (n1 (joy-pop!))) | |
(joy-push! n1) | |
(joy-binrec p t r1 r2) | |
(joy-push! n2) | |
(joy-binrec p t r1 r2) | |
(joy-exec r2))))) | |
;; General recursion combinator | |
(joy-prim-void (genrec p t r1 r2) | |
(cond | |
((joy-yields-true? p) (joy-exec t)) | |
(else | |
(joy-exec r1) | |
(joy-push! (list p t r1 r2 'genrec)) | |
(joy-exec r2)))) | |
;; FIXME: condlinrec | |
(joy-prim-void (step a p) | |
(if (string? a) | |
(joy-step-string a p 0 (string-length a)) | |
(joy-step-list a p))) | |
(define (joy-step-string s p i n) | |
(cond | |
((zero? n) #f) | |
(else | |
(joy-stable (lambda () | |
(joy-push! (string-ref s i)) | |
(joy-exec p))) | |
(joy-step-string s p (+ i 1) (- n 1))))) | |
(define (joy-step-list a p) | |
(for-each (lambda (e) | |
(joy-stable (lambda () | |
(joy-push! e) | |
(joy-exec p)))) a)) | |
;; FIXME: fold | |
;; Map aggregate through quotation | |
(define joy-map-result '()) | |
(joy-prim-void (map a p) | |
(cond | |
((string? a) | |
(let ((len (string-length a))) | |
(set! joy-map-result (make-string len)) | |
(joy-map-string! a p 0 len))) | |
(else | |
(set! joy-map-result '()) | |
(joy-map-list! a p))) | |
(joy-push! joy-map-result)) | |
(define (joy-map-string! s p i n) | |
(cond | |
((zero? n) #f) | |
(else | |
(string-set! joy-map-result i | |
(joy-stable (lambda () | |
(joy-push! (string-ref s i)) | |
(joy-exec p)))) | |
(joy-map-string! s p (+ i 1) (- n 1))))) | |
(define (joy-map-list! a p) | |
(cond | |
((null? a) #f) | |
(else | |
(set! joy-map-result (cons (joy-stable (lambda () | |
(joy-push! (car a)) | |
(joy-exec p))) joy-map-result)) | |
(joy-map-list! (cdr a) p)))) | |
;; Execute N times combinator | |
(joy-prim-void (times n p) (joy-times n p)) | |
(define (joy-times n p) | |
(cond | |
((zero? n) #f) | |
(else (joy-exec p) (joy-times (- n 1) p)))) | |
;; Infra-stack combinator | |
(joy-prim (infra l p) | |
(let ((s joy-stack)) | |
(set! joy-stack l) | |
(joy-exec p) | |
(let ((r joy-stack)) | |
(set! joy-stack s) | |
r))) | |
;; FIXME: filter, split, some, all | |
;; FIXME: treestep, treerec, treegenrec | |
;; FIXME: need to do something for manual (doc strings?) | |
;; System access is system-dependent and not included here. | |
;;; The Joy integrator | |
(display "integrator...") | |
(joy-prim-void (integrate words) | |
(for-each (lambda (w) | |
(joy-set! w (joy-integrate w '()))) words)) | |
(define (joy-integrate word parents) | |
(cond | |
((memq word parents) word) | |
((symbol? word) (joy-integrate-sym word parents)) | |
((pair? word) (cons | |
(joy-integrate (car word) parents) | |
(joy-integrate (cdr word) parents))) | |
(else word))) | |
(define (joy-integrate-sym s parents) | |
(let ((v (joy-get s))) | |
(if (pair? v) | |
(joy-integrate v (cons s parents)) | |
s))) | |
;;; REPL | |
(display "repl...") | |
;; Read-exec-print loop | |
(define (joy-repl) | |
(joy-exec-autoput (read)) | |
(joy-repl)) | |
;;; Done | |
(display "done | |
") | |
(joy-repl) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment