Add input handler and refactor interpreter
This commit is contained in:
parent
ca33a46627
commit
69142757ce
@ -28,28 +28,9 @@
|
|||||||
:integer_eq
|
:integer_eq
|
||||||
:exec_dup
|
:exec_dup
|
||||||
:exec_if
|
: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
|
'close
|
||||||
0
|
0
|
||||||
1
|
1))
|
||||||
true
|
|
||||||
false
|
|
||||||
""
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"A"
|
|
||||||
"C"
|
|
||||||
"G"
|
|
||||||
"T"))
|
|
||||||
|
|
||||||
(defn error-function
|
(defn error-function
|
||||||
"Finds the behaviors and errors of an individual. The error is the absolute
|
"Finds the behaviors and errors of an individual. The error is the absolute
|
||||||
|
3
src/propeller/problems/software/number_io.clj
Normal file
3
src/propeller/problems/software/number_io.clj
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
(ns propeller.problems.software.number-io)
|
||||||
|
|
||||||
|
|
@ -3,11 +3,19 @@
|
|||||||
[propeller.push.utils :refer [def-instruction]]))
|
[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
|
;; Allows Push to handle input instructions of the form :inN, e.g. :in2, taking
|
||||||
(def-instruction
|
;; elements thus labeled from the :input stack and pushing them onto the :exec
|
||||||
:in1
|
;; stack. We can tell whether a particular inN instruction is valid if N-1
|
||||||
(fn [state]
|
;; values are on the input stack.
|
||||||
(state/push-to-stack state :exec (:in1 (:input state)))))
|
(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
|
||||||
|
;; =============================================================================
|
||||||
|
@ -1,34 +1,38 @@
|
|||||||
(ns propeller.push.interpreter
|
(ns propeller.push.interpreter
|
||||||
(:require [propeller.push.core :as push]
|
(: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
|
(defn interpret-one-step
|
||||||
"Takes a Push state and executes the next instruction on the exec stack."
|
"Takes a Push state and executes the next instruction on the exec stack."
|
||||||
[state]
|
[state]
|
||||||
(let [popped-state (state/pop-stack state :exec)
|
(let [popped-state (state/pop-stack state :exec)
|
||||||
first-instruction-raw (first (:exec state))
|
instruction (first (:exec state))
|
||||||
first-instruction (if (keyword? first-instruction-raw)
|
literal-type (get-literal-type instruction)] ; nil for non-literals
|
||||||
(first-instruction-raw @push/instruction-table)
|
|
||||||
first-instruction-raw)]
|
|
||||||
(cond
|
(cond
|
||||||
(fn? first-instruction)
|
;;
|
||||||
(first-instruction popped-state)
|
;; Recognize functional instruction or input instruction
|
||||||
;
|
(keyword? instruction)
|
||||||
(integer? first-instruction)
|
(if-let [function (instruction @push/instruction-table)]
|
||||||
(state/push-to-stack popped-state :integer first-instruction)
|
(function popped-state)
|
||||||
;
|
(io/handle-input-instruction popped-state instruction))
|
||||||
(string? first-instruction)
|
;;
|
||||||
(state/push-to-stack popped-state :string first-instruction)
|
;; Recognize constant literal instruction
|
||||||
;
|
literal-type
|
||||||
(seq? first-instruction)
|
(if (= :generic-vector literal-type)
|
||||||
(update popped-state :exec #(concat %2 %1) first-instruction)
|
;; Empty vector gets pushed on all vector stacks
|
||||||
;
|
(reduce #(update-in % [%2] conj []) popped-state
|
||||||
(or (= first-instruction true) (= first-instruction false))
|
[:vector_boolean :vector_float :vector_integer :vector_string])
|
||||||
(state/push-to-stack popped-state :boolean first-instruction)
|
(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
|
:else
|
||||||
(throw (Exception. (str "Unrecognized Push instruction in program: "
|
(throw (Exception. (str "Unrecognized Push instruction in program: "
|
||||||
(name first-instruction-raw)))))))
|
(name instruction)))))))
|
||||||
|
|
||||||
(defn interpret-program
|
(defn interpret-program
|
||||||
"Runs the given problem starting with the stacks in start-state."
|
"Runs the given problem starting with the stacks in start-state."
|
||||||
|
@ -55,7 +55,17 @@
|
|||||||
:char char?
|
:char char?
|
||||||
:float float?
|
:float float?
|
||||||
:integer integer?
|
:integer integer?
|
||||||
:string string?}]
|
: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
|
(first (for [[stack function] literals
|
||||||
:when (function data)]
|
:when (function data)]
|
||||||
stack))))
|
stack))))
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
(ns propeller.utils)
|
(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
|
(defn indexof
|
||||||
"Returns the first index of an element in a collection. If the element is not
|
"Returns the first index of an element in a collection. If the element is not
|
||||||
present in the collection, returns -1."
|
present in the collection, returns -1."
|
||||||
@ -26,9 +31,6 @@
|
|||||||
ERC-producing functions to a constant literal."
|
ERC-producing functions to a constant literal."
|
||||||
[instructions]
|
[instructions]
|
||||||
(let [instruction (rand-nth instructions)]
|
(let [instruction (rand-nth instructions)]
|
||||||
(if (fn? instruction) (instruction) instruction)))
|
(if (fn? instruction)
|
||||||
|
(instruction)
|
||||||
(defn get-vector-literal-type
|
instruction)))
|
||||||
"Returns the literal stack corresponding to some vector stack."
|
|
||||||
[vector-stack]
|
|
||||||
(keyword (clojure.string/replace (str vector-stack) ":vector_" "")))
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user