From e21ca24d9deda942d0f29e63c6cad0b5430722c4 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 21:59:02 -0500 Subject: [PATCH 01/39] Add test for `string/butlast` This adds a test for the `string/butlast` instruction --- .../push/instructions/string_spec.clj | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/propeller/push/instructions/string_spec.clj diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj new file mode 100644 index 0000000..7f5b76d --- /dev/null +++ b/test/propeller/push/instructions/string_spec.clj @@ -0,0 +1,27 @@ +(ns propeller.push.instructions.string-spec + (:require + [clojure.test.check.generators :as gen] + [clojure.test.check.properties :as prop] + [clojure.test.check.clojure-test :as ct :refer [defspec]] + [propeller.push.state :as state] + [propeller.push.core :as core] + [propeller.push.instructions.string :as string])) + + +;; string/butlast + +(defn check-butlast + [value] + (let [start-state (state/push-to-stack state/empty-state + :string + value) + end-state ((:string_butlast @core/instruction-table) start-state) + expected-result (apply str (butlast value))] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec butlast-spec 100 + (prop/for-all [s gen/string] + (check-butlast s))) + + From d73b7c6117c3eabf4bdaf0dfcf3cab113f979943 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 22:18:37 -0500 Subject: [PATCH 02/39] Add test for `string/concat` This adds a test for the `string/concat` instruction --- test/propeller/push/instructions/string_spec.clj | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 7f5b76d..dd4c803 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -25,3 +25,19 @@ (check-butlast s))) +;; string/concat + +(defn check-concat + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value1) + (state/push-to-stack :string value2)) + end-state ((:string_concat @core/instruction-table) start-state) + expected-result (str value1 value2)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec concat-spec 100 + (prop/for-all [s1 gen/string + s2 gen/string] + (check-concat s1 s2))) \ No newline at end of file From f028b7005d3b60cf7c2483142fb9890ec8efc8cf Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 22:27:20 -0500 Subject: [PATCH 03/39] Add test for `string/conj-char` This adds a test for the `string/conj-char` instruction --- .../push/instructions/string_spec.clj | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index dd4c803..8b4dc61 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -40,4 +40,22 @@ (defspec concat-spec 100 (prop/for-all [s1 gen/string s2 gen/string] - (check-concat s1 s2))) \ No newline at end of file + (check-concat s1 s2))) + + +;; string/conj-char + +(defn check-conj-char + [value char] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char)) + end-state ((:string_concat @core/instruction-table) start-state) + expected-result (str value char)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec conj-char-spec 100 + (prop/for-all [str gen/string + char gen/char] + (check-concat str char))) \ No newline at end of file From 227a41b3762703c1fb5110bda9a1113c69f164c8 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 22:43:59 -0500 Subject: [PATCH 04/39] Add test for `string/contains` This adds a test for the `string/contains` instruction --- .../push/instructions/string_spec.clj | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 8b4dc61..10700a4 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -58,4 +58,22 @@ (defspec conj-char-spec 100 (prop/for-all [str gen/string char gen/char] - (check-concat str char))) \ No newline at end of file + (check-concat str char))) + + +;; string/contains + +(defn check-contains + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value1) + (state/push-to-stack :string value2)) + end-state ((:string_contains @core/instruction-table) start-state) + expected-result (string/includes? value2 value1)] + (= expected-result + (state/peek-stack end-state :boolean)))) + +(defspec contains-spec 100 + (prop/for-all [str1 gen/string + str2 gen/string] + (check-contains str1 str2))) \ No newline at end of file From ca311c9f36499c811964be6d6fb0be749c1013a0 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 22:47:41 -0500 Subject: [PATCH 05/39] Fix `string/contains` This fixes `string/contains` to be consistent with it's descriptions, as well as it's implementation in Clojush --- src/propeller/push/instructions/string.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/propeller/push/instructions/string.cljc b/src/propeller/push/instructions/string.cljc index 7d88e03..445373b 100755 --- a/src/propeller/push/instructions/string.cljc +++ b/src/propeller/push/instructions/string.cljc @@ -38,7 +38,7 @@ :string_contains ^{:stacks #{:boolean :string}} (fn [state] - (make-instruction state string/includes? [:string :string] :boolean))) + (make-instruction state #(string/includes? %2 %1) [:string :string] :boolean))) ;; Pushes TRUE if the top CHAR is contained in the top STRING, and FALSE ;; otherwise From 54e09010405cece33864c8225f0b675c012d0408 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 22:49:49 -0500 Subject: [PATCH 06/39] Change naming of some variables and fix `string/conj-char` This fixes `string/conj-char` to actually run the correct instruction instead of `string/concat`. Additionally, changes the name of some variables. --- test/propeller/push/instructions/string_spec.clj | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 10700a4..a10936c 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -1,11 +1,12 @@ (ns propeller.push.instructions.string-spec (:require + [clojure.string :as string] [clojure.test.check.generators :as gen] [clojure.test.check.properties :as prop] [clojure.test.check.clojure-test :as ct :refer [defspec]] [propeller.push.state :as state] [propeller.push.core :as core] - [propeller.push.instructions.string :as string])) + [propeller.push.instructions.string :as string-instructions])) ;; string/butlast @@ -21,8 +22,8 @@ (state/peek-stack end-state :string)))) (defspec butlast-spec 100 - (prop/for-all [s gen/string] - (check-butlast s))) + (prop/for-all [str gen/string] + (check-butlast str))) ;; string/concat @@ -38,9 +39,9 @@ (state/peek-stack end-state :string)))) (defspec concat-spec 100 - (prop/for-all [s1 gen/string - s2 gen/string] - (check-concat s1 s2))) + (prop/for-all [str1 gen/string + str2 gen/string] + (check-concat str1 str2))) ;; string/conj-char @@ -50,7 +51,7 @@ (let [start-state (-> state/empty-state (state/push-to-stack :string value) (state/push-to-stack :char char)) - end-state ((:string_concat @core/instruction-table) start-state) + end-state ((:string_conj-char @core/instruction-table) start-state) expected-result (str value char)] (= expected-result (state/peek-stack end-state :string)))) From 54c44a49b642aed16e739c1c5f4207a69890c5ec Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 22:54:07 -0500 Subject: [PATCH 07/39] Add test for `string/contains-char` This adds a test for the `string/contains-char` instruction --- .../push/instructions/string_spec.clj | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index a10936c..c4a9486 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -77,4 +77,22 @@ (defspec contains-spec 100 (prop/for-all [str1 gen/string str2 gen/string] - (check-contains str1 str2))) \ No newline at end of file + (check-contains str1 str2))) + + +;; string/contains-char + +(defn check-contains-char + [value char] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char)) + end-state ((:string_contains-char @core/instruction-table) start-state) + expected-result (string/includes? value char)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec contains-char-spec 100 + (prop/for-all [str gen/string + char gen/string] + (check-concat str char))) \ No newline at end of file From f14d738669809d6811d3e873fe1cef398d7ea44c Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 23:22:04 -0500 Subject: [PATCH 08/39] Fix some issues with the `string/contains-char` test Fixes the test to actually run `check-contains-char` as well as some issues with that function. Also fixes similar problems with the `string/conj-char` test. --- test/propeller/push/instructions/string_spec.clj | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index c4a9486..493f087 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -51,7 +51,7 @@ (let [start-state (-> state/empty-state (state/push-to-stack :string value) (state/push-to-stack :char char)) - end-state ((:string_conj-char @core/instruction-table) start-state) + end-state ((:string_conj_char @core/instruction-table) start-state) expected-result (str value char)] (= expected-result (state/peek-stack end-state :string)))) @@ -59,7 +59,7 @@ (defspec conj-char-spec 100 (prop/for-all [str gen/string char gen/char] - (check-concat str char))) + (check-conj-char str char))) ;; string/contains @@ -87,9 +87,15 @@ (let [start-state (-> state/empty-state (state/push-to-stack :string value) (state/push-to-stack :char char)) - end-state ((:string_contains-char @core/instruction-table) start-state) - expected-result (string/includes? value char)] + end-state ((:string_contains_char @core/instruction-table) start-state) + expected-result (string/includes? value (str char))] (= expected-result + (state/peek-stack end-state :boolean)))) + +(defspec contains-char-spec 100 + (prop/for-all [str gen/string + char gen/char] + (check-contains-char str char))) (state/peek-stack end-state :string)))) (defspec contains-char-spec 100 From 19b67cdfecbf85ea040f5c2de5bd5a666c2b389e Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 16 Mar 2021 23:22:40 -0500 Subject: [PATCH 09/39] Add test for `string/drop` This adds a test for the `string/drop` instruction --- .../push/instructions/string_spec.clj | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 493f087..50ea2de 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -96,9 +96,21 @@ (prop/for-all [str gen/string char gen/char] (check-contains-char str char))) + + +;; string/drop + +(defn check-drop + [value n] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :integer n)) + end-state ((:string_drop @core/instruction-table) start-state) + expected-result (apply str (drop n value))] + (= expected-result (state/peek-stack end-state :string)))) -(defspec contains-char-spec 100 +(defspec drop-spec 100 (prop/for-all [str gen/string - char gen/string] - (check-concat str char))) \ No newline at end of file + int gen/small-integer] + (check-drop str int))) \ No newline at end of file From 50804b7cb879aee2b513f0d613908e361da3609f Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 18 Mar 2021 22:32:11 -0500 Subject: [PATCH 10/39] Add test for `string/empty-string` This adds a test for the `string/empty-string` instruction --- .../propeller/push/instructions/string_spec.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 50ea2de..18af4b2 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -113,4 +113,19 @@ (defspec drop-spec 100 (prop/for-all [str gen/string int gen/small-integer] - (check-drop str int))) \ No newline at end of file + (check-drop str int))) + + +;; string/empty-string + +(defn check-empty-string + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_empty_string @core/instruction-table) start-state) + expected-result (empty? value)] + (= expected-result + (state/peek-stack end-state :boolean)))) + +(defspec empty-string-spec 100 + (prop/for-all [str gen/string] + (check-empty-string str))) \ No newline at end of file From 2008712e0afc857cdfccb4f32da74f022bc9dc56 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 18 Mar 2021 22:48:15 -0500 Subject: [PATCH 11/39] Add test for `string/first` This adds a test for the `string/first` instruction --- .../push/instructions/string_spec.clj | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 18af4b2..e9e0f6a 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -128,4 +128,24 @@ (defspec empty-string-spec 100 (prop/for-all [str gen/string] - (check-empty-string str))) \ No newline at end of file + (check-empty-string str))) + + +;; string/first + +(defn check-first + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_first @core/instruction-table) start-state) + expected-result (first value)] + (or + (and (empty? value) + (= (state/peek-stack end-state :string) value) + (state/empty-stack? end-state :char)) + (and (= expected-result + (state/peek-stack end-state :char)) + (state/empty-stack? end-state :string))))) + +(defspec first-spec 100 + (prop/for-all [str gen/string] + (check-first str))) \ No newline at end of file From 39a25fa7e30183af160e1ecb4b71cb096640c06d Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 18 Mar 2021 22:49:44 -0500 Subject: [PATCH 12/39] Change the `string/first` instruction This changes the `string/first` instruction to return :ignore-instruction if the string is empty. --- src/propeller/push/instructions/string.cljc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/propeller/push/instructions/string.cljc b/src/propeller/push/instructions/string.cljc index 445373b..f8ddeae 100755 --- a/src/propeller/push/instructions/string.cljc +++ b/src/propeller/push/instructions/string.cljc @@ -68,7 +68,9 @@ :string_first ^{:stacks #{:char :string}} (fn [state] - (make-instruction state first [:string] :char))) + (make-instruction state + #(if (empty? %) :ignore-instruction (first %)) + [:string] :char))) ;; Pushes the STRING version of the top BOOLEAN, e.g. "true" (def-instruction From 196f39ccb6f86870bff7cf2ee48c174cd7fe531a Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 18 Mar 2021 23:01:09 -0500 Subject: [PATCH 13/39] Add a test for `string/from-boolean` This adds a test for the `string/from-boolean` instruction --- .../propeller/push/instructions/string_spec.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index e9e0f6a..1f29a4f 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -148,4 +148,19 @@ (defspec first-spec 100 (prop/for-all [str gen/string] - (check-first str))) \ No newline at end of file + (check-first str))) + + +;; string/from-boolean + +(defn check-from-boolean + [value] + (let [start-state (state/push-to-stack state/empty-state :boolean value) + end-state ((:string_from_boolean @core/instruction-table) start-state) + expected-result (str value)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec from-boolean-spec 10 + (prop/for-all [bool gen/boolean] + (check-from-boolean bool))) \ No newline at end of file From d3b876492c2d640c8322d7336beefdc6eca74082 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 18 Mar 2021 23:05:13 -0500 Subject: [PATCH 14/39] Add a test for `string/from-char` This adds a test for the `string/from-char` instruction --- .../propeller/push/instructions/string_spec.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 1f29a4f..6c2b571 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -163,4 +163,19 @@ (defspec from-boolean-spec 10 (prop/for-all [bool gen/boolean] - (check-from-boolean bool))) \ No newline at end of file + (check-from-boolean bool))) + + +;; string/from-char + +(defn check-from-char + [value] + (let [start-state (state/push-to-stack state/empty-state :char value) + end-state ((:string_from_char @core/instruction-table) start-state) + expected-result (str value)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec from-char-spec 10 + (prop/for-all [char gen/char] + (check-from-char char))) \ No newline at end of file From 2da8ef6de52c3a2b76f898bda0b82b40649f6c79 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 18 Mar 2021 23:11:31 -0500 Subject: [PATCH 15/39] Add a test for `string/from-char` This adds a test for the `string/from-char` instruction --- .../push/instructions/string_spec.clj | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 6c2b571..4349e8f 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -176,6 +176,21 @@ (= expected-result (state/peek-stack end-state :string)))) -(defspec from-char-spec 10 +(defspec from-char-spec 100 (prop/for-all [char gen/char] - (check-from-char char))) \ No newline at end of file + (check-from-char char))) + + +;; string/from-float + +(defn check-from-float + [value] + (let [start-state (state/push-to-stack state/empty-state :float value) + end-state ((:string_from_float @core/instruction-table) start-state) + expected-result (str value)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec from-float-spec 100 + (prop/for-all [float gen/double] + (check-from-boolean float))) \ No newline at end of file From b8a011c385ebabb1afe677a422fea426005395e6 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 18 Mar 2021 23:16:41 -0500 Subject: [PATCH 16/39] Add a test for `string/from-float` This adds a test for the `string/from-float` instruction --- .../propeller/push/instructions/string_spec.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 4349e8f..c32ae2c 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -193,4 +193,19 @@ (defspec from-float-spec 100 (prop/for-all [float gen/double] - (check-from-boolean float))) \ No newline at end of file + (check-from-float float))) + + +;; string/from-integer + +(defn check-from-integer + [value] + (let [start-state (state/push-to-stack state/empty-state :integer value) + end-state ((:string_from_integer @core/instruction-table) start-state) + expected-result (str value)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec from-integer-spec 100 + (prop/for-all [int gen/small-integer] + (check-from-integer int))) \ No newline at end of file From 92cdfe9e590db8ae78eef809a3c5fe685a13d68a Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Sun, 21 Mar 2021 00:39:25 -0500 Subject: [PATCH 17/39] Add a test for `string/indexof-char` This adds a test for the `string/indexof-char` instruction --- .../push/instructions/string_spec.clj | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index c32ae2c..363f4fa 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -208,4 +208,27 @@ (defspec from-integer-spec 100 (prop/for-all [int gen/small-integer] - (check-from-integer int))) \ No newline at end of file + (check-from-integer int))) + + +;; string/indexof-char + +(defn check-indexof-char + [value char] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char)) + end-state ((:string_indexof_char @core/instruction-table) start-state) + expected-result (string/index-of value char)] + (or + (and (not expected-result) + (= (state/peek-stack end-state :string) value) + (= (state/peek-stack end-state :char) char) + (state/empty-stack? end-state :integer)) + (= expected-result + (state/peek-stack end-state :integer))))) + +(defspec indexof-char-spec 100 + (prop/for-all [str gen/string + char gen/char] + (check-indexof-char str char))) \ No newline at end of file From 9cd4f875c2dbe91c216285b088cb11dfa331bf70 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Sun, 21 Mar 2021 01:02:11 -0500 Subject: [PATCH 18/39] Fix `string/indexof-char` Changes `string/indexof-char` to return :ignore-instruction if the character is not present in the string. This makes it consistent with it's description --- src/propeller/push/instructions/string.cljc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/propeller/push/instructions/string.cljc b/src/propeller/push/instructions/string.cljc index f8ddeae..46d9811 100755 --- a/src/propeller/push/instructions/string.cljc +++ b/src/propeller/push/instructions/string.cljc @@ -106,7 +106,11 @@ :string_indexof_char ^{:stacks #{:char :integer :string}} (fn [state] - (make-instruction state string/index-of [:string :char] :integer))) + (make-instruction state + #(let [index (string/index-of %1 %2)] + (if index index :ignore-instruction)) + [:string :char] + :integer))) ;; Iterates over the top STRING using code on the EXEC stack (def-instruction From c270ce6c1a6ac5676a03c9c08a9725cb0359ef36 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 23 Mar 2021 22:18:28 -0500 Subject: [PATCH 19/39] Add test for `string/last` This adds a test for the `string/last` instruction --- .../propeller/push/instructions/string_spec.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 363f4fa..07c9f48 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -231,4 +231,19 @@ (defspec indexof-char-spec 100 (prop/for-all [str gen/string char gen/char] - (check-indexof-char str char))) \ No newline at end of file + (check-indexof-char str char))) + + +;; string/last + +(defn check-last + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_last @core/instruction-table) start-state) + expected-result (last value)] + (= expected-result + (state/peek-stack end-state :char)))) + +(defspec last-spec 100 + (prop/for-all [str gen/string] + (check-last str))) \ No newline at end of file From acdc225c71ebd35c950beb56af2f8bfc379cab62 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 23 Mar 2021 22:30:18 -0500 Subject: [PATCH 20/39] Add a test for `string/length` This adds a test for the `string/length` instruction --- .../propeller/push/instructions/string_spec.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 07c9f48..0a52ecf 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -246,4 +246,19 @@ (defspec last-spec 100 (prop/for-all [str gen/string] - (check-last str))) \ No newline at end of file + (check-last str))) + + +;; string/length + +(defn check-length + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_length @core/instruction-table) start-state) + expected-result (count value)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec length-spec 100 + (prop/for-all [str gen/string] + (check-length str))) \ No newline at end of file From 7aad934b9676694d08cec266e6d44c2f7d453ea2 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 23 Mar 2021 22:42:49 -0500 Subject: [PATCH 21/39] Change `string/last` Changes `string/last` to return `:ignore-instruction` if the given string is empty --- src/propeller/push/instructions/string.cljc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/propeller/push/instructions/string.cljc b/src/propeller/push/instructions/string.cljc index 46d9811..5218ff5 100755 --- a/src/propeller/push/instructions/string.cljc +++ b/src/propeller/push/instructions/string.cljc @@ -136,12 +136,13 @@ (state/push-to-stack :exec (state/peek-stack state :exec)) (state/push-to-stack :char (first top-item)))))))) -;; Pushes the last CHAR of the top STRING +;; Pushes the last CHAR of the top STRING. +;; If the string is empty, do nothing (def-instruction :string_last ^{:stacks #{:char :string}} (fn [state] - (make-instruction state last [:string] :char))) + (make-instruction state #(if (empty? %) :ignore-instruction (last %)) [:string] :char))) ;; Pushes the length of the top STRING onto the INTEGER stack (def-instruction From da117c2f08b51925df5431a5867318862861bee0 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Tue, 23 Mar 2021 22:47:46 -0500 Subject: [PATCH 22/39] Update the test for `string/length` Changes the test for the `string/length` instruction to check for an `:ignore-instruction` when the string is empty. --- test/propeller/push/instructions/string_spec.clj | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 0a52ecf..622f530 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -241,8 +241,13 @@ (let [start-state (state/push-to-stack state/empty-state :string value) end-state ((:string_last @core/instruction-table) start-state) expected-result (last value)] - (= expected-result - (state/peek-stack end-state :char)))) + (or + (and (empty? value) + (state/empty-stack? end-state :char) + (= value (state/peek-stack end-state :string))) + (and (state/empty-stack? end-state :string) + (= expected-result + (state/peek-stack end-state :char)))))) (defspec last-spec 100 (prop/for-all [str gen/string] From 8e361225aeb93d771d79eb0933ba87b58f518bbc Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Mon, 29 Mar 2021 21:01:27 -0500 Subject: [PATCH 23/39] Add test for `string/nth` This adds a test for the `string/nth` instruction --- .../push/instructions/string_spec.clj | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 622f530..4f32de4 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -266,4 +266,26 @@ (defspec length-spec 100 (prop/for-all [str gen/string] - (check-length str))) \ No newline at end of file + (check-length str))) + + +;; string/nth + +(defn check-nth + [value n] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :integer n)) + end-state ((:string_nth @core/instruction-table) start-state)] + (or + (and (empty? value) + (state/empty-stack? end-state :char) + (= value (state/peek-stack end-state :string)) + (= n (state/peek-stack end-state :integer))) + (= (nth value (mod n (count value))) + (state/peek-stack end-state :char))))) + +(defspec nth-spec 100 + (prop/for-all [str gen/string + int gen/small-integer] + (check-nth str int))) \ No newline at end of file From 695e08506ed7c864b628a0df5bba393f1264bd61 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Mon, 29 Mar 2021 21:05:35 -0500 Subject: [PATCH 24/39] Fix `string/nth` instruction This changes `string/nth` to return `:ignore-instruction` when the string is empty. Otherwise it would throw an error due to dividing by zero. --- src/propeller/push/instructions/string.cljc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/propeller/push/instructions/string.cljc b/src/propeller/push/instructions/string.cljc index 5218ff5..26398a7 100755 --- a/src/propeller/push/instructions/string.cljc +++ b/src/propeller/push/instructions/string.cljc @@ -158,7 +158,13 @@ :string_nth ^{:stacks #{:char :integer :string}} (fn [state] - (make-instruction state #(nth %2 (mod %1 (count %2))) [:integer :string] :char))) + (make-instruction state + #(let [str-length (count %2)] + (if (= 0 str-length) + :ignore-instruction + (nth %2 (mod %1 str-length)))) + [:integer :string] + :char))) ;; Pushes the number of times the top CHAR occurs in the top STRING onto the ;; INTEGER stack From 0655a5748fa26368ccdbcc0a03aef1239b245273 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 10:49:57 -0500 Subject: [PATCH 25/39] Add a test for `string/occurencesof_char` This adds a test for the `string/occurencesof_char` instruction. --- .../push/instructions/string_spec.clj | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 4f32de4..10e6343 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -234,6 +234,9 @@ (check-indexof-char str char))) +;; string/iterate + + ;; string/last (defn check-last @@ -288,4 +291,22 @@ (defspec nth-spec 100 (prop/for-all [str gen/string int gen/small-integer] - (check-nth str int))) \ No newline at end of file + (check-nth str int))) + + +;; string/occurencesof_char + +(defn check-occurencesof-char + [value char] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char)) + end-state ((:string_occurencesof_char @core/instruction-table) start-state) + expected-result (count (filter #(= char %) value))] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec occurencesof-char-spec 100 + (prop/for-all [str gen/string + char gen/char] + (check-occurencesof-char str char))) \ No newline at end of file From 95cab605763c4a6f69d6e750c2f74e8a46641e5f Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 10:55:21 -0500 Subject: [PATCH 26/39] Add a test for `string/parse-to-chars` This adds a test for the `string/parse-to-chars` instruction. --- .../push/instructions/string_spec.clj | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 10e6343..0c92c0e 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -309,4 +309,25 @@ (defspec occurencesof-char-spec 100 (prop/for-all [str gen/string char gen/char] - (check-occurencesof-char str char))) \ No newline at end of file + (check-occurencesof-char str char))) + + +;; string/parse-to-chars + +(defn check-parse-to-chars + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_parse_to_chars @core/instruction-table) start-state) + ;; Since split will return the empty string when given the empty string + string-length (if (= 0 (count value)) 1 (count value)) + expected-result (string/split value #"")] + (and + (= expected-result + (state/peek-stack-many end-state :string string-length)) + (-> end-state + (state/pop-stack-many :string string-length) + (state/empty-stack? :string))))) + +(defspec parse-to-chars-spec 100 + (prop/for-all [str gen/string] + (check-parse-to-chars str))) From da22da5014138840e33693e6134f379261593603 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 10:59:38 -0500 Subject: [PATCH 27/39] Add a test for `string/remove-char` This adds a test for the `string/remove-char` instruction --- .../push/instructions/string_spec.clj | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 0c92c0e..f29109a 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -331,3 +331,21 @@ (defspec parse-to-chars-spec 100 (prop/for-all [str gen/string] (check-parse-to-chars str))) + + +;; string/remove-char + +(defn check-remove-char + [value char] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char)) + end-state ((:string_remove_char @core/instruction-table) start-state) + expected-result (apply str (filter #(not= char %) value))] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec remove-char-spec 100 + (prop/for-all [str gen/string + char gen/char] + (check-remove-char str char))) From 95cad31e7b57311d5acf16f6dff45d409b7e473c Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 11:07:01 -0500 Subject: [PATCH 28/39] Add a test for `string/replace` This adds a test for the `string/replace` instruction --- .../push/instructions/string_spec.clj | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index f29109a..8f96c70 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -349,3 +349,23 @@ (prop/for-all [str gen/string char gen/char] (check-remove-char str char))) + + +;; string/replace + +(defn check-replace + [value1 value2 value3] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value1) + (state/push-to-stack :string value2) + (state/push-to-stack :string value3)) + end-state ((:string_replace @core/instruction-table) start-state) + expected-result (string/replace value1 value2 value3)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec replace-spec 100 + (prop/for-all [str1 gen/string + str2 gen/string + str3 gen/string] + (check-replace str1 str2 str3))) From 3fb35d7d472ce4bdae9e462f386504455427a7d8 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 11:12:26 -0500 Subject: [PATCH 29/39] Add a test for `string/replace-char` This adds a test for the `string/replace-char` instruction --- .../push/instructions/string_spec.clj | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 8f96c70..f95714f 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -369,3 +369,23 @@ str2 gen/string str3 gen/string] (check-replace str1 str2 str3))) + + +;; string/replace-char + +(defn check-replace-char + [value char1 char2] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char1) + (state/push-to-stack :char char2)) + end-state ((:string_replace_char @core/instruction-table) start-state) + expected-result (string/replace value char1 char2)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec replace-char-spec 100 + (prop/for-all [str gen/string + char1 gen/char + char2 gen/char] + (check-replace str char1 char2))) \ No newline at end of file From 110679d8f725bd7f5ec25da171ee52c21c144e86 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 11:15:40 -0500 Subject: [PATCH 30/39] Add a test for `string/replace-first` This adds a test for the `string/replace-first` instruction --- .../push/instructions/string_spec.clj | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index f95714f..0218ac0 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -388,4 +388,24 @@ (prop/for-all [str gen/string char1 gen/char char2 gen/char] - (check-replace str char1 char2))) \ No newline at end of file + (check-replace str char1 char2))) + + +;; string/replace-first + +(defn check-replace-first + [value1 value2 value3] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value1) + (state/push-to-stack :string value2) + (state/push-to-stack :string value3)) + end-state ((:string_replace_first @core/instruction-table) start-state) + expected-result (string/replace-first value1 value2 value3)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec replace-first-spec 100 + (prop/for-all [str1 gen/string + str2 gen/string + str3 gen/string] + (check-replace-first str1 str2 str3))) \ No newline at end of file From 3cdc2f7fe5887c4e82249acc8d7059eb7ff06afc Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 11:19:09 -0500 Subject: [PATCH 31/39] Add a test for `string/replace-first-char` This adds a test for the `string/replace-first-char` instruction --- .../push/instructions/string_spec.clj | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 0218ac0..a690001 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -408,4 +408,24 @@ (prop/for-all [str1 gen/string str2 gen/string str3 gen/string] - (check-replace-first str1 str2 str3))) \ No newline at end of file + (check-replace-first str1 str2 str3))) + + +;; string/replace-first-char + +(defn check-replace-first-char + [value char1 char2] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char1) + (state/push-to-stack :char char2)) + end-state ((:string_replace_first_char @core/instruction-table) start-state) + expected-result (string/replace-first value char1 char2)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec replace-first-char-spec 100 + (prop/for-all [str gen/string + char1 gen/char + char2 gen/char] + (check-replace-first-char str char1 char2))) \ No newline at end of file From 5cc3a02002f86a67c2dde2169fed9e24ba71313f Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 11:20:40 -0500 Subject: [PATCH 32/39] Fix `replace-char-spec` to use the correct function This changes `replace-char-spec` to actually use `check-replace-char` instead of `check-replace` --- test/propeller/push/instructions/string_spec.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index a690001..21d3281 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -388,7 +388,7 @@ (prop/for-all [str gen/string char1 gen/char char2 gen/char] - (check-replace str char1 char2))) + (check-replace-char str char1 char2))) ;; string/replace-first From 7e780567ec7c1060e33af92b2015b23fd1c9e672 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 11:26:55 -0500 Subject: [PATCH 33/39] Add test for `string/rest` This adds a test for the `string/rest` instruction --- .../propeller/push/instructions/string_spec.clj | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 21d3281..64707c6 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -428,4 +428,19 @@ (prop/for-all [str gen/string char1 gen/char char2 gen/char] - (check-replace-first-char str char1 char2))) \ No newline at end of file + (check-replace-first-char str char1 char2))) + + +;; string/rest + +(defn check-rest + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_rest @core/instruction-table) start-state) + expected-result (apply str (rest value))] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec rest-spec 100 + (prop/for-all [str gen/string] + (check-rest str))) From 711fc20f017f9f05da7912ddb4eb2d119fc415e0 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 11:30:02 -0500 Subject: [PATCH 34/39] Add a test for `string/reverse` This adds a test for the `string/reverse` instruction --- test/propeller/push/instructions/string_spec.clj | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 64707c6..30c738c 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -444,3 +444,18 @@ (defspec rest-spec 100 (prop/for-all [str gen/string] (check-rest str))) + + +;; string/reverse + +(defn check-reverse + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_reverse @core/instruction-table) start-state) + expected-result (apply str (reverse value))] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec reverse-spec 100 + (prop/for-all [str gen/string] + (check-reverse str))) \ No newline at end of file From 27bd7b6eb6018190bd727ecb64d6a0568f4e2c8f Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 12:03:34 -0500 Subject: [PATCH 35/39] Add a test for `string/set-char` This adds a test for the `string/set-char` instruction --- .../push/instructions/string_spec.clj | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 30c738c..f38aad8 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -458,4 +458,33 @@ (defspec reverse-spec 100 (prop/for-all [str gen/string] - (check-reverse str))) \ No newline at end of file + (check-reverse str))) + + +;; string/set-char + +(defn check-set-char + [value char n] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :char char) + (state/push-to-stack :integer n)) + end-state ((:string_set_char @core/instruction-table) start-state)] + (or + (and + (empty? value) + (= (state/peek-stack end-state :string) value) + (= (state/peek-stack end-state :char) char) + (= (state/peek-stack end-state :integer) n)) + (= + (let [index (mod n (count value)) + start (subs value 0 index) + end (subs value (+ index 1))] + (str start char end)) + (state/peek-stack end-state :string))))) + +(defspec set-char-spec 100 + (prop/for-all [str gen/string + char gen/char + int gen/small-integer] + (check-set-char str char int))) From e3d7963355786048b5be162c6b217c67d9c73c8f Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 1 Apr 2021 12:04:02 -0500 Subject: [PATCH 36/39] Fix `string/set-char` This changes `string/set-char` to throw `:ignore-instruction` when the string is empty. Otherwise the instruction throws a Divide by Zero error. --- src/propeller/push/instructions/string.cljc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/propeller/push/instructions/string.cljc b/src/propeller/push/instructions/string.cljc index 26398a7..c03ca2e 100755 --- a/src/propeller/push/instructions/string.cljc +++ b/src/propeller/push/instructions/string.cljc @@ -268,10 +268,12 @@ ^{:stacks #{:char :integer :string}} (fn [state] (make-instruction state - #(let [index (mod %2 (count %3)) + #(if (empty? %3) + :ignore-instruction + (let [index (mod %2 (count %3)) beginning (take index %3) end (drop (inc index) %3)] - (apply str (concat beginning (list %1) end))) + (apply str (concat beginning (list %1) end)))) [:char :integer :string] :string))) From 1628e669b6f9ef57e7af58285fe020b3abad6670 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 15 Apr 2021 15:12:42 -0500 Subject: [PATCH 37/39] Add a test for `string/split` This adds a test for the `string/split` instruction --- .../push/instructions/string_spec.clj | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index f38aad8..d5e6e99 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -488,3 +488,23 @@ char gen/char int gen/small-integer] (check-set-char str char int))) + + +;; string/split + +(defn check-split + [value] + (let [start-state (state/push-to-stack state/empty-state :string value) + end-state ((:string_split @core/instruction-table) start-state) + our-split (string/split (string/trim value) #"\s+") + num-items (count our-split)] + (and + (= (state/stack-size end-state :string) num-items) + (every? identity + (map = + our-split + (state/peek-stack-many end-state :string num-items)))))) + +(defspec split-spec 100 + (prop/for-all [str gen/string] + (check-split str))) \ No newline at end of file From 07ef1d3f9046ba44656e652797e52ac71d4067c0 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 15 Apr 2021 16:03:57 -0500 Subject: [PATCH 38/39] Add tests for `string/substr` and `str/take` This adds tests for the `string/substr` and `str/take` instructions. --- .../push/instructions/string_spec.clj | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index d5e6e99..11d0b78 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -507,4 +507,36 @@ (defspec split-spec 100 (prop/for-all [str gen/string] - (check-split str))) \ No newline at end of file + (check-split str))) + + +;; string/substr + +(defn check-substr + [instruction value start end] + (let [start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :integer start) + (state/push-to-stack :integer end)) + end-state ((instruction @core/instruction-table) start-state) + str-len (count value) + small (min str-len (max 0 start)) + big (min str-len (max 0 small end)) + expected-result (subs value small big)] + (= expected-result + (state/peek-stack end-state :string)))) + +(defspec substr-spec 100 + (prop/for-all + [tuple (gen/let [str gen/string + int1 (gen/large-integer* {:min -5 :max (+ 5 (count str))}) + int2 (gen/large-integer* {:min -5 :max (+ 5 (count str))})] + [:string_substr, str, int1, int2])] + (apply check-substr tuple))) + +(defspec take-spec 100 + (prop/for-all + [tuple (gen/let [str gen/string + int (gen/large-integer* {:min -5 :max (+ 5 (count str))})] + [:string_take, str, 0, int])] + (apply check-substr tuple))) \ No newline at end of file From 24630072ed64509be81f816012cc310eb7978c9d Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 15 Apr 2021 16:24:06 -0500 Subject: [PATCH 39/39] Add tests for `string/iterate` This adds a test for the `string/iterate` instruction --- .../push/instructions/string_spec.clj | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/propeller/push/instructions/string_spec.clj b/test/propeller/push/instructions/string_spec.clj index 11d0b78..d0b00fb 100644 --- a/test/propeller/push/instructions/string_spec.clj +++ b/test/propeller/push/instructions/string_spec.clj @@ -6,7 +6,8 @@ [clojure.test.check.clojure-test :as ct :refer [defspec]] [propeller.push.state :as state] [propeller.push.core :as core] - [propeller.push.instructions.string :as string-instructions])) + [propeller.push.instructions.string :as string-instructions] + [propeller.push.interpreter :as interpreter])) ;; string/butlast @@ -236,6 +237,23 @@ ;; string/iterate +(defn check-iterate + [value] + (let [print-instr (keyword "char_print") + iter-instr (keyword "string_iterate") + program [iter-instr print-instr] + start-state (-> state/empty-state + (state/push-to-stack :string value) + (state/push-to-stack :output "")) + ; 4 times the string length should be enough for this iteration, perhaps even + ; more than we strictly need. + end-state (interpreter/interpret-program program start-state (* 4 (count value)))] + (= value + (state/peek-stack end-state :output)))) + +(defspec iterate-spec 100 + (prop/for-all [value gen/string] + (check-iterate value))) ;; string/last