Add input handler and refactor interpreter

This commit is contained in:
mcgirjau 2020-06-29 22:52:41 -04:00
parent ca33a46627
commit 69142757ce
6 changed files with 66 additions and 58 deletions

View File

@ -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

View File

@ -0,0 +1,3 @@
(ns propeller.problems.software.number-io)

View File

@ -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
;; =============================================================================

View File

@ -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."

View File

@ -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))))

View File

@ -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)))