From 94cf5b3f47ac552b303b729b64cd8fae0831fb97 Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 01:34:03 -0400 Subject: [PATCH 01/10] added logic in assembler to distinguish between registers and labels and thus succeeded in getting rid of the register dependency in the assembler namespace. --- src/robotwar/assembler.clj | 76 +++++++++++++++++----------- src/robotwar/brain.clj | 2 +- test/robotwar/assembler_test.clj | 85 ++++++++++++++++---------------- 3 files changed, 91 insertions(+), 72 deletions(-) diff --git a/src/robotwar/assembler.clj b/src/robotwar/assembler.clj index b20f256..d4999e5 100644 --- a/src/robotwar/assembler.clj +++ b/src/robotwar/assembler.clj @@ -38,11 +38,10 @@ (re-seq-with-pos lex-re line))) (defn lex - "Lexes a sequence of lines. After this point, tokens - are no longer grouped by line (line numbers have been - captured in metadata, along with column numbers)." + "Lexes a sequence of lines into a sequence of sequences of tokens + (referred to in docstrings for parsing functions as lines of tokens)." [lines] - (apply concat (map-indexed lex-line lines))) + (map-indexed lex-line lines)) (defn str->int "Integer/parseInt, but returns nil on failure" @@ -58,16 +57,15 @@ (def return-err (constantly "Invalid word or symbol")) (defn parse-token - "takes a vector of reg-names and a token with a token-str field and parses the token. + "parses a token with a token-str field. needs to work with the original token map by using dissoc and into (rather than building a new one) because it contains line and column number metadata." - [{token-str :token-str :as token} reg-names] + [{token-str :token-str :as token}] (let [parser-priority - [[(set reg-names) :register] - [(set commands) :command] + [[(set commands) :command] [str->int :number] - [valid-word :label] + [valid-word :identifier] [return-err :error]]] (some (fn [[parser token-type]] @@ -76,19 +74,42 @@ :token-str))) parser-priority))) -(defn parse - "take the tokens and convert them to structured source code ready for compiling. - if there's an error, returns a different type: just the token, - outside of any sequence." - [initial-tokens reg-names] +(defn parse-line + "takes a line of tokens and runs each token through parse-token for the first + pass of determining its type. Then parse-line further divides :identifier + tokens into two types: :label if it's the only thing on its line or it follows + a 'GOTO' or a 'GOSUB', and :register otherwise. + If we encounter an error, just return the token, not a sequence of tokens." + [initial-tokens] (loop [[token & tail :as tokens] initial-tokens parsed-tokens []] (if (empty? tokens) parsed-tokens - (let [{token-type :type :as parsed-token} (parse-token token reg-names)] - (if (= token-type :error) - parsed-token - (recur tail (conj parsed-tokens parsed-token))))))) + (let [{token-type :type token-val :val :as parsed-token} (parse-token token)] + (case token-type + :error parsed-token + (:command :number) (recur tail (conj parsed-tokens parsed-token)) + :identifier (if (or (= (count initial-tokens) 1) + (#{"GOTO" "GOSUB"} (:val (last parsed-tokens)))) + (recur tail (conj parsed-tokens (assoc parsed-token :type :label))) + (recur tail (conj parsed-tokens (assoc parsed-token :type :register))))))))) + +(defn parse + "take the lines of tokens and converts them to :val and :type format. + After this point, tokens are no longer separated into sequences of sequences + according to the linebreaks in the original source code -- + if we need that information later for error reporting, it's in the metadata. + if there's an error, this function just returns the token, + outside of any sequence." + [initial-token-lines] + (loop [[token-line & tail :as token-lines] initial-token-lines + parsed-token-lines []] + (if (empty? token-lines) + parsed-token-lines + (let [parsed-line (parse-line token-line)] + (if (= (:type parsed-line) :error) + parsed-line + (recur tail (concat parsed-token-lines parsed-line))))))) (defn disambiguate-minus-signs [initial-tokens] @@ -118,12 +139,12 @@ (if (empty? tokens) result (match [token] - [{:type (:or :number :register)}] - (recur tail (conj result [(into token {:val ",", :type :command}) token])) - [(:or {:type :label} {:type :command, :val "ENDSUB"})] - (recur tail (conj result [token nil])) - [{:type :command}] - (recur (rest tail) (conj result [token (first tail)])))))) + [{:type (:or :number :register)}] + (recur tail (conj result [(into token {:val ",", :type :command}) token])) + [(:or {:type :label} {:type :command, :val "ENDSUB"})] + (recur tail (conj result [token nil])) + [{:type :command}] + (recur (rest tail) (conj result [token (first tail)])))))) ; TODO: preserve :line and :pos metadata with labels, ; when labels are transferred from the instruction list to the label map @@ -143,17 +164,16 @@ (recur tail (assoc-in result [:labels (command :val)] next-instr-num)) (recur tail (assoc-in result [:instrs next-instr-num] instr))))))) -(defn assemble [src-code reg-names] +(defn assemble [src-code] "compiles robotwar code, with error-checking beginning after the lexing step. All functions that return errors will return a map with the keyword :error, and then a token with a :val field containing the error string, and metadata containing :pos and :line fields containing the location. So far only parse implements error-checking." - (let [parse-with-reg-names #(parse % reg-names) - lexed (-> src-code split-lines strip-comments lex)] + (let [lexed (-> src-code split-lines strip-comments lex)] (reduce (fn [result step] (if (= (:type result) :error) result (step result))) lexed - [parse-with-reg-names disambiguate-minus-signs make-instr-pairs map-labels]))) + [parse disambiguate-minus-signs make-instr-pairs map-labels]))) diff --git a/src/robotwar/brain.clj b/src/robotwar/brain.clj index c206174..2583d07 100644 --- a/src/robotwar/brain.clj +++ b/src/robotwar/brain.clj @@ -15,7 +15,7 @@ :instr-ptr 0 :call-stack [] :registers registers - :obj-code (assembler/assemble src-code (keys registers))}) + :obj-code (assembler/assemble src-code)}) (defn resolve-arg [{arg-val :val arg-type :type} registers labels world read-register] "resolves an instruction argument to a numeric value diff --git a/test/robotwar/assembler_test.clj b/test/robotwar/assembler_test.clj index f11c08e..d794aa8 100644 --- a/test/robotwar/assembler_test.clj +++ b/test/robotwar/assembler_test.clj @@ -1,8 +1,7 @@ (ns robotwar.assembler-test (:use (clojure [string :only [join]] [test]) - [robotwar.assembler]) - (:require [robotwar.register :as register])) + [robotwar.assembler])) (def line1 "IF DAMAGE # D GOTO MOVE ; comment or something") (def line2 "AIM-17 TO AIM ; other comment") @@ -15,37 +14,37 @@ (def line-no-comments3 "IF X<-5 GOTO SCAN") (def multi-line ["SCAN" "6 TO AIM"]) -(def lexed-multi-line [{:token-str "SCAN"} - {:token-str "6"} - {:token-str "TO"} - {:token-str "AIM"}]) +(def lexed-multi-line [[{:token-str "SCAN"}] + [{:token-str "6"} + {:token-str "TO"} + {:token-str "AIM"}]]) -(def lexed-tokens1 [{:token-str "IF"} - {:token-str "DAMAGE"} - {:token-str "#"} - {:token-str "D"} - {:token-str "GOTO"} - {:token-str "MOVE"}]) +(def lexed-tokens1 [[{:token-str "IF"} + {:token-str "DAMAGE"} + {:token-str "#"} + {:token-str "D"} + {:token-str "GOTO"} + {:token-str "MOVE"}]]) -(def lexed-tokens2 [{:token-str "AIM"} - {:token-str "-"} - {:token-str "17"} - {:token-str "TO"} - {:token-str "AIM"}]) +(def lexed-tokens2 [[{:token-str "AIM"} + {:token-str "-"} + {:token-str "17"} + {:token-str "TO"} + {:token-str "AIM"}]]) -(def lexed-tokens3 [{:token-str "IF"} - {:token-str "X"} - {:token-str "<"} - {:token-str "-"} - {:token-str "5"} - {:token-str "GOTO"} - {:token-str "SCAN"}]) +(def lexed-tokens3 [[{:token-str "IF"} + {:token-str "X"} + {:token-str "<"} + {:token-str "-"} + {:token-str "5"} + {:token-str "GOTO"} + {:token-str "SCAN"}]]) -(def lexed-tokens4 [{:token-str "AIM"} - {:token-str "@"} - {:token-str "17"} - {:token-str "TO"} - {:token-str "AIM"}]) +(def lexed-tokens4 [[{:token-str "AIM"} + {:token-str "@"} + {:token-str "17"} + {:token-str "TO"} + {:token-str "AIM"}]]) (def parsed-tokens2 [{:val "AIM", :type :register} {:val "-", :type :command} @@ -212,47 +211,47 @@ (deftest parse-token-register (testing "parsing register token" - (is (= (parse-token {:token-str "AIM"} register/reg-names) - {:val "AIM", :type :register})))) + (is (= (parse-token {:token-str "AIM"}) + {:val "AIM", :type :identifier})))) (deftest parse-token-command-word (testing "parsing command token (word)" - (is (= (parse-token {:token-str "GOTO"} register/reg-names) + (is (= (parse-token {:token-str "GOTO"}) {:val "GOTO", :type :command})))) (deftest parse-token-command-operator (testing "parsing command token (operator)" - (is (= (parse-token {:token-str "#"} register/reg-names) + (is (= (parse-token {:token-str "#"}) {:val "#", :type :command})))) (deftest parse-token-number (testing "parsing number token" - (is (= (parse-token {:token-str "-17"} register/reg-names) + (is (= (parse-token {:token-str "-17"}) {:val -17, :type :number})))) (deftest parse-token-label (testing "parsing label token" - (is (= (parse-token {:token-str "SCAN"} register/reg-names) - {:val "SCAN", :type :label})))) + (is (= (parse-token {:token-str "SCAN"}) + {:val "SCAN", :type :identifier})))) (deftest parse-token-error (testing "parsing error token" - (is (= (parse-token {:token-str "-GOTO"} register/reg-names) + (is (= (parse-token {:token-str "-GOTO"}) {:val "Invalid word or symbol", :type :error})))) (deftest parse-tokens-minus-sign (testing "parsing tokens with a binary minus sign" - (is (= (parse lexed-tokens2 register/reg-names) + (is (= (parse lexed-tokens2) parsed-tokens2)))) (deftest parse-tokens-negative-sign (testing "parsing tokens with a unary negative sign" - (is (= (parse lexed-tokens3 register/reg-names) + (is (= (parse lexed-tokens3) parsed-tokens3)))) (deftest parse-tokens-error (testing "parsing tokens with an invalid operator" - (is (= (parse lexed-tokens4 register/reg-names) + (is (= (parse lexed-tokens4) parsed-tokens4)))) (def minus-sign-disambiguated-tokens2 parsed-tokens2) @@ -294,17 +293,17 @@ (deftest assemble-test-success (testing "compiling successfully" - (is (= (assemble (join "\n" [line1 line2 line3]) register/reg-names) + (is (= (assemble (join "\n" [line1 line2 line3])) multi-line-assembled)))) (deftest assemble-test-failure (testing "assemble results in error" - (is (= (assemble (join "\n" [line1 line2 line3 line4]) register/reg-names) + (is (= (assemble (join "\n" [line1 line2 line3 line4])) multi-line-assembled-error)))) (deftest preserving-line-and-pos-metadata-test (testing "line and pos metadata preserved through assembly process" - (is (= (meta (get-in (assemble (join "\n" [line1 line2 line3]) register/reg-names) + (is (= (meta (get-in (assemble (join "\n" [line1 line2 line3])) [:instrs 8 1])) {:line 3, :pos 14})))) From 1424d47a4c3c0fc9b8e9fd940f7c118dfd2485a9 Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 13:13:40 -0400 Subject: [PATCH 02/10] started register-test namespace, with storage-register-test --- test/robotwar/register_test.clj | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/robotwar/register_test.clj diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj new file mode 100644 index 0000000..052e16e --- /dev/null +++ b/test/robotwar/register_test.clj @@ -0,0 +1,18 @@ +(ns robotwar.register-test + (:require [clojure.test :refer :all] + [robotwar.register :refer :all] + [robotwar.world :as world])) + +(def world (world/init-world 256 256 [""])) +(def robot-path [:robots 0]) +(def reg-path [:robots 0 :brain :registers]) +(def registers (get-in world reg-path)) + +(deftest storage-register-test + (testing "can write and read to storage register's :val field" + (let [new-world (write-register (registers "A") world 42) + new-registers (get-in new-world reg-path)] + (is (= (read-register (new-registers "A") new-world) + 42)) + (is (= (get-in new-registers ["A" :val]) + 42))))) From 2f85cef47795509e585380e45650b60ec845f702 Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 13:27:48 -0400 Subject: [PATCH 03/10] removed random and index/data tests from brain-test --- test/robotwar/brain_test.clj | 40 +++++++----------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/test/robotwar/brain_test.clj b/test/robotwar/brain_test.clj index 576ccac..cb81447 100644 --- a/test/robotwar/brain_test.clj +++ b/test/robotwar/brain_test.clj @@ -5,30 +5,27 @@ [robotwar.register :as register] [robotwar.test-programs :as test-programs])) -(def initial-multi-use-world +(def initial-world (world/init-world 256 256 [test-programs/multi-use-program])) -(def initial-index-data-world - (world/init-world 256 256 [test-programs/index-data-program])) -(def multi-use-worlds (iterate world/tick-world initial-multi-use-world)) -(def index-data-worlds (iterate world/tick-world initial-index-data-world)) +(def worlds (iterate world/tick-world initial-world)) (deftest branching-test (testing "comparison statement should cause jump in instr-ptr" - (is (= (get-in (world/get-world 4 0 multi-use-worlds) + (is (= (get-in (world/get-world 4 0 worlds) [:robots 0 :brain :instr-ptr]) 5)))) (deftest arithmetic-test (testing "addition" - (is (= (get-in (world/get-world 7 0 multi-use-worlds) + (is (= (get-in (world/get-world 7 0 worlds) [:robots 0 :brain :acc]) 1)))) (deftest gosub-test (testing "gosub should move instr-ptr and add the return-ptr to the call stack" (is (let [{:keys [instr-ptr call-stack]} - (get-in (world/get-world 5 0 multi-use-worlds) + (get-in (world/get-world 5 0 worlds) [:robots 0 :brain])] (= [instr-ptr call-stack] [9 [6]]))))) @@ -36,36 +33,13 @@ (deftest endsub-test (testing "endsub pops instr-ptr off call stack and goes there" (is (let [{:keys [instr-ptr call-stack]} - (get-in (world/get-world 9 0 multi-use-worlds) + (get-in (world/get-world 9 0 worlds) [:robots 0 :brain])] (= [instr-ptr call-stack] [6 []]))))) (deftest push-test (testing "pushing number to register" - (is (= (get-in (world/get-world 8 0 multi-use-worlds) + (is (= (get-in (world/get-world 8 0 worlds) [:robots 0 :brain :registers "A" :val]) 1)))) - -(deftest index-data-pair-test - (testing "registers whose index numbers are push to INDEX can - be referenced by accessing DATA" - (is (= (get-in (world/get-world 5 0 index-data-worlds) - [:robots 0 :brain :registers "A" :val]) - 300)))) - -; last test will use a different method: -; just push and pull from one sample world and one sample robot - -(def initial-multi-use-robot ((:robots initial-multi-use-world) 0)) - -(deftest random-test - (testing "push to random register and pull a series of numbers all different - from random register" - (let [random-register (get-in initial-multi-use-robot [:brain :registers "RANDOM"]) - new-world (register/write-register random-register initial-multi-use-world 1000) - random-nums (repeatedly 5 (partial register/read-register random-register new-world))] - (is (= (get-in new-world [:robots 0 :brain :registers "RANDOM" :val]) - 1000)) - (is (every? #(< -1 % 1000) random-nums))))) - From 9e61c987c375e122a45e5c3c902fe9ca8f0073cc Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 13:28:28 -0400 Subject: [PATCH 04/10] added index/data test to register-test --- test/robotwar/register_test.clj | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj index 052e16e..cee90b1 100644 --- a/test/robotwar/register_test.clj +++ b/test/robotwar/register_test.clj @@ -16,3 +16,33 @@ 42)) (is (= (get-in new-registers ["A" :val]) 42))))) + + + + + +(deftest index-data-pair-test + (testing "registers whose index numbers are push to INDEX can + be referenced by accessing DATA" + (let [world1 (write-register (registers "A") world 42) + registers1 (get-in world1 reg-path) + world2 (write-register (registers1 "INDEX") world1 1) + registers2 (get-in world2 reg-path) + world3 (write-register (registers2 "DATA") world2 100) + registers3 (get-in world3 reg-path)] + (is (= (read-register (registers2 "DATA") world2) + 42)) + (is (= (read-register (registers3 "A") world3) + 100))))) + + +;(deftest random-test +; (testing "push to random register and pull a series of numbers all different +; from random register" +; (let [random-register (get-in initial-multi-use-robot [:brain :registers "RANDOM"]) +; new-world (register/write-register random-register initial-multi-use-world 1000) +; random-nums (repeatedly 5 (partial register/read-register random-register new-world))] +; (is (= (get-in new-world [:robots 0 :brain :registers "RANDOM" :val]) +; 1000)) +; (is (every? #(< -1 % 1000) random-nums))))) +; From 0b007c9b532cc467d1fbe35282b798d5636eb42d Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 13:41:42 -0400 Subject: [PATCH 05/10] added random-test to register-test --- test/robotwar/register_test.clj | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj index cee90b1..a6e36d5 100644 --- a/test/robotwar/register_test.clj +++ b/test/robotwar/register_test.clj @@ -17,10 +17,6 @@ (is (= (get-in new-registers ["A" :val]) 42))))) - - - - (deftest index-data-pair-test (testing "registers whose index numbers are push to INDEX can be referenced by accessing DATA" @@ -35,14 +31,15 @@ (is (= (read-register (registers3 "A") world3) 100))))) +(deftest random-test + (testing "write to random register's :val field, + and read a series of numbers all different + from random register" + (let [new-world (write-register (registers "RANDOM") world 1000) + new-registers (get-in new-world reg-path) + random-nums (repeatedly 5 (partial read-register (new-registers "RANDOM") new-world))] + (is (= (get-in new-registers ["RANDOM" :val]) + 1000)) + (is (every? #(< -1 % 1000) random-nums)) + (is (apply not= random-nums))))) -;(deftest random-test -; (testing "push to random register and pull a series of numbers all different -; from random register" -; (let [random-register (get-in initial-multi-use-robot [:brain :registers "RANDOM"]) -; new-world (register/write-register random-register initial-multi-use-world 1000) -; random-nums (repeatedly 5 (partial register/read-register random-register new-world))] -; (is (= (get-in new-world [:robots 0 :brain :registers "RANDOM" :val]) -; 1000)) -; (is (every? #(< -1 % 1000) random-nums))))) -; From d0a1933b7d2a96570fb7d6fd07ac3f07dd1fbfb5 Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 14:28:17 -0400 Subject: [PATCH 06/10] set up midje (mainly for auto-testing, for the time being) --- project.clj | 1 + test/robotwar/assembler_test.clj | 5 +++-- test/robotwar/brain_test.clj | 1 + test/robotwar/core_test.clj | 5 +++-- test/robotwar/register_test.clj | 7 ++++--- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/project.clj b/project.clj index ac0ee09..efb59c1 100644 --- a/project.clj +++ b/project.clj @@ -5,4 +5,5 @@ :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.5.1"] [org.clojure/core.match "0.2.0-rc5"]] + :profiles {:dev {:dependencies [[midje "1.5.1"]]}} :main robotwar.core) diff --git a/test/robotwar/assembler_test.clj b/test/robotwar/assembler_test.clj index d794aa8..d63dab4 100644 --- a/test/robotwar/assembler_test.clj +++ b/test/robotwar/assembler_test.clj @@ -1,6 +1,7 @@ (ns robotwar.assembler-test - (:use (clojure [string :only [join]] - [test]) + (:use [clojure.string :only [join]] + [clojure.test] + [midje.sweet] [robotwar.assembler])) (def line1 "IF DAMAGE # D GOTO MOVE ; comment or something") diff --git a/test/robotwar/brain_test.clj b/test/robotwar/brain_test.clj index cb81447..e5765c4 100644 --- a/test/robotwar/brain_test.clj +++ b/test/robotwar/brain_test.clj @@ -1,5 +1,6 @@ (ns robotwar.brain-test (:use [clojure.test] + [midje.sweet] [robotwar.brain]) (:require [robotwar.world :as world] [robotwar.register :as register] diff --git a/test/robotwar/core_test.clj b/test/robotwar/core_test.clj index d782f2e..f5a484f 100644 --- a/test/robotwar/core_test.clj +++ b/test/robotwar/core_test.clj @@ -1,3 +1,4 @@ (ns robotwar.core-test - (:require [clojure.test :refer :all] - [robotwar.core :refer :all])) + (:use [clojure.test] + [midje.sweet] + [robotwar.core])) diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj index a6e36d5..87e0458 100644 --- a/test/robotwar/register_test.clj +++ b/test/robotwar/register_test.clj @@ -1,7 +1,8 @@ (ns robotwar.register-test - (:require [clojure.test :refer :all] - [robotwar.register :refer :all] - [robotwar.world :as world])) + (:use [clojure.test] + [midje.sweet] + [robotwar.register]) + (:require [robotwar.world :as world])) (def world (world/init-world 256 256 [""])) (def robot-path [:robots 0]) From d07ab0607c967c0f7193fd9b1b5885cbdb1c50c1 Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 14:29:17 -0400 Subject: [PATCH 07/10] added get-registers helper function to registers-test --- test/robotwar/register_test.clj | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj index 87e0458..cc1236c 100644 --- a/test/robotwar/register_test.clj +++ b/test/robotwar/register_test.clj @@ -8,11 +8,12 @@ (def robot-path [:robots 0]) (def reg-path [:robots 0 :brain :registers]) (def registers (get-in world reg-path)) +(def get-registers #(get-in % reg-path)) (deftest storage-register-test (testing "can write and read to storage register's :val field" (let [new-world (write-register (registers "A") world 42) - new-registers (get-in new-world reg-path)] + new-registers (get-registers new-world)] (is (= (read-register (new-registers "A") new-world) 42)) (is (= (get-in new-registers ["A" :val]) @@ -22,11 +23,11 @@ (testing "registers whose index numbers are push to INDEX can be referenced by accessing DATA" (let [world1 (write-register (registers "A") world 42) - registers1 (get-in world1 reg-path) + registers1 (get-registers world1) world2 (write-register (registers1 "INDEX") world1 1) - registers2 (get-in world2 reg-path) + registers2 (get-registers world2) world3 (write-register (registers2 "DATA") world2 100) - registers3 (get-in world3 reg-path)] + registers3 (get-registers world3)] (is (= (read-register (registers2 "DATA") world2) 42)) (is (= (read-register (registers3 "A") world3) @@ -37,7 +38,7 @@ and read a series of numbers all different from random register" (let [new-world (write-register (registers "RANDOM") world 1000) - new-registers (get-in new-world reg-path) + new-registers (get-registers new-world) random-nums (repeatedly 5 (partial read-register (new-registers "RANDOM") new-world))] (is (= (get-in new-registers ["RANDOM" :val]) 1000)) From 99528fe9ba6c7ed5d9a29ed4516d9ba925ff5577 Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 14:29:52 -0400 Subject: [PATCH 08/10] added read-only-test to register-test --- test/robotwar/register_test.clj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj index cc1236c..f4c5435 100644 --- a/test/robotwar/register_test.clj +++ b/test/robotwar/register_test.clj @@ -45,3 +45,13 @@ (is (every? #(< -1 % 1000) random-nums)) (is (apply not= random-nums))))) +(deftest read-only-test + (testing "can read from read-only registers, but not write to them" + (let [world1 (assoc-in world [:robots 0 :damage] 50) + registers1 (get-registers world1) + world2 (write-register (registers "DAMAGE") world1 25) + registers2 (get-registers world2)] + (is (= (read-register (registers1 "DAMAGE") world1) + 50)) + (is (= (read-register (registers2 "DAMAGE") world2) + 50))))) From 43125f0e2607f7d63c6d3cf66152a6a78bd7e4be Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 14:40:10 -0400 Subject: [PATCH 09/10] added test to read-only test section of register-test new test checks to make sure the appropriate robot field got written to. --- test/robotwar/register_test.clj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj index f4c5435..40d8081 100644 --- a/test/robotwar/register_test.clj +++ b/test/robotwar/register_test.clj @@ -46,7 +46,8 @@ (is (apply not= random-nums))))) (deftest read-only-test - (testing "can read from read-only registers, but not write to them" + (testing "can read from read-only registers, but not write to them + (and also the robot fields don't get written to)" (let [world1 (assoc-in world [:robots 0 :damage] 50) registers1 (get-registers world1) world2 (write-register (registers "DAMAGE") world1 25) @@ -54,4 +55,6 @@ (is (= (read-register (registers1 "DAMAGE") world1) 50)) (is (= (read-register (registers2 "DAMAGE") world2) + 50)) + (is (= (get-in world2 [:robots 0 :damage]) 50))))) From cbcf620a00088cb903907e71a95949e0c6b8992a Mon Sep 17 00:00:00 2001 From: Richard Harrington Date: Sat, 10 Aug 2013 14:41:05 -0400 Subject: [PATCH 10/10] added read-write test to register-test --- test/robotwar/register_test.clj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/robotwar/register_test.clj b/test/robotwar/register_test.clj index 40d8081..12f1208 100644 --- a/test/robotwar/register_test.clj +++ b/test/robotwar/register_test.clj @@ -58,3 +58,13 @@ 50)) (is (= (get-in world2 [:robots 0 :damage]) 50))))) + +(deftest read-write-test + (testing "can read and write from registers that are interfaces + for robot fields, and also those robot fields get written to" + (let [new-world (write-register (registers "SPEEDX") world 90) + new-registers (get-registers new-world)] + (is (= (read-register (new-registers "SPEEDX") new-world) + 90)) + (is (= (get-in new-world [:robots 0 :desired-v-x]) + 90)))))