VERY UNSTABLE. WIP

pull/1125/head
Rick Carlino 2019-02-20 17:13:23 -06:00
parent 4176ba234b
commit 3439ae6c9e
4 changed files with 144 additions and 47 deletions

View File

@ -3,6 +3,19 @@
# parser generators (but not exactly).
module CeleryScript
class Corpus
class ArgAtom
attr_reader :value
def initialize(value)
raise "USE SYMBOLS!" unless value.is_a?(Symbol)
@value = value
end
end
class Enum < ArgAtom; end
class Value < ArgAtom; end
class Node < ArgAtom; end
ATOMS = [Enum, Value, Node]
BAD_NODE_NAME = "Can't find validation rules for node "
NO_ARG_SPEC = "CANT FIND ARG SPEC"
NO_NODE_SPEC = "NO_NODE_SPEC"
@ -34,7 +47,11 @@ module CeleryScript
end
def arg(name, defn, &blk)
raise "NO!" unless defn.is_a?(Array)
defn.map do |x|
binding.pry if x.is_a?(Symbol)
binding.pry if x.is_a?(Class)
puts x.class.inspect
end
@arg_def_list[name] = ArgumentSpecification.new(name, defn, blk)
self
end

View File

@ -38,10 +38,9 @@ module CeleryScriptSettingsBag
factory_reset find_home home install_farmware
install_first_party_farmware _if move_absolute
move_relative power_off read_pin read_status reboot
register_gpio remove_farmware resource_update
send_message set_servo_angle set_user_env sync
take_photo toggle_pin update_farmware wait write_pin
zero )
remove_farmware resource_update send_message
set_servo_angle set_user_env sync take_photo
toggle_pin update_farmware wait write_pin zero )
ALLOWED_SPEC_ACTION = %w(dump_info emergency_lock emergency_unlock power_off
read_status reboot sync take_photo)
ANY_VARIABLE = %i(tool coordinate point identifier every_point)
@ -99,55 +98,108 @@ module CeleryScriptSettingsBag
resource_type: ALLOWED_RESOURCE_TYPE,
}.map { |(name, list)| Corpus.enum(name, list) }
def self.e(symbol)
CeleryScript::Corpus::Enum.new(symbol)
end
def self.n(symbol)
CeleryScript::Corpus::Node.new(symbol)
end
def self.v(symbol)
CeleryScript::Corpus::Value.new(symbol)
end
ANY_VAR_TOKENIZED = ANY_VARIABLE.map { |x| n(x) }
CORPUS_ARGS = {
_else: {defn: [:execute, :nothing]},
_then: {defn: [:execute, :nothing]},
data_value: {defn: ANY_VARIABLE},
default_value: {defn: ANY_VARIABLE},
label: {defn: [String]},
locals: {defn: [:scope_declaration]},
location: {defn: ANY_VARIABLE},
milliseconds: {defn: [Integer]},
offset: {defn: [:coordinate]},
pin_id: {defn: [Integer]},
pin_number: {defn: [Integer, :named_pin]},
pin_value: {defn: [Integer]},
radius: {defn: [Integer]},
resource_id: {defn: [Integer]},
rhs: {defn: [Integer]},
url: {defn: [String]},
value: {defn: [String, Integer, TrueClass, FalseClass]},
version: {defn: [Integer]},
x: {defn: [Integer, Float]},
y: {defn: [Integer, Float]},
z: {defn: [Integer, Float]},
_else: {
defn: [
n(:execute),
n(:nothing)
]
},
_then: {
defn: [
n(:execute),
n(:nothing)
]
},
data_value: {
defn: ANY_VAR_TOKENIZED
},
default_value: {
defn: ANY_VAR_TOKENIZED
},
label: {
defn: [v(:string)]
},
locals: {
defn: [n(:scope_declaration)]
},
location: {
defn: ANY_VAR_TOKENIZED
},
milliseconds: {
defn: [v(:integer)]
},
offset: {
defn: [n(:coordinate)]
},
pin_id: {
defn: [v(:integer)]
},
pin_number: {
defn: [
v(:integer),
n(:named_pin)
]
},
pin_value: {
defn: [ v(:integer) ]
},
radius: {
defn: [ v(:integer) ]
},
resource_id: {
defn: [ v(:integer) ]
},
rhs: { defn: [ v(:integer) ] },
url: { defn: [ v(:string) ] },
value: {
defn: [v(:string), v(:integer), v(:boolean)]
},
version: {defn: [v(:integer)]},
x: {defn: [v(:integer), v(:float)]},
y: {defn: [v(:integer), v(:float)]},
z: {defn: [v(:integer), v(:float)]},
pin_type: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_PIN_TYPES, node, BAD_PIN_TYPE)
end
},
pointer_id: {
defn: [Integer],
defn: [v(:integer)],
blk: -> (node, device) do
bad_node = !Point.where(id: node.value, device_id: device.id).exists?
node.invalidate!(BAD_POINTER_ID % node.value) if bad_node
end
},
pointer_type: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_POINTER_TYPE, node, BAD_POINTER_TYPE)
end
},
pin_mode: {
defn: [Integer],
defn: [v(:integer)],
blk: -> (node) do
enum(ALLOWED_PIN_MODES, node, BAD_ALLOWED_PIN_MODES)
end
},
sequence_id: {
defn: [Integer],
defn: [v(:integer)],
blk: -> (node) do
if (node.value == 0)
node.invalidate!(NO_SUB_SEQ)
@ -165,43 +217,43 @@ module CeleryScriptSettingsBag
end
},
op: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_OPS, node, BAD_OP)
end
},
channel_name: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_CHANNEL_NAMES, node, BAD_CHANNEL_NAME)
end
},
message_type: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_MESSAGE_TYPES, node, BAD_MESSAGE_TYPE)
end
},
tool_id: {
defn: [Integer],
defn: [v(:integer)],
blk: -> (node) do
node.invalidate!(BAD_TOOL_ID % node.value) if !Tool.exists?(node.value)
end
},
package: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_PACKAGES, node, BAD_PACKAGE)
end
},
axis: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_AXIS, node, BAD_AXIS)
end
},
message: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
notString = !node.value.is_a?(String)
tooShort = notString || node.value.length == 0
@ -210,19 +262,19 @@ module CeleryScriptSettingsBag
end
},
speed: {
defn: [Integer],
defn: [v(:integer)],
blk: -> (node) do
node.invalidate!(BAD_SPEED) unless node.value.between?(1, 100)
end
},
resource_type: {
defn: [String],
defn: [v(:string)],
blk: -> (n) do
enum(ALLOWED_RESOURCE_TYPE, n, BAD_RESOURCE_TYPE)
end
},
every_point_type: {
defn: [String],
defn: [v(:string)],
blk: -> (node) do
enum(ALLOWED_EVERY_POINT_TYPE, node, BAD_EVERY_POINT_TYPE)
end
@ -294,7 +346,7 @@ module CeleryScriptSettingsBag
body: [:parameter_application]
},
internal_regimen: {
body: [:parameter_application]
body: %i(parameter_application parameter_declaration variable_declaration)
},
move_relative: {
args: [:x, :y, :z, :speed]
@ -381,26 +433,26 @@ module CeleryScriptSettingsBag
},
move_absolute: {
args: [:location, :speed, :offset],
blk: ->(n) do
blk: -> (n) do
loc = n.args[:location].try(:kind)
n.invalidate!(ONLY_ONE_COORD) if loc == "every_point"
end
},
write_pin: {
args: [:pin_number, :pin_value, :pin_mode ],
blk: ->(n) do
blk: -> (n) do
no_rpi_analog(n)
end
},
read_pin: {
args: [:pin_number, :label, :pin_mode],
blk: ->(n) do
blk: -> (n) do
no_rpi_analog(n)
end
},
resource_update: {
args: RESOURCE_UPDATE_ARGS,
blk: ->(x) do
blk: -> (x) do
resource_type = x.args.fetch(:resource_type).value
resource_id = x.args.fetch(:resource_id).value
check_resource_type(x, resource_type, resource_id)

View File

@ -36,7 +36,7 @@ class CorpusEmitter
attr_reader :name, :allowed_args, :allowed_body_types
def initialize(name:, allowed_args:, allowed_body_types: [])
def initialize(name:, allowed_args:, allowed_body_types: [], tags:)
@name,
@allowed_args,
@allowed_body_types = name, allowed_args, allowed_body_types

View File

@ -60,6 +60,34 @@ describe Api::RegimensController do
expect(json[:color]).to eq(color)
end
it "creates a regimen that uses unbound variables" do
pending("TODO: Help Gabe with this.")
sign_in user
s = FakeSequence.with_parameters
payload = { device: s.device,
name: "specs",
color: "red",
body: [
{
kind: "parameter_application",
args: {
label: "parent",
data_value: {
kind: "identifier", args: { label: "parent" }
}
}
}
],
regimen_items: [ { time_offset: 100, sequence_id: s.id } ] }
post :create, body: payload.to_json, format: :json
expect(response.status).to eq(200)
declr = json.fetch(:body).first
expect(declr).to be
expect(declr.fetch(:kind)).to eq("parameter_application")
path = [:args, :data_value, :args, :label]
expect(declr.dig(*path)).to eq("parent")
end
it "handles CeleryScript::TypeCheckError" do
sign_in user
s = FakeSequence.with_parameters