how to run the bytecode generated by ruby? - ruby-on-rails

I am new to the Ruby scripting language.
I was learning how to generate the byte code in Ruby.
I found the answer for generating the byte code.
But I don't know how to run that generated byte code. I searched the internet, but I didn't get the answer for this.
Generating a byte code:-
puts RubyVM::InstructionSequence.compile("x = 50; x > 100 ? 'foo' : 'bar'").disassemble
The output is,
== disasm: <RubyVM::InstructionSequence:<compiled>#<compiled>>==========
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] x
0000 trace 1 ( 1)
0002 putobject 50
0004 setlocal x
0006 trace 1
0008 getlocal x
0010 putobject 100
0012 opt_gt <ic:1>
0014 branchunless 20
0016 putstring "foo"
0018 leave
0019 pop
0020 putstring "bar"
0022 leave
I don't know how to execute the same script, by using the generated byte code.
Anyone please explain me how to execute this.
Thanks in advance!

TL;DR; You are looking for .eval method.
The .compile method would return an instance of RubyVM::InstructionSequence class, which has .eval method that evaluates/runs your "compiled" instructions.
iseq = RubyVM::InstructionSequence.compile("x = 50; x > 100 ? 'foo' : 'bar'")
iseq.eval # => "bar"
Or, a oneliner:
RubyVM::InstructionSequence.compile("x = 50; x > 100 ? 'foo' : 'bar'").eval

Related

how do i convert int to byte and back

given a 64bit int I need to split it into 4 x 2bytes int.
for example decimal 66309 is 0000 0000 0000 0001 0000 0011 0000 0101
I need to convert this into an array of 4 ints {0, 1, 3, 5}. How can I do it in lua?
First, the conversion of 66309 into four 16 bit integers wouldn't be {0, 1, 3, 5}, but {0, 0, 1, 773}. In your example, you are splitting it into 8 bit integers. The below does 16 bit integers.
local int = 66309
local t = {}
for i = 0, 3 do
t[i+1] = (int >> (i * 16)) & 0xFFFF
end
If you want it to be 8 bit integers change the 3 in the loop to 7, the 16 in the shift expression to an 8, and the hex mask 0xFFFF to 0xFF.
And finally, this only works for Lua 5.3. You cannot accurately represent a 64 bit integer in Lua before this version without external libraries.

Lua - local required eveytime a local variable is assigned?

I've found a strange piece of code in the Lua documentation :
function trim8(s)
local i1,i2 = find(s,'^%s*')
if i2 >= i1 then s = sub(s,i2+1) end
local i1,i2 = find(s,'%s*$')
if i2 >= i1 then s = sub(s,1,i1-1) end
return s
end
Why is local used once again with i1 and i2? Aren't they already declared among local variables? Do you have to repeat the local keyword every time you want to assign them?
No, it is not necessary to use local over and over. The variables i1 and i2 will be local in the scope of the function because of the first line itself.
While it should not be done, there is nothing wrong with defining the same variables over and over. It will just assign a new position in stack to the newer, and shadow the older one.
The following is the instruction output for a simple function:
function t()
local i = 2
local i = 3
end
t()
function <temp.lua:1,4> (3 instructions, 12 bytes at 00658990)
0 params, 2 slots, 0 upvalues, 2 locals, 2 constants, 0 functions
1 [2] LOADK 0 -1 ; 2
2 [3] LOADK 1 -2 ; 3
3 [4] RETURN 0 1
and updating the second local i = 3 to just i = 3:
function t()
local i = 2
i = 3
end
t()
function <temp.lua:1,4> (3 instructions, 12 bytes at 00478990)
0 params, 2 slots, 0 upvalues, 1 local, 2 constants, 0 functions
1 [2] LOADK 0 -1 ; 2
2 [3] LOADK 0 -2 ; 3
3 [4] RETURN 0 1
Notice the difference at the second instruction.
Apart from that, the function is quite inefficient. You can instead use the following:
function Trim(sInput)
return sInput:match "^%s*(.-)%s*$"
end
Technically, using local or not in the second declaration are not equivalent. Using a second local would declare another variable.
However in your example code, they have basically the same. Check these simpler code:
local a = 0
local a = 1
and
local a = 0
a = 1
Use luac -p -l outputs the following result:
0+ params, 2 slots, 0 upvalues, 2 locals, 2 constants, 0 functions
1 [1] LOADK 0 -1 ; 0
2 [2] LOADK 1 -2 ; 1
3 [2] RETURN 0 1
and
0+ params, 2 slots, 0 upvalues, 1 local, 2 constants, 0 functions
1 [1] LOADK 0 -1 ; 0
2 [2] LOADK 0 -2 ; 1
3 [2] RETURN 0 1

Comparing signed 64 bit number using 32 bit bitwise operations in Lua

I am using Lua on Redis and want to compare two signed 64-bit numbers, which are stored in two 8-byte/character strings.
How can I compare them using the libraries available in Redis?
http://redis.io/commands/EVAL#available-libraries
I'd like to know >/< and == checks. I think this probably involves pulling two 32-bit numbers for each 64-bit int, and doing some clever math on those, but I am not sure.
I have some code to make this less abstract. a0, a1, b0, b1 are all 32 bit numbers used to represent the msb & lsb's of two 64-bit signed int 64s:
-- ...
local comp_int64s = function (a0, a1, b0, b1)
local cmpres = 0
-- TOOD: Real comparison
return cmpres
end
local l, a0, a1, b0, b1
a0, l = bit.tobit(struct.unpack("I4", ARGV[1]))
a1, l = bit.tobit(struct.unpack("I4", ARGV[1], 5))
b0, l = bit.tobit(struct.unpack("I4", blob))
b1, l = bit.tobit(struct.unpack("I4", blob, 5))
print("Cmp result", comp_int64s(a0, a1, b0, b1))
EDIT: Added code
I came up with a method that looks like it's working. It's a little ugly though.
The first step is to compare top 32 bits as 2 compliment #’s
MSB sign bit stays, so numbers keep correct relations
-1 —> -1
0 —> 0
9223372036854775807 = 0x7fff ffff ffff ffff -> 0x7ffff ffff = 2147483647
So returning the result from the MSB's works unless they are equal, then the LSB's need to get checked.
I have a few cases to establish the some patterns:
-1 = 0xffff ffff ffff ffff
-2 = 0xffff ffff ffff fffe
32 bit is:
-1 -> 0xffff ffff = -1
-2 -> 0xffff fffe = -2
-1 > -2 would be like -1 > -2 : GOOD
And
8589934591 = 0x0000 0001 ffff ffff
8589934590 = 0x0000 0001 ffff fffe
32 bit is:
8589934591 -> ffff ffff = -1
8589934590 -> ffff fffe = -2
8589934591 > 8589934590 would be -1 > -2 : GOOD
The sign bit on MSB’s doesn’t matter b/c negative numbers have the same relationship between themselves as positive numbers. e.g regardless of sign bit, lsb values of 0xff > 0xfe, always.
What about if the MSB on the lower 32 bits is different?
0xff7f ffff 7fff ffff = -36,028,799,166,447,617
0xff7f ffff ffff ffff = -36,028,797,018,963,969
32 bit is:
-..799.. -> 0x7fff ffff = 2147483647
-..797.. -> 0xffff ffff = -1
-..799.. < -..797.. would be 2147483647 < -1 : BAD!
So we need to ignore the sign bit on the lower 32 bits. And since the relationships are the same for the LSBs regardless of sign, just using
the lowest 32 bits unsigned works for all cases.
This means I want signed for the MSB's and unsigned for the LSBs - so chaging I4 to i4 for the LSBs. Also making big endian official and using '>' on the struct.unpack calls:
-- ...
local comp_int64s = function (as0, au1, bs0, bu1)
if as0 > bs0 then
return 1
elseif as0 < bs0 then
return -1
else
-- msb's equal comparing lsbs - these are unsigned
if au1 > bu1 then
return 1
elseif au1 < bu1 then
return -1
else
return 0
end
end
end
local l, as0, au1, bs0, bu1
as0, l = bit.tobit(struct.unpack(">i4", ARGV[1]))
au1, l = bit.tobit(struct.unpack(">I4", ARGV[1], 5))
bs0, l = bit.tobit(struct.unpack(">i4", blob))
bu1, l = bit.tobit(struct.unpack(">I4", blob, 5))
print("Cmp result", comp_int64s(as0, au1, bs0, bu1))
Comparing is a simple string compare s1 == s2.
Greater than is when not s1 == s2 and i1 < i2.
Less than is the real work. string.byte allows to get single bytes as unsigned char. In case of unsigned integer, you would just have to check bytes-downwards: b1==b2 -> check next byte; through all bytes -> false (equal); b1>b2 -> false (greater than); b1<b2 -> true. Signed requires more steps: first check the sign bit (uppermost byte >127). If sign 1 is set but not sign 2, integer 1 is negative but not integer 2 -> true. The opposite would obviously result in false. When both signs are equal, you can do the unsigned processing.
When you can pack more bytes to an integer, it's fine too, but you have to adjust the sign bit check. When you have LuaJIT, you can use the ffi library to cast your string into a byte array into an int64.

"Bitwise AND" in Lua

I'm trying to translate a code from C to Lua and I'm facing a problem.
How can I translate a Bitwise AND in Lua?
The source C code contains:
if ((command&0x80)==0)
...
How can this be done in Lua?
I am using Lua 5.1.4-8
Implementation of bitwise operations in Lua 5.1 for non-negative 32-bit integers
OR, XOR, AND = 1, 3, 4
function bitoper(a, b, oper)
local r, m, s = 0, 2^31
repeat
s,a,b = a+b+m, a%m, b%m
r,m = r + m*oper%(s-a-b), m/2
until m < 1
return r
end
print(bitoper(6,3,OR)) --> 7
print(bitoper(6,3,XOR)) --> 5
print(bitoper(6,3,AND)) --> 2
Here is a basic, isolated bitwise-and implementation in pure Lua 5.1:
function bitand(a, b)
local result = 0
local bitval = 1
while a > 0 and b > 0 do
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
result = result + bitval -- set the current bit
end
bitval = bitval * 2 -- shift left
a = math.floor(a/2) -- shift right
b = math.floor(b/2)
end
return result
end
usage:
print(bitand(tonumber("1101", 2), tonumber("1001", 2))) -- prints 9 (1001)
Here's an example of how i bitwise-and a value with a constant 0x8000:
result = (value % 65536) - (value % 32768) -- bitwise and 0x8000
In case you use Adobe Lightroom Lua, Lightroom SDK contains LrMath.bitAnd() method for "bitwise AND" operation:
-- x = a AND b
local a = 11
local b = 6
local x = import 'LrMath'.bitAnd(a, b)
-- x is 2
And there are also LrMath.bitOr(a, b) and LrMath.bitXor(a, b) methods for "bitwise OR" and "biwise XOR" operations.
This answer is specifically for Lua 5.1.X
you can use
if( (bit.band(command,0x80)) == 0) then
...
in Lua 5.3.X and onwards it's very straight forward...
print(5 & 6)
hope that helped 😉

How do I show the contents of a matrix?

Consider:
: cell-matrix
create ( width height "name" ) over , * cells allot
does> ( x y -- addr ) dup cell+ >r # * + cells r> + ;
It is the definition that makes the matrix and then you assign values like this:
5 5 cell-matrix test
And then you stuff the values into there.... There they're...
36 0 0 test !
(I think)
Nowhere on the Internet can you find anything to explain this. How do you show the contents of the matrix?
If you want to print the contents of the whole matrix, you can do something like:
: .row ( addr u -- addr' u ) tuck 0 do #+ . loop swap cr ;
: .matrix ( u addr -- ) >body #+ rot 0 do .row loop 2drop ;
Note that your cell-matrix doesn't save the number of rows, so you have to supply this number to .matrix. E.g. like this:
2 3 cell-matrix foo
3 ' foo .matrix
Logically simple:
100 0 0 test ! ok
400 1 0 test ! ok
0 0 test # . 100 ok
1 0 test # . 400 ok

Resources