Flow rule generation very nearly correct!
Not all tests pass; additional conditions are not yet evaluated.
This commit is contained in:
parent
2a5d598f28
commit
93a0f3ea1d
|
@ -4,7 +4,7 @@
|
||||||
declarative parser, q.v."
|
declarative parser, q.v."
|
||||||
:author "Simon Brooke"}
|
:author "Simon Brooke"}
|
||||||
mw-parser.core
|
mw-parser.core
|
||||||
(:require [clojure.string :only [split trim triml]]
|
(:require [clojure.string :refer [split trim triml]]
|
||||||
[mw-engine.utils :refer [member?]])
|
[mw-engine.utils :refer [member?]])
|
||||||
(:gen-class))
|
(:gen-class))
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
"Parse a token assumed to be the name of a property of the current cell,
|
"Parse a token assumed to be the name of a property of the current cell,
|
||||||
whose value is assumed to be an integer."
|
whose value is assumed to be an integer."
|
||||||
[[value & remainder]]
|
[[value & remainder]]
|
||||||
(when value [(list 'get-int 'cell (keyword value)) remainder]))
|
(when value [(list 'mw-engine.utils/get-int 'cell (keyword value)) remainder]))
|
||||||
|
|
||||||
(defn parse-property-value
|
(defn parse-property-value
|
||||||
"Parse a token assumed to be the name of a property of the current cell."
|
"Parse a token assumed to be the name of a property of the current cell."
|
||||||
|
|
|
@ -25,11 +25,13 @@
|
||||||
"PERCENTAGE := NUMBER #'%';"
|
"PERCENTAGE := NUMBER #'%';"
|
||||||
"QUANTITY := PERCENTAGE | NUMBER | EXPRESSION | SOME;"
|
"QUANTITY := PERCENTAGE | NUMBER | EXPRESSION | SOME;"
|
||||||
"SOURCE := STATE | STATE SPACE WITH SPACE CONDITIONS;"
|
"SOURCE := STATE | STATE SPACE WITH SPACE CONDITIONS;"
|
||||||
"DESTINATION := STATE | STATE SPACE WITH SPACE FLOW-CONDITIONS | STATE SPACE WITHIN SPACE VALUE SPACE WITH SPACE FLOW-CONDITIONS;"
|
"DESTINATION := TARGET | TARGET SPACE WITH SPACE FLOW-CONDITIONS;"
|
||||||
"DETERMINER := MOST | LEAST;"
|
"DETERMINER := MOST | LEAST;"
|
||||||
"DETERMINER-CONDITION := DETERMINER SPACE PROPERTY | DETERMINER SPACE PROPERTY;"
|
"DETERMINER-CONDITION := DETERMINER SPACE PROPERTY;"
|
||||||
"FLOW-CONDITIONS := DETERMINER-CONDITION | CONDITIONS"
|
"FLOW-CONDITIONS := DETERMINER-CONDITION | CONDITIONS"
|
||||||
|
"RANGE := WITHIN SPACE VALUE;"
|
||||||
"STATE := SYMBOL;"
|
"STATE := SYMBOL;"
|
||||||
|
"TARGET := STATE | STATE SPACE RANGE;"
|
||||||
"TO-HOW := TO | TO-EACH | TO-FIRST;"
|
"TO-HOW := TO | TO-EACH | TO-FIRST;"
|
||||||
"TO-EACH := TO SPACE EACH | TO SPACE ALL;"
|
"TO-EACH := TO SPACE EACH | TO SPACE ALL;"
|
||||||
"TO-FIRST := TO SPACE FIRST"]))
|
"TO-FIRST := TO SPACE FIRST"]))
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
(ns ^{:doc "Generate Clojure source from simplified parse trees."
|
(ns ^{:doc "Generate Clojure source from simplified parse trees."
|
||||||
:author "Simon Brooke"}
|
:author "Simon Brooke"}
|
||||||
mw-parser.generate
|
mw-parser.generate
|
||||||
(:require [clojure.pprint :refer [pprint]]
|
(:require [mw-parser.errors :as pe]
|
||||||
[clojure.tools.trace :refer [deftrace]]
|
[mw-parser.utils :refer [assert-type search-tree TODO]]))
|
||||||
[mw-parser.utils :refer [assert-type TODO]]
|
|
||||||
[mw-parser.errors :as pe]))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
|
@ -233,7 +231,8 @@
|
||||||
(list 'count
|
(list 'count
|
||||||
(list 'remove 'false?
|
(list 'remove 'false?
|
||||||
(list 'map (list 'fn ['cell] property-condition)
|
(list 'map (list 'fn ['cell] property-condition)
|
||||||
(list 'mw-engine.utils/get-neighbours 'world 'cell distance)))) quantity))
|
(list 'mw-engine.utils/get-neighbours 'world 'cell distance))))
|
||||||
|
quantity))
|
||||||
([comp1 quantity property-condition]
|
([comp1 quantity property-condition]
|
||||||
(generate-neighbours-condition comp1 quantity property-condition 1)))
|
(generate-neighbours-condition comp1 quantity property-condition 1)))
|
||||||
|
|
||||||
|
@ -253,7 +252,11 @@
|
||||||
distance (generate (nth tree 4))
|
distance (generate (nth tree 4))
|
||||||
pc (generate (nth tree 6))]
|
pc (generate (nth tree 6))]
|
||||||
(case quantifier-type
|
(case quantifier-type
|
||||||
:NUMBER (generate-neighbours-condition '= (read-string (second (second quantifier))) pc distance)
|
:NUMBER (generate-neighbours-condition
|
||||||
|
'=
|
||||||
|
(read-string (second (second quantifier)))
|
||||||
|
pc
|
||||||
|
distance)
|
||||||
:SOME (generate-neighbours-condition '> 0 pc distance)
|
:SOME (generate-neighbours-condition '> 0 pc distance)
|
||||||
:MORE (let [value (generate (nth quantifier 3))]
|
:MORE (let [value (generate (nth quantifier 3))]
|
||||||
(generate-neighbours-condition '> value pc distance))
|
(generate-neighbours-condition '> value pc distance))
|
||||||
|
@ -280,23 +283,100 @@
|
||||||
;;; (fn [cell world])
|
;;; (fn [cell world])
|
||||||
;;; (if (= (:state cell) (or (:house cell) :house))
|
;;; (if (= (:state cell) (or (:house cell) :house))
|
||||||
|
|
||||||
(defmacro flow-rule
|
(defn flow-rule
|
||||||
|
"Generate a flow rule for this `quantity` of this `property` from this
|
||||||
|
`source` to this `destination`."
|
||||||
[source property quantity-frag destinations]
|
[source property quantity-frag destinations]
|
||||||
`(fn [cell world]
|
(vary-meta
|
||||||
(when (and ~source (pos? cell ~property))
|
(list 'fn ['cell 'world]
|
||||||
(map
|
(list 'when (list 'and source (list 'pos? 'cell property))
|
||||||
(fn [d] {:source (select-keys cell [:x :y])
|
(list 'map
|
||||||
:destination (select-keys d [:x :y])
|
(list 'fn ['d]
|
||||||
:property ~property
|
{:source (list 'select-keys 'cell [:x :y])
|
||||||
:quantity ~quantity-frag})
|
:destination (list 'select-keys 'd [:x :y])
|
||||||
~destinations))))
|
:property property
|
||||||
|
:quantity quantity-frag})
|
||||||
|
destinations)))
|
||||||
|
merge
|
||||||
|
{:rule-type
|
||||||
|
:flow}))
|
||||||
|
|
||||||
|
(defn generate-quantity-accessor
|
||||||
|
"Generate a code fragment which will generate the appropriate quantity of
|
||||||
|
the `property` specified in a rule, from this `q-clause`."
|
||||||
|
[q-clause property]
|
||||||
|
(case (first q-clause)
|
||||||
|
;; TODO :EXPRESSION still needed
|
||||||
|
:NUMBER (generate q-clause)
|
||||||
|
:PERCENTAGE (let [multiplier (/ (generate (second q-clause)) 100)]
|
||||||
|
(list '* multiplier (list property 'cell)))
|
||||||
|
:SOME (list 'rand (list property 'cell))
|
||||||
|
(throw (ex-info
|
||||||
|
(format "Unexpected QUANTITY type: `%s`" (first q-clause))
|
||||||
|
{:clause q-clause
|
||||||
|
:property property}))))
|
||||||
|
|
||||||
|
(defn generate-target-state-filter
|
||||||
|
[clause targets-frag]
|
||||||
|
(assert-type clause :DESTINATION)
|
||||||
|
(list 'filter
|
||||||
|
(list 'fn ['cell]
|
||||||
|
(generate-property-condition
|
||||||
|
(search-tree (search-tree clause :TARGET)
|
||||||
|
:PROPERTY-CONDITION)))
|
||||||
|
targets-frag))
|
||||||
|
|
||||||
|
(defn generate-dest-accessor
|
||||||
|
[clause]
|
||||||
|
(let [dc (search-tree clause :DETERMINER-CONDITION)
|
||||||
|
range (search-tree clause :RANGE)
|
||||||
|
distance (if range (generate (nth range 2)) 1)]
|
||||||
|
(list 'let ['candidates
|
||||||
|
(generate-target-state-filter
|
||||||
|
clause
|
||||||
|
(list 'mw-engine.utils/get-neighbours 'world 'cell distance))]
|
||||||
|
(if dc
|
||||||
|
(list 'list
|
||||||
|
(let [determiner (first (second (search-tree dc :DETERMINER)))
|
||||||
|
prop (generate (nth dc 2))]
|
||||||
|
(case determiner
|
||||||
|
:LEAST (list 'mw-engine.utils/get-least-cell 'candidates prop)
|
||||||
|
:MOST (list 'mw-engine.utils/get-most-cell 'candidates prop))))
|
||||||
|
'candidates))))
|
||||||
|
;; (fn
|
||||||
|
;; [cell world]
|
||||||
|
;; (when
|
||||||
|
;; (and (= (:state cell) (or (:house cell) :house)) (pos? cell :food))
|
||||||
|
;; (map
|
||||||
|
;; (fn
|
||||||
|
;; [d]
|
||||||
|
;; (assoc
|
||||||
|
;; {}
|
||||||
|
;; :source
|
||||||
|
;; (select-keys cell [:x :y])
|
||||||
|
;; :destination
|
||||||
|
;; (select-keys d [:x :y])
|
||||||
|
;; :property
|
||||||
|
;; :food
|
||||||
|
;; :quantity
|
||||||
|
;; (* 1/10 (:food cell)))
|
||||||
|
;; {})
|
||||||
|
;; (let
|
||||||
|
;; [candidates
|
||||||
|
;; (filter
|
||||||
|
;; (fn [cell] (= (:state cell) (or (:house cell) :house)))
|
||||||
|
;; (mw-engine.utils/get-neighbours world cell 2))]
|
||||||
|
;; (list (mw-engine.utils/get-least-cell candidates :food))))))
|
||||||
|
|
||||||
(defn generate-flow
|
(defn generate-flow
|
||||||
[tree]
|
[tree]
|
||||||
(assert-type tree :FLOW-RULE)
|
(assert-type tree :FLOW-RULE)
|
||||||
(let [clauses (reduce #(assoc %1 (first %2) %2) {} (rest tree))]
|
(let [clauses (reduce #(assoc %1 (first %2) %2) {} (rest tree))
|
||||||
(list 'fn ['cell 'world]
|
source-accessor (generate (:SOURCE clauses))
|
||||||
(list 'when (generate (:SOURCE clauses))))))
|
property (generate (:SYMBOL clauses))
|
||||||
|
quantity (generate-quantity-accessor (second (:QUANTITY clauses)) property)
|
||||||
|
dest-accessor (generate-dest-accessor (:DESTINATION clauses))]
|
||||||
|
(flow-rule source-accessor property quantity dest-accessor)))
|
||||||
|
|
||||||
;;; Top level; only function anything outside this file (except tests) should
|
;;; Top level; only function anything outside this file (except tests) should
|
||||||
;;; really call.
|
;;; really call.
|
||||||
|
@ -333,8 +413,10 @@
|
||||||
:PROPERTY (list (generate (second tree)) 'cell) ;; dubious - may not be right
|
:PROPERTY (list (generate (second tree)) 'cell) ;; dubious - may not be right
|
||||||
:PROPERTY-CONDITION (generate-property-condition tree)
|
:PROPERTY-CONDITION (generate-property-condition tree)
|
||||||
:QUALIFIER (generate-qualifier tree)
|
:QUALIFIER (generate-qualifier tree)
|
||||||
|
:QUANTITY (generate (second tree))
|
||||||
:RULE (generate-rule tree)
|
:RULE (generate-rule tree)
|
||||||
:SIMPLE-ACTION (generate-simple-action tree)
|
:SIMPLE-ACTION (generate-simple-action tree)
|
||||||
|
:SOURCE (generate (second tree))
|
||||||
:SYMBOL (keyword (second tree))
|
:SYMBOL (keyword (second tree))
|
||||||
:VALUE (generate (second tree))
|
:VALUE (generate (second tree))
|
||||||
:WITHIN-CONDITION (generate-within-condition tree)
|
:WITHIN-CONDITION (generate-within-condition tree)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns ^{:doc "Simplify a parse tree."
|
(ns ^{:doc "Simplify a parse tree."
|
||||||
:author "Simon Brooke"}
|
:author "Simon Brooke"}
|
||||||
mw-parser.simplify)
|
mw-parser.simplify
|
||||||
|
(:require [mw-parser.utils :refer [search-tree]]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;
|
;;;;
|
||||||
|
@ -72,16 +73,29 @@
|
||||||
:CONDITIONS (simplify-second-of-two tree)
|
:CONDITIONS (simplify-second-of-two tree)
|
||||||
:DISJUNCT-EXPRESSION (simplify-chained-list tree :DISJUNCT-VALUE :VALUE)
|
:DISJUNCT-EXPRESSION (simplify-chained-list tree :DISJUNCT-VALUE :VALUE)
|
||||||
:EXPRESSION (simplify-second-of-two tree)
|
:EXPRESSION (simplify-second-of-two tree)
|
||||||
|
:FLOW-CONDITIONS (simplify-second-of-two tree)
|
||||||
:IN nil
|
:IN nil
|
||||||
:PROPERTY (simplify-second-of-two tree)
|
:PROPERTY (simplify-second-of-two tree)
|
||||||
:PROPERTY-CONDITION-OR-EXPRESSION (simplify-second-of-two tree)
|
:PROPERTY-CONDITION-OR-EXPRESSION (simplify-second-of-two tree)
|
||||||
:OR nil
|
:OR nil
|
||||||
:SPACE nil
|
:SPACE nil
|
||||||
|
:STATE (list :PROPERTY-CONDITION
|
||||||
|
(list :SYMBOL "state")
|
||||||
|
'(:QUALIFIER
|
||||||
|
(:EQUIVALENCE
|
||||||
|
(:IS "is")))
|
||||||
|
(list :EXPRESSION
|
||||||
|
(list :VALUE (second tree))))
|
||||||
:THEN nil
|
:THEN nil
|
||||||
:VALUE (simplify-second-of-two tree)
|
:VALUE (simplify-second-of-two tree)
|
||||||
(remove nil? (map simplify tree)))
|
(remove nil? (map simplify tree)))
|
||||||
tree))
|
tree))
|
||||||
|
|
||||||
|
;; OK, there is a major unresolved problem. If there is a determiner condition,
|
||||||
|
;; the tree as parsed from natural language is the wrong shape, and we're
|
||||||
|
;; going to have to restructure it somewhere to being the determiner upstream
|
||||||
|
;; of the property conditions. It *may* be possible to do that in `generate`.
|
||||||
|
|
||||||
(defn simplify-determiner-condition
|
(defn simplify-determiner-condition
|
||||||
[tree]
|
[tree]
|
||||||
(apply vector
|
(apply vector
|
||||||
|
|
|
@ -49,7 +49,9 @@
|
||||||
"If `tree-fragment` is not a tree fragment of the expected `type`, throw an exception."
|
"If `tree-fragment` is not a tree fragment of the expected `type`, throw an exception."
|
||||||
[tree-fragment type]
|
[tree-fragment type]
|
||||||
(assert (suitable-fragment? tree-fragment type)
|
(assert (suitable-fragment? tree-fragment type)
|
||||||
(throw (Exception. (format "Expected a %s fragment" type)))))
|
(throw (ex-info (format "Expected a %s fragment" type)
|
||||||
|
{:actual tree-fragment
|
||||||
|
:expected type}))))
|
||||||
|
|
||||||
|
|
||||||
(defn search-tree
|
(defn search-tree
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
(is (= (first (parse-simple-value '("this" "and" "that"))) :this)
|
(is (= (first (parse-simple-value '("this" "and" "that"))) :this)
|
||||||
"or else just a keyword")
|
"or else just a keyword")
|
||||||
(is (= (first (parse-simple-value '("this" "and" "that") true))
|
(is (= (first (parse-simple-value '("this" "and" "that") true))
|
||||||
'(get-int cell :this))
|
'(mw-engine.utils/get-int cell :this))
|
||||||
"...unless an integer is explicitly sought, in which case it should be something which gets an integer from the current cell")
|
"...unless an integer is explicitly sought, in which case it should be something which gets an integer from the current cell")
|
||||||
(is (= (parse-value '()) nil)
|
(is (= (parse-value '()) nil)
|
||||||
"if there's nothing to parse, return nil")
|
"if there's nothing to parse, return nil")
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
(is (= (first (parse-value '("this" "and" "that"))) :this)
|
(is (= (first (parse-value '("this" "and" "that"))) :this)
|
||||||
"or else just a keyword")
|
"or else just a keyword")
|
||||||
(is (= (first (parse-value '("this" "and" "that") true))
|
(is (= (first (parse-value '("this" "and" "that") true))
|
||||||
'(get-int cell :this))
|
'(mw-engine.utils/get-int cell :this))
|
||||||
"...unless an integer is explicitly sought, in which case it should be something which gets an integer from the current cell")
|
"...unless an integer is explicitly sought, in which case it should be something which gets an integer from the current cell")
|
||||||
(is (= (parse-property-value '()) nil)
|
(is (= (parse-property-value '()) nil)
|
||||||
"if there's nothing to parse, return nil")
|
"if there's nothing to parse, return nil")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
(ns mw-parser.flow-test
|
(ns mw-parser.flow-test
|
||||||
(:require ;; [clojure.pprint :as pprint]
|
(:require ;; [clojure.pprint :as pprint]
|
||||||
[clojure.test :refer [deftest is testing]] ;; [mw-engine.core :refer [transform-world]]
|
[clojure.test :refer [deftest is testing]] ;; [mw-engine.core :refer [transform-world]]
|
||||||
[mw-parser.flow :refer [parse-flow simplify-flow]]))
|
[mw-parser.declarative :refer [parse]]
|
||||||
|
[mw-parser.simplify :refer [simplify]]))
|
||||||
|
|
||||||
(deftest parse-flow-tests
|
(deftest parse-flow-tests
|
||||||
(testing "flow-grammar"
|
(testing "flow-grammar"
|
||||||
|
@ -31,11 +32,13 @@
|
||||||
(:WITH "with")
|
(:WITH "with")
|
||||||
(:FLOW-CONDITIONS
|
(:FLOW-CONDITIONS
|
||||||
(:DETERMINER-CONDITION (:LEAST "least") (:SYMBOL "food")))))
|
(:DETERMINER-CONDITION (:LEAST "least") (:SYMBOL "food")))))
|
||||||
actual (simplify-flow (parse-flow rule))]
|
actual (simplify (parse rule))]
|
||||||
|
|
||||||
(is (= actual expected) rule))
|
(is (= actual expected) rule))
|
||||||
(let [rule "flow 10% food from house having food more than 10 to each house within 2 with food less than 4"
|
(let [rule "flow 10% food from house having food more than 10 to each house within 2 with food less than 4"
|
||||||
expected '(:FLOW-RULE
|
expected '(:FLOW-RULE
|
||||||
(:PERCENTAGE (:NUMBER "10") "%")
|
(:FLOW "flow")
|
||||||
|
(:QUANTITY (:PERCENTAGE (:NUMBER "10") "%"))
|
||||||
(:SYMBOL "food")
|
(:SYMBOL "food")
|
||||||
(:FROM "from")
|
(:FROM "from")
|
||||||
(:SOURCE
|
(:SOURCE
|
||||||
|
@ -46,21 +49,21 @@
|
||||||
(:WITH "having")
|
(:WITH "having")
|
||||||
(:PROPERTY-CONDITION
|
(:PROPERTY-CONDITION
|
||||||
(:SYMBOL "food")
|
(:SYMBOL "food")
|
||||||
(:QUALIFIER (:COMPARATIVE-QUALIFIER (:MORE "more") (:THAN "than")))
|
(:QUALIFIER
|
||||||
|
(:COMPARATIVE-QUALIFIER (:MORE "more") (:THAN "than")))
|
||||||
(:NUMBER "10")))
|
(:NUMBER "10")))
|
||||||
(:TO-HOW (:TO-EACH (:TO "to") (:EACH "each")))
|
(:TO-HOW (:TO-EACH (:TO "to") (:EACH "each")))
|
||||||
(:DESTINATION
|
(:DESTINATION
|
||||||
(:PROPERTY-CONDITION
|
(:TARGET
|
||||||
(:SYMBOL "state")
|
|
||||||
(:QUALIFIER (:EQUIVALENCE (:IS "is")))
|
|
||||||
(:EXPRESSION (:VALUE [:SYMBOL "house"])))
|
|
||||||
(:WITHIN "within")
|
|
||||||
(:VALUE (:NUMBER "2"))
|
|
||||||
(:WITH "with")
|
|
||||||
(:FLOW-CONDITIONS
|
|
||||||
(:PROPERTY-CONDITION
|
(:PROPERTY-CONDITION
|
||||||
(:SYMBOL "food")
|
(:SYMBOL "state") (:QUALIFIER (:EQUIVALENCE (:IS "is")))
|
||||||
(:QUALIFIER (:COMPARATIVE-QUALIFIER (:LESS "less") (:THAN "than")))
|
(:EXPRESSION (:VALUE [:SYMBOL "house"])))
|
||||||
(:NUMBER "4")))))
|
(:RANGE (:WITHIN "within") (:NUMBER "2")))
|
||||||
actual (simplify-flow (parse-flow rule))]
|
(:WITH "with")
|
||||||
|
(:PROPERTY-CONDITION
|
||||||
|
(:SYMBOL "food")
|
||||||
|
(:QUALIFIER
|
||||||
|
(:COMPARATIVE-QUALIFIER (:LESS "less") (:THAN "than")))
|
||||||
|
(:NUMBER "4"))))
|
||||||
|
actual (simplify (parse rule))]
|
||||||
(is (= actual expected) rule))))
|
(is (= actual expected) rule))))
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
(ns mw-parser.generate-test
|
(ns mw-parser.generate-test
|
||||||
(:require [clojure.test :refer [deftest is testing]]
|
(:require [clojure.test :refer [deftest is testing]]
|
||||||
[mw-parser.generate :refer [generate]]))
|
[mw-parser.generate :refer [generate]]
|
||||||
|
[mw-parser.declarative :refer [parse]]
|
||||||
;; TODO: these tests are badly written and many (all?!?) of them were not
|
[mw-parser.simplify :refer [simplify]]))
|
||||||
;; actually firing. rewrite ALL to the pattern:
|
|
||||||
;;
|
|
||||||
;; (let [actual ...
|
|
||||||
;; expected ...]
|
|
||||||
;; (is (= actual expected)))
|
|
||||||
|
|
||||||
(deftest expressions-tests
|
(deftest expressions-tests
|
||||||
(testing "Generating primitive expressions."
|
(testing "Generating primitive expressions."
|
||||||
(is (= (generate '(:NUMERIC-EXPRESSION (:NUMBER "50"))) 50))
|
(let [actual (generate '(:NUMERIC-EXPRESSION (:NUMBER "50")))
|
||||||
(is (= (generate '(:NUMERIC-EXPRESSION (:SYMBOL "sealevel")))
|
expected 50]
|
||||||
'(:sealevel cell)))))
|
(is (= actual expected)))
|
||||||
|
(let [actual (generate '(:NUMERIC-EXPRESSION (:SYMBOL "sealevel")))
|
||||||
|
expected '(:sealevel cell)]
|
||||||
|
(is (= actual expected)))))
|
||||||
|
|
||||||
(deftest lhs-generators-tests
|
(deftest lhs-generators-tests
|
||||||
(testing "Generating left-hand-side fragments of rule functions from appropriate fragments of parse trees"
|
(testing "Generating left-hand-side fragments of rule functions from appropriate fragments of parse trees"
|
||||||
|
@ -85,3 +83,20 @@
|
||||||
actual-meta (meta actual)]
|
actual-meta (meta actual)]
|
||||||
(is (= actual expected))
|
(is (= actual expected))
|
||||||
(is (= actual-meta expected-meta)))))
|
(is (= actual-meta expected-meta)))))
|
||||||
|
|
||||||
|
(deftest metadata-tests
|
||||||
|
(testing "Rules have correct metadata"
|
||||||
|
(let [expected :production
|
||||||
|
actual (:rule-type
|
||||||
|
(meta
|
||||||
|
(generate
|
||||||
|
(simplify
|
||||||
|
(parse "if state is house then state should be waste")))))]
|
||||||
|
(is (= actual expected)))
|
||||||
|
(let [expected :flow
|
||||||
|
actual (:rule-type
|
||||||
|
(meta
|
||||||
|
(generate
|
||||||
|
(simplify
|
||||||
|
(parse "flow 10% food from house to house within 2 with least food")))))]
|
||||||
|
(is (= actual expected)))))
|
Loading…
Reference in a new issue