class Lignite::SystemCommands
The commands that cannot appear in a .rbf program, used mostly for program manipulation
Public Class Methods
new(conn = Connection.create)
click to toggle source
@param conn [Connection]
# File lib/lignite/system_commands.rb, line 16 def initialize(conn = Connection.create) @conn = conn load_yml end
run(conn = Connection.create, &block)
click to toggle source
# File lib/lignite/system_commands.rb, line 9 def self.run(conn = Connection.create, &block) sc = new(conn) sc.instance_exec(&block) sc.close end
Public Instance Methods
close()
click to toggle source
# File lib/lignite/system_commands.rb, line 21 def close @conn.close end
Private Instance Methods
assert_match(actual, expected, description)
click to toggle source
# File lib/lignite/system_commands.rb, line 125 def assert_match(actual, expected, description) return if actual == expected raise "#{description} does not match, expected #{expected}, actual #{actual}" end
handlers(odata)
click to toggle source
# File lib/lignite/system_commands.rb, line 74 def handlers(odata) oparams = odata["params"] param_handlers = [] return_handlers = [] oparams.each do |p| if p["dir"] == "in" param_handlers << param_handler(p) else return_handlers << return_handler(p) end end [param_handlers, return_handlers] end
load_op(oname, odata)
click to toggle source
oname LIST_FILES
# File lib/lignite/system_commands.rb, line 36 def load_op(oname, odata) ovalue = odata["value"] param_handlers, return_handlers = handlers(odata) osym = oname.downcase.to_sym self.class.send(:define_method, osym) do |*args| logger.debug "called #{osym} with #{args.inspect}" if args.size != param_handlers.size raise ArgumentError, "expected #{param_handlers.size} arguments, got #{args.size}" end bytes = u8(ovalue) bytes += param_handlers.zip(args).map do |h, a| # h.call(a) would have self = Op instead of #<Op> instance_exec(a, &h) end.join("") logger.debug "sysop to execute: #{bytes.inspect}" reply = system_command_with_reply(bytes) parse_reply(reply, return_handlers) end end
load_yml()
click to toggle source
# File lib/lignite/system_commands.rb, line 27 def load_yml fname = File.expand_path("../../../data/sysops.yml", __FILE__) op_hash = YAML.load_file(fname)["sysops"] op_hash.each do |oname, odata| load_op(oname, odata) end end
param_handler(oparam)
click to toggle source
# File lib/lignite/system_commands.rb, line 88 def param_handler(oparam) case oparam["type"] when "U8" then ->(x) { u8(x) } when "U16" then ->(x) { u16(x) } when "U32" then ->(x) { u32(x) } when "BYTES" then ->(x) { x } when "ZBYTES" then ->(x) { x + u8(0) } else raise end end
parse_reply(reply, return_handlers)
click to toggle source
@param reply [ByteString] @param return_handlers [Array<Proc>] @return [Object,Array<Object>]
# File lib/lignite/system_commands.rb, line 64 def parse_reply(reply, return_handlers) replies = return_handlers.map do |h| parsed, reply = h.call(reply) parsed end raise "Unparsed reply #{reply.inspect}" unless reply.empty? # A single reply is returned as a scalar, not an array replies.size == 1 ? replies.first : replies end
return_handler(oparam)
click to toggle source
the handler is a lambda returning a pair: a parsed value and the rest of the input
# File lib/lignite/system_commands.rb, line 102 def return_handler(oparam) case oparam["type"] when "U8" then ->(i) { [unpack_u8(i[0, 1]), i[1..-1]] } when "U16" then ->(i) { [unpack_u16(i[0, 2]), i[2..-1]] } when "U32" then ->(i) { [unpack_u32(i[0, 4]), i[4..-1]] } when "BYTES" then ->(i) { [i, ""] } else raise end end
system_command_with_reply(instr_bytes)
click to toggle source
# File lib/lignite/system_commands.rb, line 113 def system_command_with_reply(instr_bytes) cmd = Message.system_command_with_reply(instr_bytes) @conn.send(cmd.bytes) reply = Message.reply_from_bytes(@conn.receive) assert_match(reply.msgid, cmd.msgid, "Reply id") assert_match(reply.command, unpack_u8(instr_bytes[0]), "Command num") raise VMError, format("Error: %u", reply.status) if reply.error? reply.data end