diff --git a/src/propeller/problems/simple_regression.clj b/src/propeller/problems/simple_regression.clj index a1d2801..bc734ff 100644 --- a/src/propeller/problems/simple_regression.clj +++ b/src/propeller/problems/simple_regression.clj @@ -28,28 +28,9 @@ :integer_eq :exec_dup :exec_if - :boolean_and - :boolean_or - :boolean_not - :boolean_eq - :string_eq - :string_take - :string_drop - :string_reverse - :string_concat - :string_length - :string_includes? 'close 0 - 1 - true - false - "" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "A" - "C" - "G" - "T")) + 1)) (defn error-function "Finds the behaviors and errors of an individual. The error is the absolute diff --git a/src/propeller/problems/software/number_io.clj b/src/propeller/problems/software/number_io.clj new file mode 100644 index 0000000..d21dba7 --- /dev/null +++ b/src/propeller/problems/software/number_io.clj @@ -0,0 +1,3 @@ +(ns propeller.problems.software.number-io) + + diff --git a/src/propeller/push/instructions/input_output.clj b/src/propeller/push/instructions/input_output.clj index 037b9af..a761642 100644 --- a/src/propeller/push/instructions/input_output.clj +++ b/src/propeller/push/instructions/input_output.clj @@ -3,11 +3,19 @@ [propeller.push.utils :refer [def-instruction]])) ;; ============================================================================= -;; INPUT and OUTPUT Instructions +;; INPUT Instructions ;; ============================================================================= -;; Pushes the input labeled :in1 on the inputs map onto the :exec stack -(def-instruction - :in1 - (fn [state] - (state/push-to-stack state :exec (:in1 (:input state))))) +;; Allows Push to handle input instructions of the form :inN, e.g. :in2, taking +;; elements thus labeled from the :input stack and pushing them onto the :exec +;; stack. We can tell whether a particular inN instruction is valid if N-1 +;; values are on the input stack. +(defn handle-input-instruction + [state instruction] + (if-let [input (instruction (:input state))] + (state/push-to-stack state :exec input) + (throw (Exception. (str "Undefined input instruction " instruction))))) + +;; ============================================================================= +;; OUTPUT and PRINT Instructions +;; ============================================================================= diff --git a/src/propeller/push/interpreter.clj b/src/propeller/push/interpreter.clj index 13006fc..d8504ca 100644 --- a/src/propeller/push/interpreter.clj +++ b/src/propeller/push/interpreter.clj @@ -1,34 +1,38 @@ (ns propeller.push.interpreter (:require [propeller.push.core :as push] - [propeller.push.state :as state])) + [propeller.push.state :as state] + [propeller.push.utils :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) - first-instruction-raw (first (:exec state)) - first-instruction (if (keyword? first-instruction-raw) - (first-instruction-raw @push/instruction-table) - first-instruction-raw)] + instruction (first (:exec state)) + literal-type (get-literal-type instruction)] ; nil for non-literals (cond - (fn? first-instruction) - (first-instruction popped-state) - ; - (integer? first-instruction) - (state/push-to-stack popped-state :integer first-instruction) - ; - (string? first-instruction) - (state/push-to-stack popped-state :string first-instruction) - ; - (seq? first-instruction) - (update popped-state :exec #(concat %2 %1) first-instruction) - ; - (or (= first-instruction true) (= first-instruction false)) - (state/push-to-stack popped-state :boolean first-instruction) - ; + ;; + ;; Recognize functional instruction or input instruction + (keyword? instruction) + (if-let [function (instruction @push/instruction-table)] + (function popped-state) + (io/handle-input-instruction popped-state instruction)) + ;; + ;; Recognize constant literal instruction + literal-type + (if (= :generic-vector literal-type) + ;; Empty vector gets pushed on all vector stacks + (reduce #(update-in % [%2] conj []) popped-state + [:vector_boolean :vector_float :vector_integer :vector_string]) + (state/push-to-stack popped-state literal-type instruction)) + ;; + ;; Recognize parenthesized group of instructions + (seq? instruction) + (update popped-state :exec #(concat %2 %1) instruction) + ;; :else (throw (Exception. (str "Unrecognized Push instruction in program: " - (name first-instruction-raw))))))) + (name instruction))))))) (defn interpret-program "Runs the given problem starting with the stacks in start-state." diff --git a/src/propeller/push/utils.clj b/src/propeller/push/utils.clj index 16ef1c8..f1582e1 100644 --- a/src/propeller/push/utils.clj +++ b/src/propeller/push/utils.clj @@ -51,11 +51,21 @@ ;; :integer. Otherwise, return nil" (defn get-literal-type [data] - (let [literals {:boolean (fn [thing] (or (true? thing) (false? thing))) - :char char? - :float float? - :integer integer? - :string string?}] + (let [literals {:boolean (fn [thing] (or (true? thing) (false? thing))) + :char char? + :float float? + :integer integer? + :string string? + :vector_boolean (fn [thing] (and (vector? thing) + (or (true? (first thing)) + (false? (first thing))))) + :vector_float (fn [thing] (and (vector? thing) + (float? (first thing)))) + :vector_integer (fn [thing] (and (vector? thing) + (integer? (first thing)))) + :vector_string (fn [thing] (and (vector? thing) + (string? (first thing)))) + :generic-vector (fn [thing] (= [] thing))}] (first (for [[stack function] literals :when (function data)] stack)))) diff --git a/src/propeller/utils.clj b/src/propeller/utils.clj index d532327..492ec20 100644 --- a/src/propeller/utils.clj +++ b/src/propeller/utils.clj @@ -1,5 +1,10 @@ (ns propeller.utils) +(defn get-vector-literal-type + "Returns the literal stack corresponding to some vector stack." + [vector-stack] + (keyword (clojure.string/replace (str vector-stack) ":vector_" ""))) + (defn indexof "Returns the first index of an element in a collection. If the element is not present in the collection, returns -1." @@ -26,9 +31,6 @@ ERC-producing functions to a constant literal." [instructions] (let [instruction (rand-nth instructions)] - (if (fn? instruction) (instruction) instruction))) - -(defn get-vector-literal-type - "Returns the literal stack corresponding to some vector stack." - [vector-stack] - (keyword (clojure.string/replace (str vector-stack) ":vector_" ""))) + (if (fn? instruction) + (instruction) + instruction)))