Added unit tests for RPLACA and RPLACD
This commit is contained in:
parent
3d2c524f3f
commit
877e9ba00a
|
@ -1,7 +1,8 @@
|
||||||
(ns beowulf.cons-cell
|
(ns beowulf.cons-cell
|
||||||
"The fundamental cons cell on which all Lisp structures are built.
|
"The fundamental cons cell on which all Lisp structures are built.
|
||||||
Lisp 1.5 lists do not necessarily have a sequence as their CDR, so
|
Lisp 1.5 lists do not necessarily have a sequence as their CDR, and
|
||||||
cannot be implemented on top of Clojure lists.")
|
must have both CAR and CDR mutable, so cannot be implemented on top
|
||||||
|
of Clojure lists.")
|
||||||
|
|
||||||
(def NIL
|
(def NIL
|
||||||
"The canonical empty list symbol."
|
"The canonical empty list symbol."
|
||||||
|
@ -29,15 +30,19 @@
|
||||||
"like `more`, q.v., but returns List `NIL` not Clojure `nil` when empty." ))
|
"like `more`, q.v., but returns List `NIL` not Clojure `nil` when empty." ))
|
||||||
|
|
||||||
(deftype ConsCell [^:unsynchronized-mutable CAR ^:unsynchronized-mutable CDR]
|
(deftype ConsCell [^:unsynchronized-mutable CAR ^:unsynchronized-mutable CDR]
|
||||||
|
;; Note that, because the CAR and CDR fields are unsynchronised mutable - i.e.
|
||||||
|
;; plain old Java instance variables which can be written as well as read -
|
||||||
|
;; ConsCells are NOT thread safe. This does not matter, since Lisp 1.5 is
|
||||||
|
;; single threaded.
|
||||||
MutableSequence
|
MutableSequence
|
||||||
|
|
||||||
(rplaca [this value]
|
(rplaca [this value]
|
||||||
(if
|
(if
|
||||||
(or
|
(or
|
||||||
(satisfies? MutableSequence value) ;; can't reference
|
(satisfies? MutableSequence value) ;; can't reference
|
||||||
;; beowulf.cons_cell.ConsCell,
|
;; beowulf.cons_cell.ConsCell,
|
||||||
;; because it is not yet
|
;; because it is not yet
|
||||||
;; defined
|
;; defined
|
||||||
(number? value)
|
(number? value)
|
||||||
(symbol? value))
|
(symbol? value))
|
||||||
(do
|
(do
|
||||||
|
@ -62,7 +67,7 @@
|
||||||
{:cause :bad-value
|
{:cause :bad-value
|
||||||
:detail :rplaca}))))
|
:detail :rplaca}))))
|
||||||
(getCdr [this]
|
(getCdr [this]
|
||||||
(. this CDR))
|
(. this CDR))
|
||||||
|
|
||||||
clojure.lang.ISeq
|
clojure.lang.ISeq
|
||||||
(cons [this x] (ConsCell. x this))
|
(cons [this x] (ConsCell. x this))
|
||||||
|
|
|
@ -1,17 +1,68 @@
|
||||||
(ns beowulf.host
|
(ns beowulf.host
|
||||||
"provides Lisp 1.5 functions which can't be (or can't efficiently
|
"provides Lisp 1.5 functions which can't be (or can't efficiently
|
||||||
be) implemented in Lisp 1.5, which therefore need to be implemented in the
|
be) implemented in Lisp 1.5, which therefore need to be implemented in the
|
||||||
host language, in this case Clojure.")
|
host language, in this case Clojure."
|
||||||
|
(:require [beowulf.cons-cell :refer [T NIL F]]
|
||||||
|
;; note hyphen - this is Clojure...
|
||||||
|
)
|
||||||
|
(:import [beowulf.cons_cell ConsCell]
|
||||||
|
;; note underscore - same namespace, but Java.
|
||||||
|
))
|
||||||
|
|
||||||
;; these are CANDIDATES to be host-implemented. only a subset of them MUST be.
|
;; these are CANDIDATES to be host-implemented. only a subset of them MUST be.
|
||||||
;; those which can be implemented in Lisp should be, since that aids
|
;; those which can be implemented in Lisp should be, since that aids
|
||||||
;; portability.
|
;; portability.
|
||||||
|
|
||||||
;; RPLACA
|
|
||||||
|
|
||||||
;; RPLACD
|
(defn RPLACA
|
||||||
|
"Replace the CAR pointer of this `cell` with this `value`. Dangerous, should
|
||||||
|
really not exist, but does in Lisp 1.5 (and was important for some
|
||||||
|
performance hacks in early Lisps)"
|
||||||
|
[^ConsCell cell value]
|
||||||
|
(if
|
||||||
|
(instance? ConsCell cell)
|
||||||
|
(if
|
||||||
|
(or
|
||||||
|
(instance? ConsCell value)
|
||||||
|
(number? value)
|
||||||
|
(symbol? value)
|
||||||
|
(= value NIL))
|
||||||
|
(do
|
||||||
|
(.rplaca cell value)
|
||||||
|
cell)
|
||||||
|
(throw (ex-info
|
||||||
|
(str "Invalid value in RPLACA: `" value "` (" (type value) ")")
|
||||||
|
{:cause :bad-value
|
||||||
|
:detail :rplaca})))
|
||||||
|
(throw (ex-info
|
||||||
|
(str "Invalid cell in RPLACA: `" cell "` (" (type cell) ")")
|
||||||
|
{:cause :bad-value
|
||||||
|
:detail :rplaca}))))
|
||||||
|
|
||||||
;; PLUS
|
(defn RPLACD
|
||||||
|
"Replace the CDR pointer of this `cell` with this `value`. Dangerous, should
|
||||||
|
really not exist, but does in Lisp 1.5 (and was important for some
|
||||||
|
performance hacks in early Lisps)"
|
||||||
|
[^ConsCell cell value]
|
||||||
|
(if
|
||||||
|
(instance? ConsCell cell)
|
||||||
|
(if
|
||||||
|
(or
|
||||||
|
(instance? ConsCell value)
|
||||||
|
(number? value)
|
||||||
|
(symbol? value)
|
||||||
|
(= value NIL))
|
||||||
|
(do
|
||||||
|
(.rplacd cell value)
|
||||||
|
cell)
|
||||||
|
(throw (ex-info
|
||||||
|
(str "Invalid value in RPLACD: `" value "` (" (type value) ")")
|
||||||
|
{:cause :bad-value
|
||||||
|
:detail :rplaca})))
|
||||||
|
(throw (ex-info
|
||||||
|
(str "Invalid cell in RPLACD: `" cell "` (" (type cell) ")")
|
||||||
|
{:cause :bad-value
|
||||||
|
:detail :rplaca}))));; PLUS
|
||||||
|
|
||||||
;; MINUS
|
;; MINUS
|
||||||
|
|
||||||
|
|
27
test/beowulf/host_test.clj
Normal file
27
test/beowulf/host_test.clj
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
(ns beowulf.host-test
|
||||||
|
(:require [clojure.math.numeric-tower :refer [abs]]
|
||||||
|
[clojure.test :refer :all]
|
||||||
|
[beowulf.cons-cell :refer [make-beowulf-list make-cons-cell NIL T F]]
|
||||||
|
[beowulf.bootstrap :refer [CDR]]
|
||||||
|
[beowulf.host :refer :all]
|
||||||
|
[beowulf.read :refer [gsp]]))
|
||||||
|
|
||||||
|
(deftest destructive-change-test
|
||||||
|
(testing "RPLACA"
|
||||||
|
(let
|
||||||
|
[l (make-beowulf-list '(A B C D E))
|
||||||
|
target (CDR l)
|
||||||
|
expected "(A F C D E)"
|
||||||
|
actual (do (RPLACA target 'F) (print-str l))]
|
||||||
|
(is (= actual expected)))
|
||||||
|
)
|
||||||
|
(testing "RPLACA"
|
||||||
|
(let
|
||||||
|
[l (make-beowulf-list '(A B C D E))
|
||||||
|
target (CDR l)
|
||||||
|
expected "(A B . F)"
|
||||||
|
actual (do (RPLACD target 'F) (print-str l))]
|
||||||
|
(is (= actual expected)))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue