Merge branch 'master' of ssh://goldsmith.journeyman.cc/srv/git/mw-parser
This commit is contained in:
		
						commit
						d44ba60802
					
				
					 3 changed files with 48 additions and 40 deletions
				
			
		| 
						 | 
					@ -8,32 +8,32 @@
 | 
				
			||||||
        [clojure.string :only [split trim]])
 | 
					        [clojure.string :only [split trim]])
 | 
				
			||||||
  (:import (java.io BufferedReader StringReader)))
 | 
					  (:import (java.io BufferedReader StringReader)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn comment? 
 | 
					(defn comment?
 | 
				
			||||||
  "Is this `line` a comment?"
 | 
					  "Is this `line` a comment?"
 | 
				
			||||||
  [line]
 | 
					  [line]
 | 
				
			||||||
  (or (empty? (trim line)) (member? (first line) '(nil \# \;))))
 | 
					  (or (empty? (trim line)) (member? (first line) '(nil \# \;))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn parse-string 
 | 
					(defn parse-string
 | 
				
			||||||
  "Parse rules from successive lines in this `string`, assumed to have multiple
 | 
					  "Parse rules from successive lines in this `string`, assumed to have multiple
 | 
				
			||||||
   lines delimited by the new-line character. Return a list of S-expressions."
 | 
					   lines delimited by the new-line character. Return a list of S-expressions."
 | 
				
			||||||
  [string]
 | 
					  [string]
 | 
				
			||||||
        ;; TODO: tried to do this using with-open, but couldn't make it work.
 | 
					        ;; TODO: tried to do this using with-open, but couldn't make it work.
 | 
				
			||||||
  (map parse-rule (remove comment? (split string #"\n"))))
 | 
					  (map parse-rule (remove comment? (split string #"\n"))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn parse-file 
 | 
					(defn parse-file
 | 
				
			||||||
  "Parse rules from successive lines in the file loaded from this `filename`.
 | 
					  "Parse rules from successive lines in the file loaded from this `filename`.
 | 
				
			||||||
   Return a list of S-expressions."
 | 
					   Return a list of S-expressions."
 | 
				
			||||||
  [filename]
 | 
					  [filename]
 | 
				
			||||||
  (parse-string (slurp filename)))
 | 
					  (parse-string (slurp filename)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn compile-string
 | 
					(defn compile-string
 | 
				
			||||||
  "Compile each non-comment line of this `string` into an executable anonymous 
 | 
					  "Compile each non-comment line of this `string` into an executable anonymous
 | 
				
			||||||
   function, and return the sequence of such functions."
 | 
					   function, and return the sequence of such functions."
 | 
				
			||||||
  [string]
 | 
					  [string]
 | 
				
			||||||
  (map #(compile-rule % true) (remove comment? (split string #"\n"))))
 | 
					  (map #(compile-rule % true) (remove comment? (split string #"\n"))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn compile-file 
 | 
					(defn compile-file
 | 
				
			||||||
  "Compile each non-comment line of the file indicated by this `filename` into 
 | 
					  "Compile each non-comment line of the file indicated by this `filename` into
 | 
				
			||||||
   an executable anonymous function, and return the sequence of such functions."
 | 
					   an executable anonymous function, and return the sequence of such functions."
 | 
				
			||||||
  [filename]
 | 
					  [filename]
 | 
				
			||||||
  (compile-string (slurp filename)))
 | 
					  (compile-string (slurp filename)))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,22 +118,28 @@
 | 
				
			||||||
(defn generate-ranged-property-condition
 | 
					(defn generate-ranged-property-condition
 | 
				
			||||||
  "Generate a property condition where the expression is a numeric range"
 | 
					  "Generate a property condition where the expression is a numeric range"
 | 
				
			||||||
  [tree property expression]
 | 
					  [tree property expression]
 | 
				
			||||||
  (assert-type tree :PROPERTY-CONDITION)
 | 
					   (assert-type tree :PROPERTY-CONDITION)
 | 
				
			||||||
  (assert-type (nth tree 3) :RANGE-EXPRESSION)
 | 
					   (assert-type (nth tree 3) :RANGE-EXPRESSION)
 | 
				
			||||||
  (let [l1 (generate (nth expression 2))
 | 
					   (let [l1 (generate (nth expression 2))
 | 
				
			||||||
        l2 (generate (nth expression 4))
 | 
					         l2 (generate (nth expression 4))
 | 
				
			||||||
        pv (list property 'cell)]
 | 
					         pv (list property 'cell)]
 | 
				
			||||||
    (list 'let ['lower (list 'min l1 l2)
 | 
					     (list 'let ['lower (list 'min l1 l2)
 | 
				
			||||||
                'upper (list 'max l1 l2)]
 | 
					                 'upper (list 'max l1 l2)]
 | 
				
			||||||
          (list 'and (list '>= pv 'lower)(list '<= pv 'upper)))))
 | 
					           (list 'and (list '>= pv 'lower)(list '<= pv 'upper)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn generate-disjunct-condition
 | 
					(defn generate-disjunct-property-condition
 | 
				
			||||||
  "Generate a property condition where the expression is a disjunct expression"
 | 
					  "Generate a property condition where the expression is a disjunct expression.
 | 
				
			||||||
  [tree property qualifier expression]
 | 
					  TODO: this is definitely still wrong!"
 | 
				
			||||||
  (let [e (list 'some (list 'fn ['i] '(= i value)) (list 'quote expression))]
 | 
					  ([tree]
 | 
				
			||||||
    (list 'let ['value (list property 'cell)]
 | 
					   (let [property (generate (nth tree 1))
 | 
				
			||||||
          (if (= qualifier '=) e
 | 
					         qualifier (generate (nth tree 2))
 | 
				
			||||||
            (list 'not e)))))
 | 
					         expression (generate (nth tree 3))]
 | 
				
			||||||
 | 
					     (generate-disjunct-property-condition tree property qualifier expression)))
 | 
				
			||||||
 | 
					  ([tree property qualifier expression]
 | 
				
			||||||
 | 
					   (let [e (list 'some (list 'fn ['i] '(= i value)) (list 'quote expression))]
 | 
				
			||||||
 | 
					     (list 'let ['value (list property 'cell)]
 | 
				
			||||||
 | 
					           (if (= qualifier '=) e
 | 
				
			||||||
 | 
					             (list 'not e))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn generate-property-condition
 | 
					(defn generate-property-condition
 | 
				
			||||||
  ([tree]
 | 
					  ([tree]
 | 
				
			||||||
| 
						 | 
					@ -145,7 +151,7 @@
 | 
				
			||||||
         qualifier (generate (nth tree 2))
 | 
					         qualifier (generate (nth tree 2))
 | 
				
			||||||
         expression (generate (nth tree 3))]
 | 
					         expression (generate (nth tree 3))]
 | 
				
			||||||
     (case expression-type
 | 
					     (case expression-type
 | 
				
			||||||
       :DISJUNCT-EXPRESSION (generate-disjunct-condition tree property qualifier expression)
 | 
					       :DISJUNCT-EXPRESSION (generate-disjunct-property-condition tree property qualifier expression)
 | 
				
			||||||
       :RANGE-EXPRESSION (generate-ranged-property-condition tree property expression)
 | 
					       :RANGE-EXPRESSION (generate-ranged-property-condition tree property expression)
 | 
				
			||||||
       (list qualifier (list property 'cell) expression)))))
 | 
					       (list qualifier (list property 'cell) expression)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,10 +165,9 @@
 | 
				
			||||||
      (list 'merge 'cell {property expression}))))
 | 
					      (list 'merge 'cell {property expression}))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn generate-multiple-actions
 | 
					(defn generate-multiple-actions
 | 
				
			||||||
   [tree]
 | 
					  [tree]
 | 
				
			||||||
  nil)
 | 
					  (assert (and (coll? tree)(= (first tree) :ACTIONS)) "Expected an ACTIONS fragment")
 | 
				
			||||||
;;   (assert (and (coll? tree)(= (first tree) :ACTIONS)) "Expected an ACTIONS fragment")
 | 
					  (conj 'do (map generate-simple-action (rest tree))))
 | 
				
			||||||
;;   (conj 'do (map
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn generate-disjunct-value
 | 
					(defn generate-disjunct-value
 | 
				
			||||||
  "Generate a disjunct value. Essentially what we need here is to generate a
 | 
					  "Generate a disjunct value. Essentially what we need here is to generate a
 | 
				
			||||||
| 
						 | 
					@ -269,6 +274,8 @@
 | 
				
			||||||
      (map generate tree))
 | 
					      (map generate tree))
 | 
				
			||||||
    tree))
 | 
					    tree))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(generate '(:PROPERTY-CONDITION (:SYMBOL "wolves") (:QUALIFIER (:COMPARATIVE-QUALIFIER (:IS "are") (:MORE "more") (:THAN "than"))) (:SYMBOL "deer")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defn simplify-qualifier
 | 
					(defn simplify-qualifier
 | 
				
			||||||
  "Given that this `tree` fragment represents a qualifier, what
 | 
					  "Given that this `tree` fragment represents a qualifier, what
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -179,13 +179,14 @@
 | 
				
			||||||
             (is (nil? (apply afn (list {:altitude 200} nil)))
 | 
					             (is (nil? (apply afn (list {:altitude 200} nil)))
 | 
				
			||||||
                 "Rule does not fire when condition is not met")))
 | 
					                 "Rule does not fire when condition is not met")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (testing "Property is more than property"
 | 
					;; TODO: this one is very tricky and will require a rethink of the way conditions are parsed.
 | 
				
			||||||
           (let [afn (compile-rule "if wolves are more than deer then deer should be 0")]
 | 
					;;   (testing "Property is more than property"
 | 
				
			||||||
             (is (= (apply afn (list {:deer 2 :wolves 3} nil))
 | 
					;;            (let [afn (compile-rule "if wolves are more than deer then deer should be 0")]
 | 
				
			||||||
                    {:deer 0 :wolves 3})
 | 
					;;              (is (= (apply afn (list {:deer 2 :wolves 3} nil))
 | 
				
			||||||
                 "Rule fires when condition is met")
 | 
					;;                     {:deer 0 :wolves 3})
 | 
				
			||||||
             (is (nil? (apply afn (list {:deer 3 :wolves 2} nil)))
 | 
					;;                  "Rule fires when condition is met")
 | 
				
			||||||
                 "Rule does not fire when condition is not met")))
 | 
					;;              (is (nil? (apply afn (list {:deer 3 :wolves 2} nil)))
 | 
				
			||||||
 | 
					;;                  "Rule does not fire when condition is not met")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (testing "Property is less than numeric-value"
 | 
					  (testing "Property is less than numeric-value"
 | 
				
			||||||
           (let [afn (compile-rule "if altitude is less than 10 then state should be water")]
 | 
					           (let [afn (compile-rule "if altitude is less than 10 then state should be water")]
 | 
				
			||||||
| 
						 | 
					@ -195,13 +196,13 @@
 | 
				
			||||||
             (is (nil? (apply afn (list {:altitude 10} nil)))
 | 
					             (is (nil? (apply afn (list {:altitude 10} nil)))
 | 
				
			||||||
                 "Rule does not fire when condition is not met")))
 | 
					                 "Rule does not fire when condition is not met")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (testing "Property is less than property"
 | 
					;;   (testing "Property is less than property"
 | 
				
			||||||
           (let [afn (compile-rule "if wolves are less than deer then deer should be deer - wolves")]
 | 
					;;            (let [afn (compile-rule "if wolves are less than deer then deer should be deer - wolves")]
 | 
				
			||||||
             (is (= (apply afn (list {:deer 3 :wolves 2} nil))
 | 
					;;              (is (= (apply afn (list {:deer 3 :wolves 2} nil))
 | 
				
			||||||
                    {:deer 1 :wolves 2})
 | 
					;;                     {:deer 1 :wolves 2})
 | 
				
			||||||
                 "Rule fires when condition is met")
 | 
					;;                  "Rule fires when condition is met")
 | 
				
			||||||
             (is (nil? (apply afn (list {:deer 2 :wolves 3} nil)))
 | 
					;;              (is (nil? (apply afn (list {:deer 2 :wolves 3} nil)))
 | 
				
			||||||
                 "Rule does not fire when condition is not met")))
 | 
					;;                  "Rule does not fire when condition is not met")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (testing "Number neighbours have property equal to value"
 | 
					  (testing "Number neighbours have property equal to value"
 | 
				
			||||||
           (let [afn (compile-rule "if 3 neighbours have state equal to new then state should be water")
 | 
					           (let [afn (compile-rule "if 3 neighbours have state equal to new then state should be water")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue