about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/61a-pages/Lib/apl-meta.scm
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/61a-pages/Lib/apl-meta.scm
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/61a-pages/Lib/apl-meta.scm')
-rw-r--r--js/games/nluqo.github.io/~bh/61a-pages/Lib/apl-meta.scm260
1 files changed, 260 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/61a-pages/Lib/apl-meta.scm b/js/games/nluqo.github.io/~bh/61a-pages/Lib/apl-meta.scm
new file mode 100644
index 0000000..8147708
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/61a-pages/Lib/apl-meta.scm
@@ -0,0 +1,260 @@
+;;; apl-meta.scm     APL version of metacircular evaluator.
+
+;;; SETTING UP THE ENVIRONMENT
+
+;;; APL primitives aren't part of the environment.  They are not subject
+;;; to redefinition, for example.  They are kept in a separate list.  So
+;;; the initial environment is empty.  But define! only works if there is
+;;; a non-empty environment, so we fake something.
+
+(define the-global-environment '())
+
+;;; INITIALIZATION AND DRIVER LOOP
+
+;;; The following code initializes the machine and starts the APL
+;;; system.  You should not call it very often, because it will clobber
+;;; the global environment, and you will lose any definitions you have
+;;; accumulated.
+
+(define (initialize-apl)
+  (set! the-global-environment
+  	(extend-environment '(no-name) '(no-value) '()))
+  (set! apl-operators
+    (list (make-scalar-op '+ (lambda (x) x) +)
+	  (make-scalar-op '- - -)
+	  (make-scalar-op '*
+		 	  (lambda (x) (cond ((< x 0) -1) ((= x 0) 0) (else 1)))
+		 	  *)
+	  (make-scalar-op '% / /)
+	  (make-scalar-op 'bar abs rem)
+	  (make-scalar-op '= error (apl-pred2 =))
+	  (make-scalar-op '< error (apl-pred2 <))
+	  (make-scalar-op '> error (apl-pred2 >))
+	  (make-op '/ error compress)
+	  (make-op 'iota iota error)
+	  (make-op 'rho shape reshape)
+	  (make-op 'comma ravel cat)
+	  (make-op 'gets error 'set!)))
+  (apl-loop))
+
+;;; APPLYING PRIMITIVE PROCEDURES
+
+;;; The mechanism for applying primitive procedures is somewhat
+;;; different from the one given in the course notes.  We can recognize
+;;; primitive procedures (which are all inherited from Scheme) by asking
+;;; Scheme if the object we have is a Scheme procedure.
+
+(define (primitive-procedure? p)
+  (applicable? p))
+
+;;; To apply a primitive procedure, we ask the underlying Scheme system
+;;; to perform the application.  (Of course, an implementation on a
+;;; low-level machine would perform the application in some other way.)
+
+(define (apply-primitive-procedure p args)
+  (apply p args))
+
+
+;;; Now for the code from the book!!!
+
+
+;;; Section 4.1.1
+
+(define (mini-eval exp env)
+  (cond ((self-evaluating? exp) exp)
+        ((variable? exp) (lookup-variable-value exp env))
+        ((assignment? exp) (eval-assignment exp env))
+        ((application? exp)
+         (mini-apply (mini-eval (operator exp) env)
+                     (list-of-values (operands exp) env)
+		     env))
+        (else (error "Unknown expression type -- MINI-EVAL" exp))))
+
+(define (mini-apply procedure arguments env)
+  (cond ((primitive-procedure? procedure)
+         (apply-primitive-procedure procedure arguments))
+        ((compound-procedure? procedure)
+         (eval-sequence (procedure-body procedure)
+                        (extend-environment
+                         (parameters procedure)
+                         arguments
+                         env)))
+        (else
+         (error "Unknown procedure type -- MINI-APPLY" procedure))))
+
+(define (list-of-values exps env)
+  (cond ((no-operands? exps) '())
+        (else (cons (mini-eval (first-operand exps) env)
+                    (list-of-values (rest-operands exps)
+                                    env)))))
+
+(define (eval-sequence exps env)
+  (cond ((last-exp? exps) (mini-eval (first-exp exps) env))
+        (else (mini-eval (first-exp exps) env)
+              (eval-sequence (rest-exps exps) env))))
+
+(define (eval-assignment exp env)
+  (let ((new-value (mini-eval (assignment-value exp) env)))
+    (set-variable-value! (assignment-variable exp)
+                         new-value
+                         env)
+    new-value))
+
+;;; Section 4.1.2 -- Representing expressions
+
+;;; numbers
+
+(define (self-evaluating? exp) (number? exp))
+
+;;; variables
+
+(define (variable? exp) (symbol? exp))
+
+;;; assignment
+
+(define (assignment? exp)
+  (if (not (pair? exp))
+      #f
+      (eq? (car exp) 'set!)))
+
+(define (assignment-variable exp) (cadr exp))
+
+(define (assignment-value exp) (caddr exp))
+
+;;; sequences
+
+(define (last-exp? seq) (null? (cdr seq)))
+
+(define (first-exp seq) (car seq))
+
+(define (rest-exps seq) (cdr seq))
+
+;;; procedure applications
+
+(define (application? exp)
+  (if (not (pair? exp))
+      #f
+      (procedure? (car exp))))
+
+(define (procedure? exp)
+  (or (applicable? exp) (compound-procedure? exp)))
+
+(define (operator app) (car app))
+
+(define (operands app) (cdr app))
+
+(define (no-operands? args) (null? args))
+
+(define (first-operand args) (car args))
+
+(define (rest-operands args) (cdr args))
+
+;;; Representation of procedure objects
+
+(define (make-procedure lambda-exp env)
+  (list 'procedure lambda-exp env))
+
+(define (compound-procedure? proc)
+  (if (not (pair? proc))
+      #f
+      (eq? (car proc) 'procedure)))
+
+(define (parameters proc) (cadr (cadr proc)))
+
+(define (procedure-body proc) (cddr (cadr proc)))
+
+(define (procedure-environment proc) (caddr proc))
+
+;;; Section 4.1.3
+
+;;; Operations on environments
+
+(define (lookup-variable-value var env)
+  (if (assq var apl-operators)
+      var
+      (let ((b (binding-in-env var env)))
+	(if (found-binding? b)
+	    (binding-value b)
+	    (error "Unbound variable" var)))))
+
+(define (binding-in-env var env)
+  (if (no-more-frames? env)
+      no-binding
+      (let ((b (binding-in-frame var (first-frame env))))
+        (if (found-binding? b)
+            b
+            (binding-in-env var (rest-frames env))))))
+
+(define (extend-environment variables values base-env)
+  (adjoin-frame (make-frame variables values) base-env))
+
+(define (set-variable-value! var val env)
+  (let ((b (binding-in-env var env)))
+    (if (found-binding? b)
+        (set-binding-value! b val)
+        (error "Unbound variable" var))))
+
+(define (define-variable! var val env)
+  (let ((b (binding-in-frame var (first-frame env))))
+    (if (found-binding? b)
+        (set-binding-value! b val)
+        (set-first-frame!
+          env
+          (adjoin-binding (make-binding var val)
+                          (first-frame env))))))
+
+;;; Representing environments
+
+(define (first-frame env) (car env))
+
+(define (rest-frames env) (cdr env))
+
+(define (no-more-frames? env) (null? env))
+
+(define (adjoin-frame frame env) (cons frame env))
+
+(define (set-first-frame! env new-frame)
+  (set-car! env new-frame))
+
+;;; Representing frames
+
+(define (make-frame variables values)
+  (cond ((and (null? variables) (null? values)) '())
+        ((null? variables)
+         (error "Too many values supplied" values))
+        ((null? values)
+         (error "Too few values supplied" variables))
+        (else
+         (cons (make-binding (car variables) (car values))
+               (make-frame (cdr variables) (cdr values))))))
+
+(define (adjoin-binding binding frame)
+  (cons binding frame))
+
+(define (assq key bindings)
+  (cond ((null? bindings) no-binding)
+        ((eq? key (binding-variable (car bindings))) 
+         (car bindings))
+        (else (assq key (cdr bindings)))))
+
+(define (binding-in-frame var frame)
+  (assq var frame))
+
+(define (found-binding? b)
+  (not (eq? b no-binding)))
+
+(define no-binding '())
+
+;;; Representing bindings
+
+(define (make-binding variable value)
+  (cons variable value))
+
+(define (binding-variable binding)
+  (car binding))
+
+(define (binding-value binding)
+  (cdr binding))
+
+(define (set-binding-value! binding value)
+  (set-cdr! binding value))