Strict mode now works...
This commit is contained in:
parent
75bf19e38e
commit
fe6fba87e0
|
@ -19,8 +19,8 @@
|
||||||
be Lisp 1.5's EQuivalent of `SETQ`), possibly by other things."
|
be Lisp 1.5's EQuivalent of `SETQ`), possibly by other things."
|
||||||
(atom NIL))
|
(atom NIL))
|
||||||
|
|
||||||
(def ^:dynamic *trace?*
|
(def ^:dynamic *options*
|
||||||
"Whether or not to trace `EVAL`."
|
"Command line options from invocation."
|
||||||
false)
|
false)
|
||||||
|
|
||||||
(defn NULL
|
(defn NULL
|
||||||
|
@ -304,7 +304,8 @@
|
||||||
See page 13 of the Lisp 1.5 Programmers Manual."
|
See page 13 of the Lisp 1.5 Programmers Manual."
|
||||||
[expr env]
|
[expr env]
|
||||||
(cond
|
(cond
|
||||||
*trace?* (traced-eval expr env)
|
(true? (:trace *options*))
|
||||||
|
(traced-eval expr env)
|
||||||
(=
|
(=
|
||||||
(ATOM? expr) 'T)
|
(ATOM? expr) 'T)
|
||||||
(CDR (ASSOC expr env))
|
(CDR (ASSOC expr env))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
(ns beowulf.core
|
(ns beowulf.core
|
||||||
(:require [beowulf.bootstrap :refer [EVAL oblist *trace?*]]
|
(:require [beowulf.bootstrap :refer [EVAL oblist *options*]]
|
||||||
[beowulf.read :refer [READ]]
|
[beowulf.read :refer [READ]]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[clojure.pprint :refer [pprint]]
|
[clojure.pprint :refer [pprint]]
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
data
|
data
|
||||||
(case (:cause data)
|
(case (:cause data)
|
||||||
:parse-failure (println (:failure data))
|
:parse-failure (println (:failure data))
|
||||||
|
:strict nil ;; the message, which has already been printed, is enough.
|
||||||
:quit (throw e)
|
:quit (throw e)
|
||||||
;; default
|
;; default
|
||||||
(pprint data))))))
|
(pprint data))))))
|
||||||
|
@ -60,7 +61,7 @@
|
||||||
(if (:errors args)
|
(if (:errors args)
|
||||||
(apply str (interpose "; " (:errors args))))
|
(apply str (interpose "; " (:errors args))))
|
||||||
"\nSprecan 'quit' tó laéfan\n"))
|
"\nSprecan 'quit' tó laéfan\n"))
|
||||||
(binding [*trace?* (true? (:trace (:options args)))]
|
(binding [*options* (:options args)]
|
||||||
(try
|
(try
|
||||||
(repl (str (:prompt (:options args)) " "))
|
(repl (str (:prompt (:options args)) " "))
|
||||||
(catch
|
(catch
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns beowulf.read
|
(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]]
|
[clojure.string :refer [starts-with? upper-case]]
|
||||||
[instaparse.core :as i]
|
[instaparse.core :as i]
|
||||||
[beowulf.cons-cell :refer [make-beowulf-list make-cons-cell NIL]]))
|
[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,
|
;; mexprs. I'm pretty clear that Lisp 1.5 could never read these,
|
||||||
;; but it's a convenience.
|
;; 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;
|
λexpr := λ lsqb bindings semi-colon body rsqb;
|
||||||
λ := 'λ';
|
λ := 'λ';
|
||||||
bindings := lsqb args rsqb;
|
bindings := lsqb args rsqb;
|
||||||
|
@ -41,9 +42,12 @@
|
||||||
mvar := #'[a-z]+';
|
mvar := #'[a-z]+';
|
||||||
semi-colon := ';';"
|
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,
|
;; 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.
|
;; 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;
|
list := lpar sexpr rpar | lpar (sexpr sep)* rpar | lpar (sexpr sep)* dot-terminal;
|
||||||
dotted-pair := lpar dot-terminal ;
|
dotted-pair := lpar dot-terminal ;
|
||||||
dot := '.';
|
dot := '.';
|
||||||
|
@ -95,6 +99,11 @@
|
||||||
(= context :mexpr)
|
(= context :mexpr)
|
||||||
[:quoted-expr p]
|
[:quoted-expr p]
|
||||||
p)
|
p)
|
||||||
|
:comment (if
|
||||||
|
(:strict *options*)
|
||||||
|
(throw
|
||||||
|
(ex-info "Cannot parse comments in strict mode"
|
||||||
|
{:cause :strict})))
|
||||||
:dotted-pair (if
|
:dotted-pair (if
|
||||||
(= context :mexpr)
|
(= context :mexpr)
|
||||||
[:fncall
|
[:fncall
|
||||||
|
@ -103,7 +112,12 @@
|
||||||
(simplify (nth p 1) context)
|
(simplify (nth p 1) context)
|
||||||
(simplify (nth p 2) context)]]
|
(simplify (nth p 2) context)]]
|
||||||
(map simplify p))
|
(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
|
:list (if
|
||||||
(= context :mexpr)
|
(= context :mexpr)
|
||||||
[:fncall
|
[:fncall
|
||||||
|
@ -115,7 +129,6 @@
|
||||||
p)))
|
p)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; # From Lisp 1.5 Programmers Manual, page 10
|
;; # From Lisp 1.5 Programmers Manual, page 10
|
||||||
;; Note that I've retyped much of this, since copy/pasting out of PDF is less
|
;; Note that I've retyped much of this, since copy/pasting out of PDF is less
|
||||||
;; than reliable. Any typos are mine. Quote starts [[
|
;; than reliable. Any typos are mine. Quote starts [[
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns beowulf.mexpr-test
|
(ns beowulf.mexpr-test
|
||||||
(:require [clojure.test :refer :all]
|
(: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
|
;; These tests are taken generally from the examples on page 10 of
|
||||||
;; Lisp 1.5 Programmers Manual:
|
;; Lisp 1.5 Programmers Manual:
|
||||||
|
@ -64,3 +65,10 @@
|
||||||
(parse "label[ff;λ[[x];[atom[x]->x; T->ff[car[x]]]]]"))))]
|
(parse "label[ff;λ[[x];[atom[x]->x; T->ff[car[x]]]]]"))))]
|
||||||
(is (= actual expected)))))
|
(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]]]]]"))))))
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
(:require [clojure.math.numeric-tower :refer [abs]]
|
(:require [clojure.math.numeric-tower :refer [abs]]
|
||||||
[clojure.test :refer :all]
|
[clojure.test :refer :all]
|
||||||
[beowulf.cons-cell :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
|
;; broadly, sexprs should be homoiconic
|
||||||
|
|
||||||
|
@ -24,6 +25,32 @@
|
||||||
actual (generate (simplify (parse (str expected))))]
|
actual (generate (simplify (parse (str expected))))]
|
||||||
(is (= actual 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
|
(deftest number-tests
|
||||||
(testing "Reading octal numbers"
|
(testing "Reading octal numbers"
|
||||||
(let [expected 1
|
(let [expected 1
|
||||||
|
|
Loading…
Reference in a new issue