lignite 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/NEWS.md +10 -0
- data/VERSION +1 -1
- data/examples/bobbee.rb +75 -29
- data/examples/gyro-sensor.rb +19 -0
- data/lib/lignite.rb +12 -0
- data/lib/lignite/assembler.rb +48 -5
- data/lib/lignite/body_compiler.rb +35 -37
- data/lib/lignite/condition.rb +116 -0
- data/lib/lignite/connection.rb +4 -0
- data/lib/lignite/ev3_ops.rb +104 -12
- data/lib/lignite/ev3_tool.rb +9 -2
- data/lib/lignite/jump_offset.rb +18 -0
- data/lib/lignite/motors.rb +17 -8
- data/lib/lignite/op_compiler.rb +52 -26
- data/lib/lignite/parameter_declarer.rb +15 -15
- data/lib/lignite/variables.rb +27 -15
- data/lignite.gemspec +3 -0
- data/spec/data/HelloWorld.rb +2 -2
- data/spec/data/Performance.rb +1 -1
- data/spec/data/Performance.rbf +0 -0
- data/spec/data/ev3tool_download.yml +4 -2
- data/spec/data/everstorm.rbf +0 -0
- data/spec/ev3_tool_spec.rb +4 -1
- data/tools/ops_from_yml +9 -1
- metadata +5 -2
| @@ -0,0 +1,116 @@ | |
| 1 | 
            +
            module Lignite
         | 
| 2 | 
            +
              # Compile a conditional jump forward or backward
         | 
| 3 | 
            +
              class Condition
         | 
| 4 | 
            +
                # Call that instruction of the compiler
         | 
| 5 | 
            +
                # that jumps by *offset* according to the condition that we implement
         | 
| 6 | 
            +
                def cond_jump(_compiler, _offset)
         | 
| 7 | 
            +
                  raise ScriptError, "subclasses must override this"
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                # Negation of this condition.
         | 
| 11 | 
            +
                # An `if(cond){ body }` becomes roughly `cond.not.jump_forward(body.size); body`
         | 
| 12 | 
            +
                def not
         | 
| 13 | 
            +
                  raise ScriptError, "subclasses must override this"
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def jump_forward(compiler, body_size)
         | 
| 17 | 
            +
                  cond_jump(compiler, body_size)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def jump_back(compiler, body_size, self_size = nil)
         | 
| 21 | 
            +
                  if self_size.nil?
         | 
| 22 | 
            +
                    fake = compiler.clone_context
         | 
| 23 | 
            +
                    jump_back(fake, body_size, 0)
         | 
| 24 | 
            +
                    self_size = fake.bytes.bytesize
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  cond_jump(compiler, - (body_size + self_size))
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              # A condition that is always true
         | 
| 32 | 
            +
              class Always < Condition
         | 
| 33 | 
            +
                def not
         | 
| 34 | 
            +
                  Never.new
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def cond_jump(compiler, offset)
         | 
| 38 | 
            +
                  compiler.jr(JumpOffset.new(offset))
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              # A condition that is never true
         | 
| 43 | 
            +
              class Never < Condition
         | 
| 44 | 
            +
                def not
         | 
| 45 | 
            +
                  Always.new
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def cond_jump(compiler, _offset)
         | 
| 49 | 
            +
                  # Never jump: do a jump of size 0
         | 
| 50 | 
            +
                  # but it must be a jump because code size calculations need that
         | 
| 51 | 
            +
                  compiler.jr(JumpOffset.new(0))
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              # Less-than (32 bit)
         | 
| 56 | 
            +
              class Lt32 < Condition
         | 
| 57 | 
            +
                def initialize(a, b)
         | 
| 58 | 
            +
                  @a = a
         | 
| 59 | 
            +
                  @b = b
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def not
         | 
| 63 | 
            +
                  Gteq32.new(@a, @b)
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def cond_jump(compiler, offset)
         | 
| 67 | 
            +
                  compiler.jr_lt32(@a, @b, JumpOffset.new(offset))
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              # Greater-than-or-equal (32 bit)
         | 
| 72 | 
            +
              class Gteq32 < Condition
         | 
| 73 | 
            +
                def initialize(a, b)
         | 
| 74 | 
            +
                  @a = a
         | 
| 75 | 
            +
                  @b = b
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                def not
         | 
| 79 | 
            +
                  Lt32.new(@a, @b)
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                def cond_jump(compiler, offset)
         | 
| 83 | 
            +
                  compiler.jr_gteq32(@a, @b, JumpOffset.new(offset))
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              # Test a boolean flag
         | 
| 88 | 
            +
              class Flag < Condition
         | 
| 89 | 
            +
                def initialize(f)
         | 
| 90 | 
            +
                  @f = f
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def not
         | 
| 94 | 
            +
                  NotFlag.new(@f)
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def cond_jump(compiler, offset)
         | 
| 98 | 
            +
                  compiler.jr_true(@f, JumpOffset.new(offset))
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              # Test a negated boolean flag
         | 
| 103 | 
            +
              class NotFlag < Condition
         | 
| 104 | 
            +
                def initialize(f)
         | 
| 105 | 
            +
                  @f = f
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                def not
         | 
| 109 | 
            +
                  Flag.new(@f)
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                def cond_jump(compiler, offset)
         | 
| 113 | 
            +
                  compiler.jr_false(@f, JumpOffset.new(offset))
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
            end
         | 
    
        data/lib/lignite/connection.rb
    CHANGED
    
    | @@ -5,18 +5,22 @@ module Lignite | |
| 5 5 | 
             
              class Connection
         | 
| 6 6 | 
             
                include Bytes
         | 
| 7 7 | 
             
                include Logger
         | 
| 8 | 
            +
                extend Logger
         | 
| 8 9 |  | 
| 9 10 | 
             
                # @return [Connection] Try a {Usb} connection first, then a {Bluetooth} one.
         | 
| 10 11 | 
             
                def self.create
         | 
| 11 12 | 
             
                  @c ||= Replay.new(ENV["LIGNITE_REPLAY"]) if ENV["LIGNITE_REPLAY"]
         | 
| 12 13 |  | 
| 13 14 | 
             
                  @c ||= begin
         | 
| 15 | 
            +
                           logger.debug "Connection: trying USB"
         | 
| 14 16 | 
             
                           Usb.new
         | 
| 15 17 | 
             
                         rescue NoUsbDevice
         | 
| 18 | 
            +
                           logger.debug "Connection: trying BT"
         | 
| 16 19 | 
             
                           Bluetooth.new
         | 
| 17 20 | 
             
                         end
         | 
| 18 21 |  | 
| 19 22 | 
             
                  @c = Tap.new(@c, ENV["LIGNITE_TAP"]) if ENV["LIGNITE_TAP"]
         | 
| 23 | 
            +
                  logger.debug "Connection: #{@c.inspect}"
         | 
| 20 24 | 
             
                  @c
         | 
| 21 25 | 
             
                end
         | 
| 22 26 |  | 
    
        data/lib/lignite/ev3_ops.rb
    CHANGED
    
    | @@ -140,7 +140,7 @@ module Lignite | |
| 140 140 |  | 
| 141 141 | 
             
                  bytes = u8(0x09)
         | 
| 142 142 | 
             
                  bytes += param_simple(objid)
         | 
| 143 | 
            -
                  bytes +=  | 
| 143 | 
            +
                  bytes += param_n_multiple(*parameters)
         | 
| 144 144 | 
             
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 145 145 | 
             
                  bytes
         | 
| 146 146 | 
             
                end
         | 
| @@ -862,7 +862,23 @@ module Lignite | |
| 862 862 | 
             
                  bytes
         | 
| 863 863 | 
             
                end
         | 
| 864 864 |  | 
| 865 | 
            -
                #  | 
| 865 | 
            +
                # Move LENGTH number of DATA8 from BYTE STREAM to memory DESTINATION START
         | 
| 866 | 
            +
                # @param destination [PAR8] (out) First element in DATA8 array to be initiated
         | 
| 867 | 
            +
                # @param length [PAR32] (in) Number of elements to initiate
         | 
| 868 | 
            +
                # @param source [PARVALUES] (in) First element to initiate DATA8 array with
         | 
| 869 | 
            +
                def init_bytes(destination, length, *source)
         | 
| 870 | 
            +
                  logger.debug do
         | 
| 871 | 
            +
                    args = [destination, length, *source]
         | 
| 872 | 
            +
                    "called init_bytes with #{args.inspect}"
         | 
| 873 | 
            +
                  end
         | 
| 874 | 
            +
             | 
| 875 | 
            +
                  bytes = u8(0x2F)
         | 
| 876 | 
            +
                  bytes += param_simple(destination)
         | 
| 877 | 
            +
                  bytes += param_simple(length)
         | 
| 878 | 
            +
                  bytes += param_multiple(*source)
         | 
| 879 | 
            +
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 880 | 
            +
                  bytes
         | 
| 881 | 
            +
                end
         | 
| 866 882 |  | 
| 867 883 | 
             
                # Move 8 bit value from SOURCE to DESTINATION
         | 
| 868 884 | 
             
                # @param source [PAR8] (in)
         | 
| @@ -6045,7 +6061,7 @@ module Lignite | |
| 6045 6061 | 
             
                  bytes += param_simple(no)
         | 
| 6046 6062 | 
             
                  bytes += param_simple(type)
         | 
| 6047 6063 | 
             
                  bytes += param_simple(mode)
         | 
| 6048 | 
            -
                  bytes +=  | 
| 6064 | 
            +
                  bytes += param_n_multiple(*values)
         | 
| 6049 6065 | 
             
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 6050 6066 | 
             
                  bytes
         | 
| 6051 6067 | 
             
                end
         | 
| @@ -6070,7 +6086,7 @@ module Lignite | |
| 6070 6086 | 
             
                  bytes += param_simple(no)
         | 
| 6071 6087 | 
             
                  bytes += param_simple(type)
         | 
| 6072 6088 | 
             
                  bytes += param_simple(mode)
         | 
| 6073 | 
            -
                  bytes +=  | 
| 6089 | 
            +
                  bytes += param_n_multiple(*values)
         | 
| 6074 6090 | 
             
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 6075 6091 | 
             
                  bytes
         | 
| 6076 6092 | 
             
                end
         | 
| @@ -6095,7 +6111,7 @@ module Lignite | |
| 6095 6111 | 
             
                  bytes += param_simple(no)
         | 
| 6096 6112 | 
             
                  bytes += param_simple(type)
         | 
| 6097 6113 | 
             
                  bytes += param_simple(mode)
         | 
| 6098 | 
            -
                  bytes +=  | 
| 6114 | 
            +
                  bytes += param_n_multiple(*values)
         | 
| 6099 6115 | 
             
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 6100 6116 | 
             
                  bytes
         | 
| 6101 6117 | 
             
                end
         | 
| @@ -6277,7 +6293,7 @@ module Lignite | |
| 6277 6293 | 
             
                  bytes += param_simple(type)
         | 
| 6278 6294 | 
             
                  bytes += param_simple(mode)
         | 
| 6279 6295 | 
             
                  bytes += param_simple(format)
         | 
| 6280 | 
            -
                  bytes +=  | 
| 6296 | 
            +
                  bytes += param_n_multiple(*values)
         | 
| 6281 6297 | 
             
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 6282 6298 | 
             
                  bytes
         | 
| 6283 6299 | 
             
                end
         | 
| @@ -7559,19 +7575,95 @@ module Lignite | |
| 7559 7575 | 
             
                #
         | 
| 7560 7576 | 
             
                Lignite::INIT8 = 8
         | 
| 7561 7577 |  | 
| 7562 | 
            -
                # | 
| 7578 | 
            +
                #
         | 
| 7579 | 
            +
                # @param handle [PAR16] (in) Array handle
         | 
| 7580 | 
            +
                # @param index [PAR32] (in) Index to element to write
         | 
| 7581 | 
            +
                # @param elements [PAR32] (in) Number of elements to write
         | 
| 7582 | 
            +
                # @param values [PARVALUES] (in)
         | 
| 7583 | 
            +
                def array_init8(handle, index, elements, *values)
         | 
| 7584 | 
            +
                  logger.debug do
         | 
| 7585 | 
            +
                    args = [handle, index, elements, *values]
         | 
| 7586 | 
            +
                    "called array_init8 with #{args.inspect}"
         | 
| 7587 | 
            +
                  end
         | 
| 7588 | 
            +
             | 
| 7589 | 
            +
                  bytes = u8(0xC1)
         | 
| 7590 | 
            +
                  bytes += param_simple(8)
         | 
| 7591 | 
            +
                  bytes += param_simple(handle)
         | 
| 7592 | 
            +
                  bytes += param_simple(index)
         | 
| 7593 | 
            +
                  bytes += param_simple(elements)
         | 
| 7594 | 
            +
                  bytes += param_multiple(*values)
         | 
| 7595 | 
            +
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 7596 | 
            +
                  bytes
         | 
| 7597 | 
            +
                end
         | 
| 7563 7598 | 
             
                #
         | 
| 7564 7599 | 
             
                Lignite::INIT16 = 9
         | 
| 7565 7600 |  | 
| 7566 | 
            -
                # | 
| 7601 | 
            +
                #
         | 
| 7602 | 
            +
                # @param handle [PAR16] (in) Array handle
         | 
| 7603 | 
            +
                # @param index [PAR32] (in) Index to element to write
         | 
| 7604 | 
            +
                # @param elements [PAR32] (in) Number of elements to write
         | 
| 7605 | 
            +
                # @param values [PARVALUES] (in)
         | 
| 7606 | 
            +
                def array_init16(handle, index, elements, *values)
         | 
| 7607 | 
            +
                  logger.debug do
         | 
| 7608 | 
            +
                    args = [handle, index, elements, *values]
         | 
| 7609 | 
            +
                    "called array_init16 with #{args.inspect}"
         | 
| 7610 | 
            +
                  end
         | 
| 7611 | 
            +
             | 
| 7612 | 
            +
                  bytes = u8(0xC1)
         | 
| 7613 | 
            +
                  bytes += param_simple(9)
         | 
| 7614 | 
            +
                  bytes += param_simple(handle)
         | 
| 7615 | 
            +
                  bytes += param_simple(index)
         | 
| 7616 | 
            +
                  bytes += param_simple(elements)
         | 
| 7617 | 
            +
                  bytes += param_multiple(*values)
         | 
| 7618 | 
            +
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 7619 | 
            +
                  bytes
         | 
| 7620 | 
            +
                end
         | 
| 7567 7621 | 
             
                #
         | 
| 7568 7622 | 
             
                Lignite::INIT32 = 10
         | 
| 7569 7623 |  | 
| 7570 | 
            -
                # | 
| 7624 | 
            +
                #
         | 
| 7625 | 
            +
                # @param handle [PAR16] (in) Array handle
         | 
| 7626 | 
            +
                # @param index [PAR32] (in) Index to element to write
         | 
| 7627 | 
            +
                # @param elements [PAR32] (in) Number of elements to write
         | 
| 7628 | 
            +
                # @param values [PARVALUES] (in)
         | 
| 7629 | 
            +
                def array_init32(handle, index, elements, *values)
         | 
| 7630 | 
            +
                  logger.debug do
         | 
| 7631 | 
            +
                    args = [handle, index, elements, *values]
         | 
| 7632 | 
            +
                    "called array_init32 with #{args.inspect}"
         | 
| 7633 | 
            +
                  end
         | 
| 7634 | 
            +
             | 
| 7635 | 
            +
                  bytes = u8(0xC1)
         | 
| 7636 | 
            +
                  bytes += param_simple(10)
         | 
| 7637 | 
            +
                  bytes += param_simple(handle)
         | 
| 7638 | 
            +
                  bytes += param_simple(index)
         | 
| 7639 | 
            +
                  bytes += param_simple(elements)
         | 
| 7640 | 
            +
                  bytes += param_multiple(*values)
         | 
| 7641 | 
            +
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 7642 | 
            +
                  bytes
         | 
| 7643 | 
            +
                end
         | 
| 7571 7644 | 
             
                #
         | 
| 7572 7645 | 
             
                Lignite::INITF = 11
         | 
| 7573 7646 |  | 
| 7574 | 
            -
                # | 
| 7647 | 
            +
                #
         | 
| 7648 | 
            +
                # @param handle [PAR16] (in) Array handle
         | 
| 7649 | 
            +
                # @param index [PAR32] (in) Index to element to write
         | 
| 7650 | 
            +
                # @param elements [PAR32] (in) Number of elements to write
         | 
| 7651 | 
            +
                # @param values [PARVALUES] (in)
         | 
| 7652 | 
            +
                def array_initf(handle, index, elements, *values)
         | 
| 7653 | 
            +
                  logger.debug do
         | 
| 7654 | 
            +
                    args = [handle, index, elements, *values]
         | 
| 7655 | 
            +
                    "called array_initf with #{args.inspect}"
         | 
| 7656 | 
            +
                  end
         | 
| 7657 | 
            +
             | 
| 7658 | 
            +
                  bytes = u8(0xC1)
         | 
| 7659 | 
            +
                  bytes += param_simple(11)
         | 
| 7660 | 
            +
                  bytes += param_simple(handle)
         | 
| 7661 | 
            +
                  bytes += param_simple(index)
         | 
| 7662 | 
            +
                  bytes += param_simple(elements)
         | 
| 7663 | 
            +
                  bytes += param_multiple(*values)
         | 
| 7664 | 
            +
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 7665 | 
            +
                  bytes
         | 
| 7666 | 
            +
                end
         | 
| 7575 7667 | 
             
                #
         | 
| 7576 7668 | 
             
                Lignite::SIZE = 12
         | 
| 7577 7669 |  | 
| @@ -8924,7 +9016,7 @@ module Lignite | |
| 8924 9016 | 
             
                  bytes += param_simple(hardware)
         | 
| 8925 9017 | 
             
                  bytes += param_simple(boxname)
         | 
| 8926 9018 | 
             
                  bytes += param_simple(type)
         | 
| 8927 | 
            -
                  bytes +=  | 
| 9019 | 
            +
                  bytes += param_n_multiple(*values)
         | 
| 8928 9020 | 
             
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 8929 9021 | 
             
                  bytes
         | 
| 8930 9022 | 
             
                end
         | 
| @@ -8942,7 +9034,7 @@ module Lignite | |
| 8942 9034 | 
             
                  bytes = u8(0xDA)
         | 
| 8943 9035 | 
             
                  bytes += param_simple(no)
         | 
| 8944 9036 | 
             
                  bytes += param_simple(length)
         | 
| 8945 | 
            -
                  bytes +=  | 
| 9037 | 
            +
                  bytes += param_n_multiple(*values)
         | 
| 8946 9038 | 
             
                  logger.debug "returning bytecode: #{bytes.inspect}"
         | 
| 8947 9039 | 
             
                  bytes
         | 
| 8948 9040 | 
             
                end
         | 
    
        data/lib/lignite/ev3_tool.rb
    CHANGED
    
    | @@ -32,14 +32,15 @@ module Lignite | |
| 32 32 | 
             
                desc "download BRICK_FILENAME [LOCAL_FILENAME]", "download a file"
         | 
| 33 33 | 
             
                map "dl" => "download"
         | 
| 34 34 | 
             
                def download(brick_filename, local_filename = nil)
         | 
| 35 | 
            +
                  chunk_size = 1000 # 2000 stalls, 4096 goes out of sync in our code
         | 
| 35 36 | 
             
                  local_filename ||= File.basename(brick_filename)
         | 
| 36 | 
            -
                  fsize, handle, data = sc.begin_upload( | 
| 37 | 
            +
                  fsize, handle, data = sc.begin_upload(chunk_size, brick_filename)
         | 
| 37 38 | 
             
                  File.open(local_filename, "w") do |f|
         | 
| 38 39 | 
             
                    loop do
         | 
| 39 40 | 
             
                      f.write(data)
         | 
| 40 41 | 
             
                      fsize -= data.bytesize
         | 
| 41 42 | 
             
                      break if fsize.zero?
         | 
| 42 | 
            -
                      handle, data = sc.continue_upload(handle,  | 
| 43 | 
            +
                      handle, data = sc.continue_upload(handle, chunk_size)
         | 
| 43 44 | 
             
                    end
         | 
| 44 45 | 
             
                  end
         | 
| 45 46 | 
             
                end
         | 
| @@ -55,6 +56,12 @@ module Lignite | |
| 55 56 | 
             
                  puts raw_ls(name)
         | 
| 56 57 | 
             
                end
         | 
| 57 58 |  | 
| 59 | 
            +
                desc "asm RUBYFILE RBFFILE", "assemble RUBYFILE to RBFFILE"
         | 
| 60 | 
            +
                def asm(ruby_fn, rbf_fn)
         | 
| 61 | 
            +
                  a = Assembler.new
         | 
| 62 | 
            +
                  a.assemble(ruby_fn, rbf_fn)
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 58 65 | 
             
                no_commands do
         | 
| 59 66 | 
             
                  def raw_list_files(name)
         | 
| 60 67 | 
             
                    name ||= EV3TOOL_HOME
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            module Lignite
         | 
| 2 | 
            +
              # A specialized Integer.
         | 
| 3 | 
            +
              # When compiling jumps, the jump instruction itself must have a constant size
         | 
| 4 | 
            +
              # so this class is special-cased in {OpCompiler#param_simple}.
         | 
| 5 | 
            +
              class JumpOffset
         | 
| 6 | 
            +
                # @return [Integer]
         | 
| 7 | 
            +
                attr_reader :value
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def size
         | 
| 10 | 
            +
                  2
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def initialize(v)
         | 
| 14 | 
            +
                  raise "Jumping too far: #{value}" if v.abs > 32767
         | 
| 15 | 
            +
                  @value = v
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
    
        data/lib/lignite/motors.rb
    CHANGED
    
    | @@ -13,9 +13,18 @@ module Lignite | |
| 13 13 |  | 
| 14 14 | 
             
                # 0x02 | 0x04 | 0x08 -> [1, 2, 3]
         | 
| 15 15 | 
             
                def nos_as_indices
         | 
| 16 | 
            -
                  [0, 1, 2, 3].find_all do |n|
         | 
| 16 | 
            +
                  r = [0, 1, 2, 3].find_all do |n|
         | 
| 17 17 | 
             
                    (nos & (1 << n)) != 0
         | 
| 18 18 | 
             
                  end
         | 
| 19 | 
            +
                  r
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # 0x02 | 0x04 | 0x08 -> [0x02, 0x04, 0x08]
         | 
| 23 | 
            +
                def nos_as_bits
         | 
| 24 | 
            +
                  r = [1, 2, 4, 8].find_all do |n|
         | 
| 25 | 
            +
                    (nos & n) != 0
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                  r
         | 
| 19 28 | 
             
                end
         | 
| 20 29 |  | 
| 21 30 | 
             
                def initialize(layer, nos, dc = Lignite::DirectCommands.new)
         | 
| @@ -85,17 +94,17 @@ module Lignite | |
| 85 94 | 
             
                end
         | 
| 86 95 |  | 
| 87 96 | 
             
                # ATTR running?
         | 
| 97 | 
            +
                # @return [Boolean] true if busy/running
         | 
| 88 98 | 
             
                def test
         | 
| 89 99 | 
             
                  layer = @layer
         | 
| 90 | 
            -
                   | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
                      end
         | 
| 100 | 
            +
                  nos = @nos
         | 
| 101 | 
            +
                  busy = dc.with_reply do
         | 
| 102 | 
            +
                    data8 :busy
         | 
| 103 | 
            +
                    block do
         | 
| 104 | 
            +
                      output_test(layer, nos, :busy)
         | 
| 96 105 | 
             
                    end
         | 
| 97 | 
            -
                    busy
         | 
| 98 106 | 
             
                  end
         | 
| 107 | 
            +
                  busy != 0
         | 
| 99 108 | 
             
                end
         | 
| 100 109 |  | 
| 101 110 | 
             
                # which commands are affected? not output_start they say
         | 
    
        data/lib/lignite/op_compiler.rb
    CHANGED
    
    | @@ -43,22 +43,29 @@ module Lignite | |
| 43 43 |  | 
| 44 44 | 
             
                PRIMPAR_LABEL      = 0x20
         | 
| 45 45 |  | 
| 46 | 
            -
                 | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                   | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 46 | 
            +
                # @param n [Integer] value to encode
         | 
| 47 | 
            +
                # @param next_size [Integer] how many bytes follow the initial opcode
         | 
| 48 | 
            +
                # @return [ByteString]
         | 
| 49 | 
            +
                def numeric_literal_with_size(n, next_size)
         | 
| 50 | 
            +
                  bytes = case next_size
         | 
| 51 | 
            +
                          when 0
         | 
| 52 | 
            +
                            [n & PRIMPAR_VALUE]
         | 
| 53 | 
            +
                          when 1
         | 
| 54 | 
            +
                            [PRIMPAR_LONG | PRIMPAR_1_BYTE, n & 0xff]
         | 
| 55 | 
            +
                          when 2
         | 
| 56 | 
            +
                            [PRIMPAR_LONG | PRIMPAR_2_BYTES, n & 0xff, (n >> 8) & 0xff]
         | 
| 57 | 
            +
                          else
         | 
| 58 | 
            +
                            [PRIMPAR_LONG | PRIMPAR_4_BYTES,
         | 
| 59 | 
            +
                             n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]
         | 
| 57 60 | 
             
                  end
         | 
| 61 | 
            +
                  bytes.map(&:chr).join("")
         | 
| 58 62 | 
             
                end
         | 
| 59 63 |  | 
| 60 | 
            -
                 | 
| 61 | 
            -
             | 
| 64 | 
            +
                # @param n [Integer] value to encode
         | 
| 65 | 
            +
                # @param next_size [Integer] how many bytes follow the initial opcode
         | 
| 66 | 
            +
                # @return [ByteString]
         | 
| 67 | 
            +
                def numeric_literal(n, next_size = nil)
         | 
| 68 | 
            +
                  next_size ||= if (-31..31).cover? n
         | 
| 62 69 | 
             
                    0
         | 
| 63 70 | 
             
                  elsif (-127..127).cover? n
         | 
| 64 71 | 
             
                    1
         | 
| @@ -67,12 +74,13 @@ module Lignite | |
| 67 74 | 
             
                  else
         | 
| 68 75 | 
             
                    4
         | 
| 69 76 | 
             
                  end
         | 
| 70 | 
            -
                   | 
| 77 | 
            +
                  numeric_literal_with_size(n, next_size)
         | 
| 71 78 | 
             
                end
         | 
| 72 79 |  | 
| 80 | 
            +
                # @return [ByteString]
         | 
| 73 81 | 
             
                def make_v(n, local_or_global)
         | 
| 74 82 | 
             
                  vartag = PRIMPAR_VARIABEL | local_or_global
         | 
| 75 | 
            -
                  if (0..31).cover? n
         | 
| 83 | 
            +
                  bytes = if (0..31).cover? n
         | 
| 76 84 | 
             
                    [vartag | (n & PRIMPAR_VALUE)]
         | 
| 77 85 | 
             
                  elsif (0..255).cover? n
         | 
| 78 86 | 
             
                    [vartag | PRIMPAR_LONG | PRIMPAR_1_BYTE, n & 0xff]
         | 
| @@ -82,10 +90,12 @@ module Lignite | |
| 82 90 | 
             
                    [vartag | PRIMPAR_LONG | PRIMPAR_4_BYTES,
         | 
| 83 91 | 
             
                     n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]
         | 
| 84 92 | 
             
                  end
         | 
| 93 | 
            +
                  bytes.map(&:chr).join("")
         | 
| 85 94 | 
             
                end
         | 
| 86 95 |  | 
| 87 96 | 
             
                # Reference a variable.
         | 
| 88 97 | 
             
                # (For declaring, see {VariableDeclarer}.)
         | 
| 98 | 
            +
                # @return [ByteString]
         | 
| 89 99 | 
             
                def make_var(sym)
         | 
| 90 100 | 
             
                  raise "No variables declared, cannot process symbols" if @locals.nil? && @globals.nil?
         | 
| 91 101 | 
             
                  if @locals.key?(sym)
         | 
| @@ -99,27 +109,43 @@ module Lignite | |
| 99 109 | 
             
                  end
         | 
| 100 110 | 
             
                end
         | 
| 101 111 |  | 
| 112 | 
            +
                # @return [ByteString]
         | 
| 113 | 
            +
                def param_n_multiple(*args)
         | 
| 114 | 
            +
                  u8(args.size) + param_multiple(*args)
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 102 117 | 
             
                # @return [ByteString]
         | 
| 103 118 | 
             
                def param_multiple(*args)
         | 
| 104 | 
            -
                   | 
| 119 | 
            +
                  args.map { |a| param_simple(a) }.join("")
         | 
| 105 120 | 
             
                end
         | 
| 106 121 |  | 
| 107 122 | 
             
                # @return [ByteString]
         | 
| 108 | 
            -
                def  | 
| 123 | 
            +
                def param_simple_numeric(x)
         | 
| 109 124 | 
             
                  case x
         | 
| 110 125 | 
             
                  when Integer
         | 
| 111 | 
            -
                     | 
| 112 | 
            -
                  when Complex
         | 
| 113 | 
            -
                    # a Complex number:
         | 
| 114 | 
            -
                    #   #real: just like an Integer above, but
         | 
| 115 | 
            -
                    #   #imag tells how many bytes to use for it
         | 
| 116 | 
            -
                    make_lc(x.real, x.imag).map(&:chr).join("")
         | 
| 117 | 
            -
                  when String
         | 
| 118 | 
            -
                    u8(0x80) + x + u8(0x00)
         | 
| 126 | 
            +
                    numeric_literal(x)
         | 
| 119 127 | 
             
                  when Float
         | 
| 120 128 | 
             
                    u8(0x83) + f32(x)
         | 
| 129 | 
            +
                  else
         | 
| 130 | 
            +
                    raise ArgumentError, "Unexpected type: #{x.class}"
         | 
| 131 | 
            +
                  end
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                # @return [ByteString]
         | 
| 135 | 
            +
                def param_simple(x)
         | 
| 136 | 
            +
                  case x
         | 
| 137 | 
            +
                  when Numeric
         | 
| 138 | 
            +
                    param_simple_numeric(x)
         | 
| 139 | 
            +
                  when JumpOffset
         | 
| 140 | 
            +
                    numeric_literal(x.value, x.size)
         | 
| 141 | 
            +
                  when String
         | 
| 142 | 
            +
                    u8(0x80) + x + u8(0x00)
         | 
| 143 | 
            +
                  when true
         | 
| 144 | 
            +
                    param_simple(1)
         | 
| 145 | 
            +
                  when false
         | 
| 146 | 
            +
                    param_simple(0)
         | 
| 121 147 | 
             
                  when Symbol
         | 
| 122 | 
            -
                    make_var(x) | 
| 148 | 
            +
                    make_var(x)
         | 
| 123 149 | 
             
                  else
         | 
| 124 150 | 
             
                    raise ArgumentError, "Unexpected type: #{x.class}"
         | 
| 125 151 | 
             
                  end
         |