VERY UNSTABLE. WIP
parent
4176ba234b
commit
3439ae6c9e
|
@ -3,6 +3,19 @@
|
||||||
# parser generators (but not exactly).
|
# parser generators (but not exactly).
|
||||||
module CeleryScript
|
module CeleryScript
|
||||||
class Corpus
|
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 "
|
BAD_NODE_NAME = "Can't find validation rules for node "
|
||||||
NO_ARG_SPEC = "CANT FIND ARG SPEC"
|
NO_ARG_SPEC = "CANT FIND ARG SPEC"
|
||||||
NO_NODE_SPEC = "NO_NODE_SPEC"
|
NO_NODE_SPEC = "NO_NODE_SPEC"
|
||||||
|
@ -34,7 +47,11 @@ module CeleryScript
|
||||||
end
|
end
|
||||||
|
|
||||||
def arg(name, defn, &blk)
|
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)
|
@arg_def_list[name] = ArgumentSpecification.new(name, defn, blk)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,10 +38,9 @@ module CeleryScriptSettingsBag
|
||||||
factory_reset find_home home install_farmware
|
factory_reset find_home home install_farmware
|
||||||
install_first_party_farmware _if move_absolute
|
install_first_party_farmware _if move_absolute
|
||||||
move_relative power_off read_pin read_status reboot
|
move_relative power_off read_pin read_status reboot
|
||||||
register_gpio remove_farmware resource_update
|
remove_farmware resource_update send_message
|
||||||
send_message set_servo_angle set_user_env sync
|
set_servo_angle set_user_env sync take_photo
|
||||||
take_photo toggle_pin update_farmware wait write_pin
|
toggle_pin update_farmware wait write_pin zero )
|
||||||
zero )
|
|
||||||
ALLOWED_SPEC_ACTION = %w(dump_info emergency_lock emergency_unlock power_off
|
ALLOWED_SPEC_ACTION = %w(dump_info emergency_lock emergency_unlock power_off
|
||||||
read_status reboot sync take_photo)
|
read_status reboot sync take_photo)
|
||||||
ANY_VARIABLE = %i(tool coordinate point identifier every_point)
|
ANY_VARIABLE = %i(tool coordinate point identifier every_point)
|
||||||
|
@ -99,55 +98,108 @@ module CeleryScriptSettingsBag
|
||||||
resource_type: ALLOWED_RESOURCE_TYPE,
|
resource_type: ALLOWED_RESOURCE_TYPE,
|
||||||
}.map { |(name, list)| Corpus.enum(name, list) }
|
}.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 = {
|
CORPUS_ARGS = {
|
||||||
_else: {defn: [:execute, :nothing]},
|
_else: {
|
||||||
_then: {defn: [:execute, :nothing]},
|
defn: [
|
||||||
data_value: {defn: ANY_VARIABLE},
|
n(:execute),
|
||||||
default_value: {defn: ANY_VARIABLE},
|
n(:nothing)
|
||||||
label: {defn: [String]},
|
]
|
||||||
locals: {defn: [:scope_declaration]},
|
},
|
||||||
location: {defn: ANY_VARIABLE},
|
_then: {
|
||||||
milliseconds: {defn: [Integer]},
|
defn: [
|
||||||
offset: {defn: [:coordinate]},
|
n(:execute),
|
||||||
pin_id: {defn: [Integer]},
|
n(:nothing)
|
||||||
pin_number: {defn: [Integer, :named_pin]},
|
]
|
||||||
pin_value: {defn: [Integer]},
|
},
|
||||||
radius: {defn: [Integer]},
|
data_value: {
|
||||||
resource_id: {defn: [Integer]},
|
defn: ANY_VAR_TOKENIZED
|
||||||
rhs: {defn: [Integer]},
|
},
|
||||||
url: {defn: [String]},
|
default_value: {
|
||||||
value: {defn: [String, Integer, TrueClass, FalseClass]},
|
defn: ANY_VAR_TOKENIZED
|
||||||
version: {defn: [Integer]},
|
},
|
||||||
x: {defn: [Integer, Float]},
|
label: {
|
||||||
y: {defn: [Integer, Float]},
|
defn: [v(:string)]
|
||||||
z: {defn: [Integer, Float]},
|
},
|
||||||
|
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: {
|
pin_type: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_PIN_TYPES, node, BAD_PIN_TYPE)
|
enum(ALLOWED_PIN_TYPES, node, BAD_PIN_TYPE)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
pointer_id: {
|
pointer_id: {
|
||||||
defn: [Integer],
|
defn: [v(:integer)],
|
||||||
blk: -> (node, device) do
|
blk: -> (node, device) do
|
||||||
bad_node = !Point.where(id: node.value, device_id: device.id).exists?
|
bad_node = !Point.where(id: node.value, device_id: device.id).exists?
|
||||||
node.invalidate!(BAD_POINTER_ID % node.value) if bad_node
|
node.invalidate!(BAD_POINTER_ID % node.value) if bad_node
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
pointer_type: {
|
pointer_type: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_POINTER_TYPE, node, BAD_POINTER_TYPE)
|
enum(ALLOWED_POINTER_TYPE, node, BAD_POINTER_TYPE)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
pin_mode: {
|
pin_mode: {
|
||||||
defn: [Integer],
|
defn: [v(:integer)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_PIN_MODES, node, BAD_ALLOWED_PIN_MODES)
|
enum(ALLOWED_PIN_MODES, node, BAD_ALLOWED_PIN_MODES)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
sequence_id: {
|
sequence_id: {
|
||||||
defn: [Integer],
|
defn: [v(:integer)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
if (node.value == 0)
|
if (node.value == 0)
|
||||||
node.invalidate!(NO_SUB_SEQ)
|
node.invalidate!(NO_SUB_SEQ)
|
||||||
|
@ -165,43 +217,43 @@ module CeleryScriptSettingsBag
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
op: {
|
op: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_OPS, node, BAD_OP)
|
enum(ALLOWED_OPS, node, BAD_OP)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
channel_name: {
|
channel_name: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_CHANNEL_NAMES, node, BAD_CHANNEL_NAME)
|
enum(ALLOWED_CHANNEL_NAMES, node, BAD_CHANNEL_NAME)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
message_type: {
|
message_type: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_MESSAGE_TYPES, node, BAD_MESSAGE_TYPE)
|
enum(ALLOWED_MESSAGE_TYPES, node, BAD_MESSAGE_TYPE)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
tool_id: {
|
tool_id: {
|
||||||
defn: [Integer],
|
defn: [v(:integer)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
node.invalidate!(BAD_TOOL_ID % node.value) if !Tool.exists?(node.value)
|
node.invalidate!(BAD_TOOL_ID % node.value) if !Tool.exists?(node.value)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
package: {
|
package: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_PACKAGES, node, BAD_PACKAGE)
|
enum(ALLOWED_PACKAGES, node, BAD_PACKAGE)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
axis: {
|
axis: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_AXIS, node, BAD_AXIS)
|
enum(ALLOWED_AXIS, node, BAD_AXIS)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
notString = !node.value.is_a?(String)
|
notString = !node.value.is_a?(String)
|
||||||
tooShort = notString || node.value.length == 0
|
tooShort = notString || node.value.length == 0
|
||||||
|
@ -210,19 +262,19 @@ module CeleryScriptSettingsBag
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
speed: {
|
speed: {
|
||||||
defn: [Integer],
|
defn: [v(:integer)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
node.invalidate!(BAD_SPEED) unless node.value.between?(1, 100)
|
node.invalidate!(BAD_SPEED) unless node.value.between?(1, 100)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
resource_type: {
|
resource_type: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (n) do
|
blk: -> (n) do
|
||||||
enum(ALLOWED_RESOURCE_TYPE, n, BAD_RESOURCE_TYPE)
|
enum(ALLOWED_RESOURCE_TYPE, n, BAD_RESOURCE_TYPE)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
every_point_type: {
|
every_point_type: {
|
||||||
defn: [String],
|
defn: [v(:string)],
|
||||||
blk: -> (node) do
|
blk: -> (node) do
|
||||||
enum(ALLOWED_EVERY_POINT_TYPE, node, BAD_EVERY_POINT_TYPE)
|
enum(ALLOWED_EVERY_POINT_TYPE, node, BAD_EVERY_POINT_TYPE)
|
||||||
end
|
end
|
||||||
|
@ -294,7 +346,7 @@ module CeleryScriptSettingsBag
|
||||||
body: [:parameter_application]
|
body: [:parameter_application]
|
||||||
},
|
},
|
||||||
internal_regimen: {
|
internal_regimen: {
|
||||||
body: [:parameter_application]
|
body: %i(parameter_application parameter_declaration variable_declaration)
|
||||||
},
|
},
|
||||||
move_relative: {
|
move_relative: {
|
||||||
args: [:x, :y, :z, :speed]
|
args: [:x, :y, :z, :speed]
|
||||||
|
@ -381,26 +433,26 @@ module CeleryScriptSettingsBag
|
||||||
},
|
},
|
||||||
move_absolute: {
|
move_absolute: {
|
||||||
args: [:location, :speed, :offset],
|
args: [:location, :speed, :offset],
|
||||||
blk: ->(n) do
|
blk: -> (n) do
|
||||||
loc = n.args[:location].try(:kind)
|
loc = n.args[:location].try(:kind)
|
||||||
n.invalidate!(ONLY_ONE_COORD) if loc == "every_point"
|
n.invalidate!(ONLY_ONE_COORD) if loc == "every_point"
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
write_pin: {
|
write_pin: {
|
||||||
args: [:pin_number, :pin_value, :pin_mode ],
|
args: [:pin_number, :pin_value, :pin_mode ],
|
||||||
blk: ->(n) do
|
blk: -> (n) do
|
||||||
no_rpi_analog(n)
|
no_rpi_analog(n)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
read_pin: {
|
read_pin: {
|
||||||
args: [:pin_number, :label, :pin_mode],
|
args: [:pin_number, :label, :pin_mode],
|
||||||
blk: ->(n) do
|
blk: -> (n) do
|
||||||
no_rpi_analog(n)
|
no_rpi_analog(n)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
resource_update: {
|
resource_update: {
|
||||||
args: RESOURCE_UPDATE_ARGS,
|
args: RESOURCE_UPDATE_ARGS,
|
||||||
blk: ->(x) do
|
blk: -> (x) do
|
||||||
resource_type = x.args.fetch(:resource_type).value
|
resource_type = x.args.fetch(:resource_type).value
|
||||||
resource_id = x.args.fetch(:resource_id).value
|
resource_id = x.args.fetch(:resource_id).value
|
||||||
check_resource_type(x, resource_type, resource_id)
|
check_resource_type(x, resource_type, resource_id)
|
||||||
|
|
|
@ -36,7 +36,7 @@ class CorpusEmitter
|
||||||
|
|
||||||
attr_reader :name, :allowed_args, :allowed_body_types
|
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,
|
@name,
|
||||||
@allowed_args,
|
@allowed_args,
|
||||||
@allowed_body_types = name, allowed_args, allowed_body_types
|
@allowed_body_types = name, allowed_args, allowed_body_types
|
||||||
|
|
|
@ -60,6 +60,34 @@ describe Api::RegimensController do
|
||||||
expect(json[:color]).to eq(color)
|
expect(json[:color]).to eq(color)
|
||||||
end
|
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
|
it "handles CeleryScript::TypeCheckError" do
|
||||||
sign_in user
|
sign_in user
|
||||||
s = FakeSequence.with_parameters
|
s = FakeSequence.with_parameters
|
||||||
|
|
Loading…
Reference in New Issue