Strict mode now works...

This commit is contained in:
Simon Brooke 2019-08-20 10:38:51 +01:00
parent 75bf19e38e
commit fe6fba87e0
5 changed files with 62 additions and 12 deletions

View file

@ -19,8 +19,8 @@
be Lisp 1.5's EQuivalent of `SETQ`), possibly by other things."
(atom NIL))
(def ^:dynamic *trace?*
"Whether or not to trace `EVAL`."
(def ^:dynamic *options*
"Command line options from invocation."
false)
(defn NULL
@ -304,7 +304,8 @@
See page 13 of the Lisp 1.5 Programmers Manual."
[expr env]
(cond
*trace?* (traced-eval expr env)
(true? (:trace *options*))
(traced-eval expr env)
(=
(ATOM? expr) 'T)
(CDR (ASSOC expr env))

View file

@ -1,5 +1,5 @@
(ns beowulf.core
(:require [beowulf.bootstrap :refer [EVAL oblist *trace?*]]
(:require [beowulf.bootstrap :refer [EVAL oblist *options*]]
[beowulf.read :refer [READ]]
[clojure.java.io :as io]
[clojure.pprint :refer [pprint]]
@ -40,6 +40,7 @@
data
(case (:cause data)
:parse-failure (println (:failure data))
:strict nil ;; the message, which has already been printed, is enough.
:quit (throw e)
;; default
(pprint data))))))
@ -60,7 +61,7 @@
(if (:errors args)
(apply str (interpose "; " (:errors args))))
"\nSprecan 'quit' tó laéfan\n"))
(binding [*trace?* (true? (:trace (:options args)))]
(binding [*options* (:options args)]
(try
(repl (str (:prompt (:options args)) " "))
(catch

View file

@ -1,5 +1,6 @@
(ns beowulf.read
(:require [clojure.math.numeric-tower :refer [expt]]
(:require [beowulf.bootstrap :refer [*options*]]
[clojure.math.numeric-tower :refer [expt]]
[clojure.string :refer [starts-with? upper-case]]
[instaparse.core :as i]
[beowulf.cons-cell :refer [make-beowulf-list make-cons-cell NIL]]))
@ -24,7 +25,7 @@
;; mexprs. I'm pretty clear that Lisp 1.5 could never read these,
;; but it's a convenience.
"mexpr := λexpr | fncall | defn | cond | mvar;
"mexpr := λexpr | fncall | defn | cond | mvar | mexpr comment;
λexpr := λ lsqb bindings semi-colon body rsqb;
λ := ';
bindings := lsqb args rsqb;
@ -41,9 +42,12 @@
mvar := #'[a-z]+';
semi-colon := ';';"
;; comments. I'm pretty confident Lisp 1.5 did NOT have these.
"comment := opt-space <';;'> #'[^\\n\\r]*';"
;; sexprs. Note it's not clear to me whether Lisp 1.5 had the quote macro,
;; but I've included it on the basis that it can do little harm.
"sexpr := quoted-expr | atom | number | dotted-pair | list;
"sexpr := quoted-expr | atom | number | dotted-pair | list | sexpr comment;
list := lpar sexpr rpar | lpar (sexpr sep)* rpar | lpar (sexpr sep)* dot-terminal;
dotted-pair := lpar dot-terminal ;
dot := '.';
@ -95,6 +99,11 @@
(= context :mexpr)
[:quoted-expr p]
p)
:comment (if
(:strict *options*)
(throw
(ex-info "Cannot parse comments in strict mode"
{:cause :strict})))
:dotted-pair (if
(= context :mexpr)
[:fncall
@ -103,7 +112,12 @@
(simplify (nth p 1) context)
(simplify (nth p 2) context)]]
(map simplify p))
:mexpr (simplify (second p) :mexpr)
:mexpr (if
(:strict *options*)
(throw
(ex-info "Cannot parse meta expressions in strict mode"
{:cause :strict}))
(simplify (second p) :mexpr))
:list (if
(= context :mexpr)
[:fncall
@ -115,7 +129,6 @@
p)))
;; # From Lisp 1.5 Programmers Manual, page 10
;; Note that I've retyped much of this, since copy/pasting out of PDF is less
;; than reliable. Any typos are mine. Quote starts [[

View file

@ -1,6 +1,7 @@
(ns beowulf.mexpr-test
(:require [clojure.test :refer :all]
[beowulf.read :refer [parse simplify generate]]))
[beowulf.bootstrap :refer [*options*]]
[beowulf.read :refer [parse simplify generate gsp]]))
;; These tests are taken generally from the examples on page 10 of
;; Lisp 1.5 Programmers Manual:
@ -64,3 +65,10 @@
(parse "label[ff;λ[[x];[atom[x]->x; T->ff[car[x]]]]]"))))]
(is (= actual expected)))))
(deftest strict-tests
(testing "Strict feature"
(binding [*options* {:strict true}]
(is (thrown-with-msg?
Exception
#"Cannot parse meta expressions in strict mode"
(gsp "label[ff;λ[[x];[atom[x]->x; T->ff[car[x]]]]]"))))))

View file

@ -2,7 +2,8 @@
(:require [clojure.math.numeric-tower :refer [abs]]
[clojure.test :refer :all]
[beowulf.cons-cell :refer :all]
[beowulf.read :refer [parse simplify generate]]))
[beowulf.bootstrap :refer [*options*]]
[beowulf.read :refer [parse simplify generate gsp]]))
;; broadly, sexprs should be homoiconic
@ -24,6 +25,32 @@
actual (generate (simplify (parse (str expected))))]
(is (= actual expected)))))
(deftest comment-tests
(testing "Reading comments"
(let [expected 'A
actual (gsp "A ;; comment")]
(is (= actual expected)))
(let [expected 10
actual (gsp "10 ;; comment")]
(is (= actual expected)))
(let [expected 2/5
actual (gsp "4E-1 ;; comment")]
(is (= actual expected)))
(let [expected "(A B C)"
actual (print-str (gsp "(A ;; comment
B C)"))]
(is (= actual expected)
"Really important that comments work inside lists"))
;; ;; TODO: Currently failing and I'm not sure why
;; (binding [*options* {:strict true}]
;; (is (thrown-with-msg?
;; Exception
;; #"Cannot parse comments in strict mode"
;; (gsp "(A ;; comment
;; B C)"))))
))
(deftest number-tests
(testing "Reading octal numbers"
(let [expected 1