[STABLE] Looks like if_statements are done?

pull/305/head
Rick Carlino 2016-12-20 18:29:23 -06:00
parent 4f0cf24097
commit 074cec8676
13 changed files with 126 additions and 70 deletions

View File

@ -12,7 +12,8 @@ module SequenceMigration
[
AddVersionInfo,
UpdateChannelNames,
AddToolsToMoveAbs
AddToolsToMoveAbs,
UpdateIfStatement
]
end

View File

@ -3,7 +3,8 @@ module SequenceMigration
# When this migration was created, the move_absolute block could only move to
# a fixed point on the map.
# After this migration, the user could move to a dynamically set tool location
# -OR- a fixed point on the map.
# -OR- a fixed point on the map. It also added an "offset" property for tools
# with funny sizes.
class AddToolsToMoveAbs < Base
VERSION = 2
CREATED_ON = "DECEMBER 19 2016"

View File

@ -0,0 +1,22 @@
module SequenceMigration
# Background:
# This is a refactor of what once was called the `if_statement` block:
# * Added a `nothing` node type (sorry, we actually need it now).
# * if_statement becomes _if
# * sub_sequence_id becomes _then
# * Add _else arg to _if.
# * _then/_else expect a execute or nothing node instead of a number.
class UpdateIfStatement < Base
VERSION = 3
CREATED_ON = "DECEMBER 20 2016"
def up
sequence
.body
.select { |x| x["kind"] == "if_statement" }
.each do |x|
binding.pry
end
end
end
end

View File

@ -8,7 +8,7 @@ module CeleryScriptSettingsBag
ALLOWED_DATA_TYPES = %w(string integer)
ALLOWED_OPS = %w(< > is not)
STEPS = %w(move_absolute move_relative write_pin read_pin wait
send_message execute if_statement)
send_message execute _if)
ALLOWED_LHS = %w(busy pin0 pin1 pin2 pin3 pin4 pin5 pin6 pin7 pin8
pin9 pin10 pin11 pin12 pin13 x y z)
BAD_ALLOWED_PIN_MODES = 'Can not put "%s" into a left hand side (LHS) '\
@ -69,6 +69,9 @@ module CeleryScriptSettingsBag
.defineArg(:message, [String])
.defineArg(:location, [:tool, :coordinate])
.defineArg(:offset, [:coordinate])
.defineArg(:_then, [:execute, :nothing])
.defineArg(:_else, [:execute, :nothing])
.defineNode(:nothing, [])
.defineNode(:tool, [:tool_id])
.defineNode(:coordinate, [:x, :y, :z])
.defineNode(:move_absolute, [:location, :speed, :offset])
@ -79,7 +82,7 @@ module CeleryScriptSettingsBag
.defineNode(:wait, [:milliseconds])
.defineNode(:send_message, [:message, :message_type], [:channel])
.defineNode(:execute, [:sub_sequence_id])
.defineNode(:if_statement, [:lhs, :op, :rhs, :sub_sequence_id])
.defineNode(:_if, [:lhs, :op, :rhs, :_then, :_else])
.defineNode(:sequence, [:version], STEPS)
def self.within(array, node)

View File

@ -42,6 +42,7 @@ module Sequences
@checker = CeleryScript::Checker.new(tree, corpus)
end
# TODO: This is too specific to corpus stuff. Does not belong in this class.
def sub_sequences
all = []
return all unless checker.valid?

View File

@ -2,6 +2,6 @@ FactoryGirl.define do
factory :tool do
tool_slot
device
name "MyString"
name { Faker::Pokemon.name }
end
end

View File

@ -1,62 +1,71 @@
[
{
"kind":"move_absolute",
"args":{
"x":1,
"y":2,
"z":3,
"speed":4
"kind": "move_absolute",
"args": {
"x": 1,
"y": 2,
"z": 3,
"speed": 4
}
},
{
"kind":"move_relative",
"args":{
"x":1,
"y":2,
"z":3,
"speed":4
"kind": "move_relative",
"args": {
"x": 1,
"y": 2,
"z": 3,
"speed": 4
}
},
{
"kind":"write_pin",
"args":{
"pin_number":1,
"pin_value":0,
"pin_mode":1
"kind": "write_pin",
"args": {
"pin_number": 1,
"pin_value": 0,
"pin_mode": 1
}
},
{
"kind":"read_pin",
"args":{
"pin_number":1,
"data_label":"probably_a_variable"
"kind": "read_pin",
"args": {
"pin_number": 1,
"data_label": "probably_a_variable"
}
},
{
"kind":"wait",
"args":{
"milliseconds":5000
"kind": "wait",
"args": {
"milliseconds": 5000
}
},
{
"kind":"send_message",
"args":{
"message":"Value is {{ probably_a_variable }}"
"kind": "send_message",
"args": {
"message": "Value is {{ probably_a_variable }}"
}
},
{
"kind":"execute",
"args":{
"sub_sequence_id":123
"kind": "execute",
"args": {
"sub_sequence_id": 123
}
},
{
"kind":"if_statement",
"args":{
"lhs":"x",
"op":">",
"rhs":5,
"sub_sequence_id":123
"kind": "_if",
"args": {
"lhs": "x",
"op": ">",
"rhs": 5,
"_then": {
"kind": "nothing",
"args": {}
},
"_else": {
"kind": "execute",
"args": {
"sub_sequence_id": 123
}
}
}
}
]

View File

@ -2,7 +2,7 @@
"kind": "sequence",
"comment": "Properly formatted, syntactically valid sequence.",
"args": {
"version": 1
"version": 3
},
"body": [
{
@ -33,7 +33,7 @@
"location": {
"kind": "tool",
"args": {
"tool_id": 1
"tool_id": 8888
}
},
"offset": {
@ -94,18 +94,27 @@
]
},
{
"kind": "if_statement",
"kind": "_if",
"args": {
"lhs": "x",
"rhs": 300,
"op": "is",
"sub_sequence_id": 456
"_then": {
"kind": "execute",
"args": {
"sub_sequence_id": 9999
}
},
"_else": {
"kind": "nothing",
"args": {}
}
}
},
{
"kind": "execute",
"args": {
"sub_sequence_id": 123
"sub_sequence_id": 9999
}
}
]

View File

@ -101,7 +101,7 @@ describe CeleryScript::Corpus do
it "serializes into JSON" do
result = JSON.parse(corpus.to_json)
expect(result["tag"]).to eq(2)
expect(result["tag"]).to eq(3)
expect(result["args"]).to be_kind_of(Array)
expect(result["nodes"]).to be_kind_of(Array)
expect(result["nodes"].sample.keys.sort).to eq(["allowed_args",

View File

@ -2,6 +2,6 @@ require 'spec_helper'
describe SequenceMigration do
it 'has a latest version' do
expect(SequenceMigration::Base.latest_version).to eq(2)
expect(SequenceMigration::Base.latest_version).to eq(3)
end
end

View File

@ -36,7 +36,7 @@ describe Sequences::Create do
end
it 'Gives validation errors for malformed sub_sequence_id' do
body[7]["args"]["sub_sequence_id"] = 0
body[7]["args"]["_then"]["args"]["sub_sequence_id"] = 0
seq = Sequences::Create.run(sequence_params)
expect(seq.success?).to be(false)
expectation = "Sequence #0 does not exist."
@ -44,7 +44,7 @@ describe Sequences::Create do
end
it 'Gives validation errors for malformed LHS' do
body.select{ |x| x["kind"] == "if_statement" }.first["args"]["lhs"] = "xyz"
body.select{ |x| x["kind"] == "_if" }.first["args"]["lhs"] = "xyz"
seq = Sequences::Create.run(sequence_params)
expect(seq.success?).to be(false)
expected = "Can not put \"xyz\" into a left hand side (LHS) argument."
@ -52,7 +52,7 @@ describe Sequences::Create do
end
it 'Gives validation errors for malformed OP' do
body.select{ |x| x["kind"] == "if_statement" }.first["args"]["op"] = "was"
body.select{ |x| x["kind"] == "_if" }.first["args"]["op"] = "was"
seq = Sequences::Create.run(sequence_params)
expect(seq.success?).to be(false)
expected = "Can not put \"was\" into an operand (OP) argument."

View File

@ -96,14 +96,14 @@ describe "Migration from version 0 or nil" do
expected = BODY1.dig(0, "args", "message")
expect(actual).to eq(expected)
expect(seq1.body.dig(0, "args", "message_type")).to eq("info")
expect(seq1.args["version"]).to eq(2)
expect(seq1.args["version"]).to eq(3)
end
it 'handles `channel` body nodes' do
Sequences::Migrate.run!(device: device, sequence: seq2)
expect(seq2.body.dig(0, "args", "message_type")).to eq("info")
expect(seq2.args["version"]).to eq(2)
expect(seq2.args["version"]).to eq(3)
results = seq2
.body
.map{|x| x["body"]}

View File

@ -1,25 +1,35 @@
class Hash
def traverse(parent=nil, &blk)
each do |k, v|
Hash === v ? v.traverse(k, &blk) : blk.call([parent, k, v])
end
end
end
module Helpers
AST_FIXTURE = File.read("./spec/lib/celery_script/ast_fixture3.json").freeze
MAGIC_NUMBER_SEQ_ID = "9999"
MAGIC_NUMBER_TOOL_ID = "8888"
AST_FIXTURE = File.read("./spec/lib/celery_script/ast_fixture3.json")
# Create a VALID fake sequence.body for a particular user. Creates a fake
# subsequence in the DB when called.
def sequence_body_for(input)
user ||= FactoryGirl.create(:user)
body = JSON.parse(AST_FIXTURE)["body"]
case input
when User; id = FactoryGirl.create(:sequence, device: user.device).id
when Sequence; id = input.id
else; raise "?????"
def sequence_body_for(mystery)
case mystery
when User
device = user.device
when Device
device = mystery
when Sequence
device = mystery.device
else
raise "No #{mystery.class}"
end
tool_id = FactoryGirl.create(:tool, device: user.device).id
body.map! do |node|
has_subseq = node.dig("args", "sub_sequence_id")
has_tool = node.dig("args", "location", "args", "tool_id")
node["args"]["location"]["args"]["tool_id"] = tool_id if has_tool
node["args"]["sub_sequence_id"] = id if has_subseq
node
end
body
sid = FactoryGirl.create(:sequence, device: device).id
tid = FactoryGirl.create(:tool, device: device).id
str = AST_FIXTURE
.gsub(MAGIC_NUMBER_SEQ_ID, sid.to_s)
.gsub(MAGIC_NUMBER_TOOL_ID, tid.to_s)
JSON.parse(str)["body"]
end
def sign_in_as(user)