EVAL/APPLY now work; COND now works.
This commit is contained in:
parent
fec6a6a73a
commit
163f2845bb
|
@ -1,11 +1,35 @@
|
||||||
;; Test comment
|
;; Test comment
|
||||||
(DEFINE
|
((NIL . NIL)
|
||||||
(APPEND
|
(T . T)
|
||||||
(LAMBDA
|
;; many functions return 'F on fail, but to make this mean fail I'm binding
|
||||||
(X Y)
|
;; it to NIL
|
||||||
(COND ((NULL X) Y) (T (CONS (CAR X) (APPEND (CDR X Y)))))))
|
(F . NIL)
|
||||||
(CONC
|
;; Binding all system functions to NIL so that you can see on the OBLIST that
|
||||||
(LAMBDA
|
;; they exist
|
||||||
(X Y)
|
(ADD1 . NIL)
|
||||||
(COND ((NULL (CDR X)) (RPLACD X Y)) (T (CONC (CDR X) Y)))
|
(APPEND . NIL)
|
||||||
X)))
|
(APPLY . NIL)
|
||||||
|
(ATOM . NIL)
|
||||||
|
(CAR . NIL)
|
||||||
|
(CDR . NIL)
|
||||||
|
(CONS . NIL)
|
||||||
|
(DEFINE . NIL)
|
||||||
|
(DIFFERENCE . NIL)
|
||||||
|
(EQ . NIL)
|
||||||
|
(EQUAL . NIL)
|
||||||
|
(EVAL)
|
||||||
|
(FIXP . NIL)
|
||||||
|
(INTEROP . NIL)
|
||||||
|
(NUMBERP . NIL)
|
||||||
|
(OBLIST . NIL)
|
||||||
|
(PLUS . NIL)
|
||||||
|
(PRETTY . NIL)
|
||||||
|
(QUOTIENT . NIL)
|
||||||
|
(REMAINDER)
|
||||||
|
(RPLACA . NIL)
|
||||||
|
(RPLACD . NIL)
|
||||||
|
(SET . NIL)
|
||||||
|
(SYSIN . NIL)
|
||||||
|
(SYSOUT . NIL)
|
||||||
|
(TIMES . NIL)
|
||||||
|
)
|
|
@ -347,7 +347,9 @@
|
||||||
return the current value of the object list. Note that in PSL this function
|
return the current value of the object list. Note that in PSL this function
|
||||||
returns a list of the symbols bound, not the whole association list."
|
returns a list of the symbols bound, not the whole association list."
|
||||||
[]
|
[]
|
||||||
(make-beowulf-list (map CAR @oblist)))
|
(if (instance? ConsCell @oblist)
|
||||||
|
(make-beowulf-list (map CAR @oblist))
|
||||||
|
NIL))
|
||||||
|
|
||||||
(defn DEFINE
|
(defn DEFINE
|
||||||
"Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten
|
"Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten
|
||||||
|
@ -400,10 +402,12 @@
|
||||||
DEFINE (DEFINE (CAR args))
|
DEFINE (DEFINE (CAR args))
|
||||||
DIFFERENCE (DIFFERENCE (CAR args) (CADR args))
|
DIFFERENCE (DIFFERENCE (CAR args) (CADR args))
|
||||||
EQ (apply EQ args)
|
EQ (apply EQ args)
|
||||||
|
EQUAL (apply EQUAL args)
|
||||||
;; think about EVAL. Getting the environment right is subtle
|
;; think about EVAL. Getting the environment right is subtle
|
||||||
FIXP (apply FIXP args)
|
FIXP (apply FIXP args)
|
||||||
INTEROP (apply INTEROP args)
|
INTEROP (apply INTEROP args)
|
||||||
NUMBERP (apply NUMBERP args)
|
NUMBERP (apply NUMBERP args)
|
||||||
|
OBLIST (OBLIST)
|
||||||
PLUS (apply PLUS args)
|
PLUS (apply PLUS args)
|
||||||
PRETTY (apply pretty-print args)
|
PRETTY (apply pretty-print args)
|
||||||
QUOTIENT (apply QUOTIENT args)
|
QUOTIENT (apply QUOTIENT args)
|
||||||
|
@ -469,13 +473,16 @@
|
||||||
|
|
||||||
(defn- EVCON
|
(defn- EVCON
|
||||||
"Inner guts of primitive COND. All `clauses` are assumed to be
|
"Inner guts of primitive COND. All `clauses` are assumed to be
|
||||||
`beowulf.cons-cell/ConsCell` objects.
|
`beowulf.cons-cell/ConsCell` objects. Note that tests in Lisp 1.5
|
||||||
|
often return `F`, not `NIL`, on failure.
|
||||||
|
|
||||||
See page 13 of the Lisp 1.5 Programmers Manual."
|
See page 13 of the Lisp 1.5 Programmers Manual."
|
||||||
[clauses env]
|
[clauses env]
|
||||||
|
(let [test (EVAL (CAAR clauses) env)]
|
||||||
(if
|
(if
|
||||||
(not= (EVAL (CAAR clauses) env) NIL)
|
(and (not= test NIL) (not= test 'F))
|
||||||
(EVAL (CADAR clauses) env)
|
(EVAL (CADAR clauses) env)
|
||||||
(EVCON (CDR clauses) env)))
|
(EVCON (CDR clauses) env))))
|
||||||
|
|
||||||
(defn- EVLIS
|
(defn- EVLIS
|
||||||
"Map `EVAL` across this list of `args` in the context of this
|
"Map `EVAL` across this list of `args` in the context of this
|
||||||
|
@ -490,12 +497,12 @@
|
||||||
(EVLIS (CDR args) env))))
|
(EVLIS (CDR args) env))))
|
||||||
|
|
||||||
(defn- eval-symbolic [^Symbol s env]
|
(defn- eval-symbolic [^Symbol s env]
|
||||||
(let [binding (CDR (ASSOC s env))]
|
(let [binding (ASSOC s env)]
|
||||||
(if (= binding NIL)
|
(if (= binding NIL)
|
||||||
(throw (ex-info (format "No binding for symbol `%s`" s)
|
(throw (ex-info (format "No binding for symbol `%s`" s)
|
||||||
{:phase :eval
|
{:phase :eval
|
||||||
:symbol s}))
|
:symbol s}))
|
||||||
binding)))
|
(CDR binding))))
|
||||||
|
|
||||||
(defn- eval-internal
|
(defn- eval-internal
|
||||||
"Common guts for both EVAL and traced-eval. Evaluate this `expr`
|
"Common guts for both EVAL and traced-eval. Evaluate this `expr`
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns beowulf.core
|
(ns beowulf.core
|
||||||
"Essentially, the `-main` function and the bootstrap read-eval-print loop."
|
"Essentially, the `-main` function and the bootstrap read-eval-print loop."
|
||||||
(:require [beowulf.bootstrap :refer [EVAL]]
|
(:require [beowulf.bootstrap :refer [EVAL]]
|
||||||
|
[beowulf.io :refer [SYSIN]]
|
||||||
[beowulf.read :refer [READ read-from-console]]
|
[beowulf.read :refer [READ read-from-console]]
|
||||||
[beowulf.oblist :refer [*options* oblist]]
|
[beowulf.oblist :refer [*options* oblist]]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
|
@ -22,7 +23,8 @@
|
||||||
["-h" "--help"]
|
["-h" "--help"]
|
||||||
["-p PROMPT" "--prompt PROMPT" "Set the REPL prompt to PROMPT"
|
["-p PROMPT" "--prompt PROMPT" "Set the REPL prompt to PROMPT"
|
||||||
:default "Sprecan::"]
|
:default "Sprecan::"]
|
||||||
["-r INITFILE" "--read INITFILE" "Read Lisp functions from the file INITFILE"
|
["-r INITFILE" "--read INITFILE" "Read Lisp system from file INITFILE"
|
||||||
|
:default "resources/lisp1.5.lsp"
|
||||||
:validate [#(and
|
:validate [#(and
|
||||||
(.exists (io/file %))
|
(.exists (io/file %))
|
||||||
(.canRead (io/file %)))
|
(.canRead (io/file %)))
|
||||||
|
@ -74,7 +76,12 @@
|
||||||
(when (:errors args)
|
(when (:errors args)
|
||||||
(apply str (interpose "; " (:errors args))))
|
(apply str (interpose "; " (:errors args))))
|
||||||
"\nSprecan '" stop-word "' tó laéfan\n"))
|
"\nSprecan '" stop-word "' tó laéfan\n"))
|
||||||
|
|
||||||
(binding [*options* (:options args)]
|
(binding [*options* (:options args)]
|
||||||
|
(when (:read *options*)
|
||||||
|
(try (SYSIN (:read *options*))
|
||||||
|
(catch Throwable any
|
||||||
|
(println any))))
|
||||||
(try
|
(try
|
||||||
(repl (str (:prompt (:options args)) " "))
|
(repl (str (:prompt (:options args)) " "))
|
||||||
(catch
|
(catch
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
(:require [beowulf.cons-cell :refer [pretty-print]]
|
(:require [beowulf.cons-cell :refer [pretty-print]]
|
||||||
[beowulf.oblist :refer [*options* oblist]]
|
[beowulf.oblist :refer [*options* oblist]]
|
||||||
[beowulf.read :refer [READ]]
|
[beowulf.read :refer [READ]]
|
||||||
|
[clojure.java.io :refer [file resource]]
|
||||||
[clojure.string :refer [ends-with?]]
|
[clojure.string :refer [ends-with?]]
|
||||||
[java-time.api :refer [local-date local-date-time]]))
|
[java-time.api :refer [local-date local-date-time]]))
|
||||||
|
|
||||||
|
@ -57,20 +58,27 @@
|
||||||
(pretty-print @oblist)))))
|
(pretty-print @oblist)))))
|
||||||
|
|
||||||
(defn SYSIN
|
(defn SYSIN
|
||||||
"Read the contents of the file at this `filepath` into the object list.
|
"Read the contents of the file at this `filename` into the object list.
|
||||||
|
|
||||||
If the file is not a valid Beowulf sysout file, this will probably
|
If the file is not a valid Beowulf sysout file, this will probably
|
||||||
corrupt the system, you have been warned. File paths will be considered
|
corrupt the system, you have been warned. File paths will be considered
|
||||||
relative to the filepath set when starting Lisp.
|
relative to the filepath set when starting Lisp.
|
||||||
|
|
||||||
**NOTE THAT** if the provided `filepath` does not end with `.lsp` (which,
|
It is intended that sysout files can be read both from resources within
|
||||||
if you're writing it from the Lisp REPL it won't), the extension `.lsp`
|
the jar file, and from the file system. If a named file exists in both the
|
||||||
|
file system and the resources, the file system will be preferred.
|
||||||
|
|
||||||
|
**NOTE THAT** if the provided `filename` does not end with `.lsp` (which,
|
||||||
|
if you're writing it from the Lisp REPL, it won't), the extension `.lsp`
|
||||||
will be appended."
|
will be appended."
|
||||||
[filepath]
|
[filename]
|
||||||
(let [fp (full-path (str filepath))
|
(let [fp (file (full-path (str filename)))
|
||||||
content (try (READ (slurp fp))
|
file (when (and (.exists fp) (.canRead fp)) fp)
|
||||||
|
res (try (resource filename)
|
||||||
|
(catch Throwable _ nil))
|
||||||
|
content (try (READ (slurp (or file res)))
|
||||||
(catch Throwable any
|
(catch Throwable any
|
||||||
(throw (ex-info "Could not read from sysout"
|
(throw (ex-info "Could not read from file"
|
||||||
{:context "SYSIN"
|
{:context "SYSIN"
|
||||||
:filepath fp}
|
:filepath fp}
|
||||||
any))))]
|
any))))]
|
||||||
|
|
Loading…
Reference in a new issue