From d8c97e29e884681bc125b7d1608ef4143ee1227f Mon Sep 17 00:00:00 2001 From: Tom Helmuth Date: Tue, 2 Nov 2021 12:37:06 -0400 Subject: [PATCH] Moved macros and helpers to push/instructions.cljc --- src/propeller/problems/PSB2/basement.cljc | 2 +- .../problems/PSB2/bouncing_balls.cljc | 3 +- src/propeller/problems/PSB2/bowling.cljc | 2 +- src/propeller/problems/PSB2/camel_case.cljc | 2 +- src/propeller/problems/PSB2/dice_game.cljc | 2 +- src/propeller/problems/PSB2/fizz_buzz.cljc | 2 +- src/propeller/problems/PSB2/fuel_cost.cljc | 2 +- src/propeller/problems/PSB2/gcd.cljc | 2 +- src/propeller/problems/PSB2/luhn.cljc | 2 +- .../problems/PSB2/middle_character.cljc | 2 +- .../problems/PSB2/paired_digits.cljc | 2 +- .../problems/PSB2/shopping_list.cljc | 2 +- src/propeller/problems/PSB2/snow_day.cljc | 2 +- .../problems/PSB2/solve_boolean.cljc | 2 +- src/propeller/problems/PSB2/spin_words.cljc | 2 +- .../problems/PSB2/square_digits.cljc | 2 +- .../problems/PSB2/substitution_cipher.cljc | 3 +- src/propeller/problems/PSB2/twitter.cljc | 3 +- .../problems/software/number_io.cljc | 3 +- src/propeller/problems/software/smallest.cljc | 3 +- src/propeller/push/instructions.cljc | 121 +++++++++++++++++- src/propeller/push/instructions/bool.cljc | 5 +- .../push/instructions/character.cljc | 5 +- src/propeller/push/instructions/code.cljc | 5 +- .../push/instructions/input_output.cljc | 6 +- src/propeller/push/instructions/numeric.cljc | 8 +- .../push/instructions/polymorphic.cljc | 9 +- src/propeller/push/instructions/string.cljc | 6 +- src/propeller/push/instructions/vector.cljc | 7 +- src/propeller/push/interpreter.cljc | 5 +- src/propeller/push/utils/helpers.cljc | 86 ------------- src/propeller/push/utils/macros.cljc | 36 ------ src/propeller/session.cljc | 5 +- 33 files changed, 163 insertions(+), 186 deletions(-) delete mode 100755 src/propeller/push/utils/helpers.cljc delete mode 100755 src/propeller/push/utils/macros.cljc diff --git a/src/propeller/problems/PSB2/basement.cljc b/src/propeller/problems/PSB2/basement.cljc index 9358220..2ac4248 100644 --- a/src/propeller/problems/PSB2/basement.cljc +++ b/src/propeller/problems/PSB2/basement.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/bouncing_balls.cljc b/src/propeller/problems/PSB2/bouncing_balls.cljc index 4a9c599..f7e5c88 100644 --- a/src/propeller/problems/PSB2/bouncing_balls.cljc +++ b/src/propeller/problems/PSB2/bouncing_balls.cljc @@ -3,9 +3,8 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] - [clojure.pprint :as pprint] [propeller.tools.math :as math] [propeller.gp :as gp] #?(:cljs [cljs.reader :refer [read-string]]))) diff --git a/src/propeller/problems/PSB2/bowling.cljc b/src/propeller/problems/PSB2/bowling.cljc index 773fdff..70d4613 100644 --- a/src/propeller/problems/PSB2/bowling.cljc +++ b/src/propeller/problems/PSB2/bowling.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/camel_case.cljc b/src/propeller/problems/PSB2/camel_case.cljc index 5348284..99b20be 100644 --- a/src/propeller/problems/PSB2/camel_case.cljc +++ b/src/propeller/problems/PSB2/camel_case.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.metrics :as metrics] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/dice_game.cljc b/src/propeller/problems/PSB2/dice_game.cljc index bce6587..ee1ec07 100644 --- a/src/propeller/problems/PSB2/dice_game.cljc +++ b/src/propeller/problems/PSB2/dice_game.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/fizz_buzz.cljc b/src/propeller/problems/PSB2/fizz_buzz.cljc index 5a0182d..4b892e7 100644 --- a/src/propeller/problems/PSB2/fizz_buzz.cljc +++ b/src/propeller/problems/PSB2/fizz_buzz.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.metrics :as metrics] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/fuel_cost.cljc b/src/propeller/problems/PSB2/fuel_cost.cljc index 8ce4561..9d45455 100644 --- a/src/propeller/problems/PSB2/fuel_cost.cljc +++ b/src/propeller/problems/PSB2/fuel_cost.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/gcd.cljc b/src/propeller/problems/PSB2/gcd.cljc index 3fc10d3..f835853 100644 --- a/src/propeller/problems/PSB2/gcd.cljc +++ b/src/propeller/problems/PSB2/gcd.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/luhn.cljc b/src/propeller/problems/PSB2/luhn.cljc index 0e40a88..35f0b63 100644 --- a/src/propeller/problems/PSB2/luhn.cljc +++ b/src/propeller/problems/PSB2/luhn.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/middle_character.cljc b/src/propeller/problems/PSB2/middle_character.cljc index 55925e4..f9a4b18 100644 --- a/src/propeller/problems/PSB2/middle_character.cljc +++ b/src/propeller/problems/PSB2/middle_character.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.metrics :as metrics] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/paired_digits.cljc b/src/propeller/problems/PSB2/paired_digits.cljc index 4936c8d..633effb 100644 --- a/src/propeller/problems/PSB2/paired_digits.cljc +++ b/src/propeller/problems/PSB2/paired_digits.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/shopping_list.cljc b/src/propeller/problems/PSB2/shopping_list.cljc index f379f8d..7d922de 100644 --- a/src/propeller/problems/PSB2/shopping_list.cljc +++ b/src/propeller/problems/PSB2/shopping_list.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/snow_day.cljc b/src/propeller/problems/PSB2/snow_day.cljc index 1346545..fd0f94c 100644 --- a/src/propeller/problems/PSB2/snow_day.cljc +++ b/src/propeller/problems/PSB2/snow_day.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/solve_boolean.cljc b/src/propeller/problems/PSB2/solve_boolean.cljc index d9cf85b..12524d2 100644 --- a/src/propeller/problems/PSB2/solve_boolean.cljc +++ b/src/propeller/problems/PSB2/solve_boolean.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.gp :as gp] #?(:cljs [cljs.reader :refer [read-string]]))) diff --git a/src/propeller/problems/PSB2/spin_words.cljc b/src/propeller/problems/PSB2/spin_words.cljc index ed37706..5698f7a 100644 --- a/src/propeller/problems/PSB2/spin_words.cljc +++ b/src/propeller/problems/PSB2/spin_words.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.metrics :as metrics] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/square_digits.cljc b/src/propeller/problems/PSB2/square_digits.cljc index 9aa44cd..bc3bc61 100644 --- a/src/propeller/problems/PSB2/square_digits.cljc +++ b/src/propeller/problems/PSB2/square_digits.cljc @@ -3,7 +3,7 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.metrics :as metrics] [propeller.gp :as gp] diff --git a/src/propeller/problems/PSB2/substitution_cipher.cljc b/src/propeller/problems/PSB2/substitution_cipher.cljc index d297c75..3f83e64 100644 --- a/src/propeller/problems/PSB2/substitution_cipher.cljc +++ b/src/propeller/problems/PSB2/substitution_cipher.cljc @@ -3,9 +3,8 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] - [propeller.tools.math :as math] [propeller.tools.metrics :as metrics] [propeller.gp :as gp] #?(:cljs [cljs.reader :refer [read-string]]))) diff --git a/src/propeller/problems/PSB2/twitter.cljc b/src/propeller/problems/PSB2/twitter.cljc index 2d95dee..3d70851 100644 --- a/src/propeller/problems/PSB2/twitter.cljc +++ b/src/propeller/problems/PSB2/twitter.cljc @@ -3,9 +3,8 @@ [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.utils :as utils] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] - [propeller.tools.math :as math] [propeller.tools.metrics :as metrics] [propeller.gp :as gp] #?(:cljs [cljs.reader :refer [read-string]]))) diff --git a/src/propeller/problems/software/number_io.cljc b/src/propeller/problems/software/number_io.cljc index aefcc09..d356743 100755 --- a/src/propeller/problems/software/number_io.cljc +++ b/src/propeller/problems/software/number_io.cljc @@ -2,9 +2,8 @@ (:require [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.utils :as utils] - [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] #?(:cljs [cljs.reader :refer [read-string]]))) diff --git a/src/propeller/problems/software/smallest.cljc b/src/propeller/problems/software/smallest.cljc index f63887b..4c61033 100755 --- a/src/propeller/problems/software/smallest.cljc +++ b/src/propeller/problems/software/smallest.cljc @@ -2,9 +2,8 @@ (:require [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.instructions :refer [get-stack-instructions]] [propeller.utils :as utils] - [propeller.push.state :as state] [propeller.gp :as gp] #?(:cljs [cljs.reader :refer [read-string]]))) diff --git a/src/propeller/push/instructions.cljc b/src/propeller/push/instructions.cljc index 7761637..d44dd91 100644 --- a/src/propeller/push/instructions.cljc +++ b/src/propeller/push/instructions.cljc @@ -1,4 +1,9 @@ -(ns propeller.push.instructions) +(ns propeller.push.instructions + (:require [clojure.set] + [propeller.push.state :as state] + [propeller.utils :as u] + #?(:cljs [goog.string :as gstring]) + #?(:cljs [goog.string.format]))) ;; PushGP instructions are represented as keywords, and stored in an atom. They ;; can be either constant literals or functions that take and return a Push state @@ -13,3 +18,117 @@ :exec_k 2 :exec_s 3 :exec_y 1}) + + +#?(:clj + (def cls->type + {Boolean :boolean + Short :integer + Integer :integer + Long :integer + BigInteger :integer + Double :float + BigDecimal :float + Float :float + Character :char + String :string})) + +#?(:cljs + (def pred->type + [[boolean? :boolean] + [int? :integer] + [float? :float] + [string? :string] + [char? :char]])) + +(defn get-literal-type + "If a piece of data is a literal, return its corresponding stack name + e.g. `:integer`. Otherwise, return `nil`." + [data] + (or (when (vector? data) + (if (empty? data) + :generic-vector + (keyword (str "vector_" (name (get-literal-type (u/first-non-nil data))))))) + #?(:clj (cls->type (type data)) + :cljs (loop [remaining pred->type] + (let [[pred d-type] (first remaining)] + (cond + (empty? remaining) nil + (pred data) d-type + :else (recur (rest remaining)))))))) + +(defn get-vector-literal-type + "Returns the literal stack corresponding to some vector stack." + [vector-stack] + (get state/vec-stacks vector-stack)) + +(defn def-instruction + "Defines a Push instruction as a keyword-function pair, and adds it to the + instruction table" + [instruction function] + (swap! instruction-table assoc instruction function)) + +(defn make-metadata + "Given a generic function, e.g. _dup, and a stack type to instantiate it for, + e.g. :char, returns the appropriate stack metadata for that function instance" + [function stack] + (->> (:stacks (meta function)) + (replace {:elem (get-vector-literal-type stack)}) + (cons stack) + set + (assoc-in (meta function) [:stacks]) + (#(dissoc % :name)))) + +(defn generate-instructions + "Given a sequence of stacks, e.g. [:float :integer], and a sequence of suffix + function strings, e.g. [_add, _mult, _eq], automates the generation of all + possible combination instructions, which here would be :float_add, :float_mult, + :float_eq, :integer_add, :integer_mult, and :integer_eq, also transferring + and updating the generic function's stack-type metadata. For some vector + instructions, the placeholder :elem will be replaced with the stack of the + corresponding element type (e.g. for :vector_integer, with :integer)" + [stacks functions] + (doseq [stack stacks + func functions] + (let [instruction-name (keyword (str (name stack) (:name (meta func)))) + metadata (make-metadata func stack) + new-func (with-meta (partial func stack) metadata)] + (def-instruction instruction-name new-func)))) + + +(defn make-instruction + "A utility function for making Push instructions. Takes a state, a function + to apply to the args, the stacks to take the args from, and the stack to + return the result to. Applies the function to the args (popped from the + given stacks), and pushes the result onto the return-stack. + + If the function returns :ignore-instruction, then we will return the + initial state unchanged. This allows instructions to fail gracefully + without consuming stack values." + [state function arg-stacks return-stack] + (let [popped-args (state/get-args-from-stacks state arg-stacks)] + (if (= popped-args :not-enough-args) + state + (let [result (apply function (:args popped-args)) + new-state (:state popped-args)] + (if (= result :ignore-instruction) + state + (state/push-to-stack new-state return-stack result)))))) + +(defn get-stack-instructions + "Given a set of stacks, returns all instructions that operate on those stacks + only. Won't include random instructions unless :random is in the set as well" + [stacks] + (doseq [[instruction-name function] @instruction-table] + (assert + (:stacks (meta function)) + #?(:clj (format + "ERROR: Instruction %s does not have :stacks defined in metadata." + (name instruction-name)) + :cljs (gstring/format + "ERROR: Instruction %s does not have :stacks defined in metadata." + (name instruction-name))))) + (for [[instruction-name function] @instruction-table + :when (clojure.set/subset? (:stacks (meta function)) stacks)] + instruction-name)) + diff --git a/src/propeller/push/instructions/bool.cljc b/src/propeller/push/instructions/bool.cljc index 85a1ba2..620fcfa 100755 --- a/src/propeller/push/instructions/bool.cljc +++ b/src/propeller/push/instructions/bool.cljc @@ -1,7 +1,6 @@ (ns propeller.push.instructions.bool - #?(:cljs (:require-macros [propeller.push.utils.macros :refer [def-instruction]])) - (:require [propeller.push.utils.helpers :refer [make-instruction]] - #?(:clj [propeller.push.utils.macros :refer [def-instruction]]))) + (:require [propeller.push.instructions :refer [def-instruction + make-instruction]])) ;; ============================================================================= ;; BOOLEAN Instructions diff --git a/src/propeller/push/instructions/character.cljc b/src/propeller/push/instructions/character.cljc index 2f5d77b..33e064a 100755 --- a/src/propeller/push/instructions/character.cljc +++ b/src/propeller/push/instructions/character.cljc @@ -1,9 +1,8 @@ (ns propeller.push.instructions.character - #?(:cljs (:require-macros [propeller.push.utils.macros :refer [def-instruction]])) (:require [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [make-instruction]] [propeller.tools.character :as char] - #?(:clj [propeller.push.utils.macros :refer [def-instruction]]))) + [propeller.push.instructions :refer [def-instruction + make-instruction]])) ;; ============================================================================= ;; CHAR Instructions diff --git a/src/propeller/push/instructions/code.cljc b/src/propeller/push/instructions/code.cljc index 86e0478..424e558 100755 --- a/src/propeller/push/instructions/code.cljc +++ b/src/propeller/push/instructions/code.cljc @@ -1,9 +1,8 @@ (ns propeller.push.instructions.code - #?(:cljs (:require-macros [propeller.push.utils.macros :refer [def-instruction]])) (:require [propeller.utils :as utils] [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [make-instruction]] - #?(:clj [propeller.push.utils.macros :refer [def-instruction]]))) + [propeller.push.instructions :refer [def-instruction + make-instruction]])) ;; ============================================================================= ;; CODE Instructions diff --git a/src/propeller/push/instructions/input_output.cljc b/src/propeller/push/instructions/input_output.cljc index b597c7b..6dc4799 100755 --- a/src/propeller/push/instructions/input_output.cljc +++ b/src/propeller/push/instructions/input_output.cljc @@ -1,10 +1,6 @@ (ns propeller.push.instructions.input-output - #?(:cljs (:require-macros - [propeller.push.utils.macros :refer [def-instruction - generate-instructions]])) (:require [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [make-instruction]] - [propeller.push.utils.macros :refer [def-instruction + [propeller.push.instructions :refer [def-instruction generate-instructions]])) ;; ============================================================================= diff --git a/src/propeller/push/instructions/numeric.cljc b/src/propeller/push/instructions/numeric.cljc index da5f5d6..b9cbf1f 100755 --- a/src/propeller/push/instructions/numeric.cljc +++ b/src/propeller/push/instructions/numeric.cljc @@ -1,8 +1,8 @@ (ns propeller.push.instructions.numeric - (:require [propeller.push.utils.helpers :refer [make-instruction]] - [propeller.tools.math :as math] - [propeller.push.utils.macros :refer [def-instruction - generate-instructions]])) + (:require [propeller.tools.math :as math] + [propeller.push.instructions :refer [def-instruction + generate-instructions + make-instruction]])) ;; ============================================================================= ;; FLOAT and INTEGER Instructions (polymorphic) diff --git a/src/propeller/push/instructions/polymorphic.cljc b/src/propeller/push/instructions/polymorphic.cljc index 8f0c113..d744f3c 100755 --- a/src/propeller/push/instructions/polymorphic.cljc +++ b/src/propeller/push/instructions/polymorphic.cljc @@ -1,13 +1,10 @@ (ns propeller.push.instructions.polymorphic - #?(:cljs (:require-macros - [propeller.push.utils.macros :refer [def-instruction - generate-instructions]])) (:require [propeller.utils :as utils] [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [make-instruction]] [propeller.push.limits :as limit] - #?(:clj [propeller.push.utils.macros :refer [def-instruction - generate-instructions]]))) + [propeller.push.instructions :refer [def-instruction + generate-instructions + make-instruction]])) ;; ============================================================================= ;; Polymorphic Instructions diff --git a/src/propeller/push/instructions/string.cljc b/src/propeller/push/instructions/string.cljc index d602430..b7450cd 100755 --- a/src/propeller/push/instructions/string.cljc +++ b/src/propeller/push/instructions/string.cljc @@ -1,10 +1,8 @@ (ns propeller.push.instructions.string - #?(:cljs (:require-macros - [propeller.push.utils.macros :refer [def-instruction]])) (:require [clojure.string :as string] - [propeller.push.utils.helpers :refer [make-instruction]] [propeller.push.state :as state] - #?(:clj [propeller.push.utils.macros :refer [def-instruction]]))) + [propeller.push.instructions :refer [def-instruction + make-instruction]])) ;; ============================================================================= ;; STRING Instructions diff --git a/src/propeller/push/instructions/vector.cljc b/src/propeller/push/instructions/vector.cljc index a8822f2..4e4687b 100755 --- a/src/propeller/push/instructions/vector.cljc +++ b/src/propeller/push/instructions/vector.cljc @@ -1,11 +1,10 @@ (ns propeller.push.instructions.vector - #?(:cljs (:require-macros [propeller.push.utils.macros :refer [generate-instructions]])) (:require [clojure.string] [propeller.utils :as utils] [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [get-vector-literal-type - make-instruction]] - #?(:clj [propeller.push.utils.macros :refer [generate-instructions]]))) + [propeller.push.instructions :refer [generate-instructions + make-instruction + get-vector-literal-type]])) ;; ============================================================================= ;; VECTOR Instructions diff --git a/src/propeller/push/interpreter.cljc b/src/propeller/push/interpreter.cljc index 87ec56d..738537a 100755 --- a/src/propeller/push/interpreter.cljc +++ b/src/propeller/push/interpreter.cljc @@ -1,15 +1,14 @@ (ns propeller.push.interpreter (:require [propeller.push.instructions :as instructions] [propeller.push.state :as state] - [propeller.push.instructions.input-output :as io] - [propeller.push.utils.helpers :refer [get-literal-type]])) + [propeller.push.instructions.input-output :as io])) (defn interpret-one-step "Takes a Push state and executes the next instruction on the exec stack." [state] (let [popped-state (state/pop-stack state :exec) instruction (first (:exec state)) - literal-type (get-literal-type instruction)] ; nil for non-literals + literal-type (instructions/get-literal-type instruction)] ; nil for non-literals (cond ;; ;; Recognize functional instruction or input instruction diff --git a/src/propeller/push/utils/helpers.cljc b/src/propeller/push/utils/helpers.cljc deleted file mode 100755 index 4b3b818..0000000 --- a/src/propeller/push/utils/helpers.cljc +++ /dev/null @@ -1,86 +0,0 @@ -(ns propeller.push.utils.helpers - (:require [clojure.set] - [propeller.push.instructions :as instructions] - [propeller.push.state :as state] - [propeller.utils :as u] - #?(:cljs [goog.string :as gstring]) - #?(:cljs [goog.string.format]))) - -;; A utility function for making Push instructions. Takes a state, a function -;; to apply to the args, the stacks to take the args from, and the stack to -;; return the result to. Applies the function to the args (popped from the -;; given stacks), and pushes the result onto the return-stack. -;; -;; If the function returns :ignore-instruction, then we will return the -;; initial state unchanged. This allows instructions to fail gracefully -;; without consuming stack values. -(defn make-instruction - [state function arg-stacks return-stack] - (let [popped-args (state/get-args-from-stacks state arg-stacks)] - (if (= popped-args :not-enough-args) - state - (let [result (apply function (:args popped-args)) - new-state (:state popped-args)] - (if (= result :ignore-instruction) - state - (state/push-to-stack new-state return-stack result)))))) - -;; Given a set of stacks, returns all instructions that operate on those stacks -;; only. Won't include random instructions unless :random is in the set as well -(defn get-stack-instructions - [stacks] - (doseq [[instruction-name function] @instructions/instruction-table] - (assert - (:stacks (meta function)) - #?(:clj (format - "ERROR: Instruction %s does not have :stacks defined in metadata." - (name instruction-name)) - :cljs (gstring/format - "ERROR: Instruction %s does not have :stacks defined in metadata." - (name instruction-name))))) - (for [[instruction-name function] @instructions/instruction-table - :when (clojure.set/subset? (:stacks (meta function)) stacks)] - instruction-name)) - - -#?(:clj - (def cls->type - {Boolean :boolean - Short :integer - Integer :integer - Long :integer - BigInteger :integer - Double :float - BigDecimal :float - Float :float - Character :char - String :string})) - -#?(:cljs - (def pred->type - [[boolean? :boolean] - [int? :integer] - [float? :float] - [string? :string] - [char? :char]])) - -(defn get-literal-type - "If a piece of data is a literal, return its corresponding stack name - e.g. `:integer`. Otherwise, return `nil`." - [data] - (or (when (vector? data) - (if (empty? data) - :generic-vector - (keyword (str "vector_" (name (get-literal-type (u/first-non-nil data))))))) - #?(:clj (cls->type (type data)) - :cljs (loop [remaining pred->type] - (let [[pred d-type] (first remaining)] - (cond - (empty? remaining) nil - (pred data) d-type - :else (recur (rest remaining)))))))) - -(defn get-vector-literal-type - "Returns the literal stack corresponding to some vector stack." - [vector-stack] - (get state/vec-stacks vector-stack)) diff --git a/src/propeller/push/utils/macros.cljc b/src/propeller/push/utils/macros.cljc deleted file mode 100755 index 08ab01a..0000000 --- a/src/propeller/push/utils/macros.cljc +++ /dev/null @@ -1,36 +0,0 @@ -(ns propeller.push.utils.macros - (:require [propeller.push.instructions :as instructions] - [propeller.push.utils.helpers :refer [get-vector-literal-type]])) - -(defn def-instruction - "Defines a Push instruction as a keyword-function pair, and adds it to the - instruction table" - [instruction function] - (swap! instructions/instruction-table assoc instruction function)) - -(defn make-metadata - "Given a generic function, e.g. _dup, and a stack type to instantiate it for, - e.g. :char, returns the appropriate stack metadata for that function instance" - [function stack] - (->> (:stacks (meta function)) - (replace {:elem (get-vector-literal-type stack)}) - (cons stack) - set - (assoc-in (meta function) [:stacks]) - (#(dissoc % :name)))) - -(defn generate-instructions - "Given a sequence of stacks, e.g. [:float :integer], and a sequence of suffix - function strings, e.g. [_add, _mult, _eq], automates the generation of all - possible combination instructions, which here would be :float_add, :float_mult, - :float_eq, :integer_add, :integer_mult, and :integer_eq, also transferring - and updating the generic function's stack-type metadata. For some vector - instructions, the placeholder :elem will be replaced with the stack of the - corresponding element type (e.g. for :vector_integer, with :integer)" - [stacks functions] - (doseq [stack stacks - func functions] - (let [instruction-name (keyword (str (name stack) (:name (meta func)))) - metadata (make-metadata func stack) - new-func (with-meta (partial func stack) metadata)] - (def-instruction instruction-name new-func)))) diff --git a/src/propeller/session.cljc b/src/propeller/session.cljc index 4996b0e..c9a159d 100755 --- a/src/propeller/session.cljc +++ b/src/propeller/session.cljc @@ -7,8 +7,7 @@ [propeller.problems.string-classification :as string-classif] [propeller.push.instructions :as instructions] [propeller.push.interpreter :as interpreter] - [propeller.push.state :as state] - [propeller.push.utils.helpers :refer [get-stack-instructions]])) + [propeller.push.state :as state])) #_(interpreter/interpret-program '(1 2 :integer_add) state/empty-state 1000) @@ -36,7 +35,7 @@ ; 1000) ; ;#_(genome/plushy->push -; (genome/make-random-plushy (get-stack-instructions #{:float :integer :exec :boolean}) 20)) +; (genome/make-random-plushy (instructions/get-stack-instructions #{:float :integer :exec :boolean}) 20)) ; ;#_(gp/gp {:instructions propeller.problems.software.number-io/instructions ; :error-function propeller.problems.software.number-io/error-function