Why ChunkSpy .function part has four parameters? - lua

When using ChunkSpy, I find one thing makes me coufused. Let's see the following example
>a = 1
; source chunk: (interactive mode)
; x86 standard (32-bit, little endian, doubles)
; function [0] definition (level 1)
; 0 upvalues, 0 params, 2 stacks
.function 0 0 2 2
.const "a" ; 0
.const 1 ; 1
[1] loadk 0 1 ; 1
[2] setglobal 0 0 ; a
[3] return 0 1
; end of function
Since here is 0 upvalues, 0 params, 2 stacks, why there are four parameters in .function 0 0 2 2
In another example, we can see that
>local a; function b() a = 1 return a end
; source chunk: (interactive mode)
; x86 standard (32-bit, little endian, doubles)
; function [0] definition (level 1)
; 0 upvalues, 0 params, 2 stacks
.function 0 0 2 2
.local "a" ; 0
.const "b" ; 0
; function [0] definition (level 2)
; 1 upvalues, 0 params, 2 stacks
.function 1 0 0 2
.upvalue "a" ; 0
.const 1 ; 0
[1] loadk 0 0 ; 1
[2] setupval 0 0 ; a
[3] getupval 0 0 ; a
[4] return 0 2
[5] return 0 1
; end of function
[1] closure 1 0 ; 1 upvalues
[2] move 0 0
[3] setglobal 1 0 ; b
[4] return 0 1
; end of function
So I guess the first parameter is upvalues, but what is the use of the second?

I get the answer by the help of Egor Skriptunoff from comments.
The .fucntion part with four parameters are meaning like below:
number of upvales
number of named parameters
flag of arg : 1=VARARG_HASARG, 2=VARARG_ISVARARG, 4=VARARG_NEEDSARG. It's always 0 for normal function, and 2 for main function chunk.
number of stacks

Related

Why t[1] output is 1 for local t = {1, [1] = "a", [2] = "b"}

Test Code:
local t = {1, [1] = "a", [2] = "b"}
print("t[1]: ", t[1])
for _, v in pairs(t) do
print(v)
end
Output:
t[1]: 1
1
b
The order that fields are set in table constructors is not defined if you have duplicate keys.
Currently, the compiler batches list entries (50 list entries per batch).
The bytecode for your constructor can be seen by running luac -l on your script:
1 [1] NEWTABLE 0 1 2
2 [1] LOADK 1 -1 ; 1
3 [1] SETTABLE 0 -1 -2 ; 1 "a"
4 [1] SETTABLE 0 -3 -4 ; 2 "b"
5 [1] SETLIST 0 1 1 ; 1
Note the SETLIST at the end. For {10,20,30, [1] = "a", [2] = "b"}, the bytecode is:
1 [1] NEWTABLE 0 3 2
2 [1] LOADK 1 -1 ; 10
3 [1] LOADK 2 -2 ; 20
4 [1] LOADK 3 -3 ; 30
5 [1] SETTABLE 0 -4 -5 ; 1 "a"
6 [1] SETTABLE 0 -6 -7 ; 2 "b"
7 [1] SETLIST 0 3 1 ; 1
If the constructor began with a list of length 60 say, then the final value of t[1] would be "a".

Do math on string count (and text parsing with awk)

I have a 4 column file (input.file) with a header:
something1 something2 A B
followed by many 4-column rows with the same format (e.g.):
ID_00001 1 0 0
ID_00002 0 1 0
ID_00003 1 0 0
ID_00004 0 0 1
ID_00005 0 1 0
ID_00006 0 1 0
ID_00007 0 0 0
ID_00008 1 0 0
Where "1 0 0" is representative of "AA", "0 1 0" means "AB", and "0 0 1" means "BB"
First, I would like to create a 5th column to identify these representations:
ID_00001 1 0 0 AA
ID_00002 0 1 0 AB
ID_00003 1 0 0 AA
ID_00004 0 0 1 BB
ID_00005 0 1 0 AB
ID_00006 0 1 0 AB
ID_00007 0 0 0 no data
ID_00008 1 0 0 AA
Note that the A's and B's need to be parsed from columns 3 and 4 of the header row, as they are not always A and B.
Next, I want to "do math" on the counts for (the new) column 5 as follows:
(2BB + AB) / 2(AA + AB + BB)
Using the example, the math would give:
(2(1) + 3) / 2(3 + 3 + 1) = 5/14 = 0.357
which I would like to append to the end of the desired output file (output.file):
ID_00001 1 0 0 AA
ID_00002 0 1 0 AB
ID_00003 1 0 0 AA
ID_00004 0 0 1 BB
ID_00005 0 1 0 AB
ID_00006 0 1 0 AB
ID_00007 0 0 0 no data
ID_00008 1 0 0 AA
B_freq = 0.357
So far I have this:
awk '{ if ($2 = 1) {print $0, $5="AA"} \
else if($3 = 1) {print $0, $5="AB"} \
else if($4 = 1) {print $0, $5="BB"} \
else {print$0, $5="no data"}}' input.file > output.file
Obviously, I was not able to figure out how to parse the info from row 1 (the header row, edited out "column 1"), much less do the math.
Thanks guys!
a more structured approach...
NR==1 {a["100"]=$3$3; a["010"]=$3$4; a["001"]=$4$4; print; next}
{k=$2$3$4;
print $0, (k in a)?a[k]:"no data";
c[k]++}
END {printf "\nB freq = %.3f\n",
(2*c["001"]+c["010"]) / 2 / (c["100"]+c["010"]+c["001"])}
UPDATE
For non binary data you can follow the same logic with some pre-processing. Something like this should work in the main block:
for(i=2;i<5;i++) v[i]=(($i-0.9)^2<=0.1^2)?1:0;
k=v[2] v[3] v[4];
...
here the value is quantized at one for the range [0.8,1] and zero otherwise.
To capture "B" or substitute set h=$4 in the first block and use it as printf "\n%s freq...",h,(2*c...

Splitting a string where one item is in parentheses

Please find my code below.
str = "1791 (AR6K Async) S 2 0 0 0 -1 2129984 0 0 0 0 0 113 0 0 20 0 1 0 2370 0 0 4294967295 0 0 0 0 0 0 0 2147483647 0 3221520956 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
for val in str:gmatch("%S+") do
print(val)
end
Output:
1791
(AR6K
Async)
S
2
0
0
0
-1
....
But I am expecting the output like,
1791
(AR6K Async)
S
2
0
0
0
-1
...
Can anyone please help me how to get the values in bracket as a single value instead getting separate values.
str = "1791 (AR6K Async) S 2 0 0 0 -1 2129984 0 0 0 0 0 113 0 0 20 0 1 0 2370 0 0 4294967295 0 0 0 0 0 0 0 2147483647 0 3221520956 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
for val in str:gsub("%S+","\0%0\0")
:gsub("%b()", function(s) return s:gsub("%z","") end)
:gmatch("%z(.-)%z") do
print(val)
end
Explanation:
1. Surround all spaceless substrings with "zero marks"
(add one binary-zero-character at the beginning and one at the end)
2. Remove "zero marks" from inside parentheses
3. Display all surrounded parts
It may not be possible to use a single lua pattern alone to do this.
However it can be easy to roll your own parsing / splitting of the string or just extend your code a bit to concatenate the parts from a part that starts with ( to the part that ends with )
Here is a small example
str = "1791 (AR6K Async) S 2 0 0 0 -1 2129984 0 0 0 0 0 113 0 0 20 0 1 0 2370 0 0 4294967295 0 0 0 0 0 0 0 2147483647 0 3221520956 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
local temp
for val in str:gmatch("%S+") do
if temp then
if val:sub(#val, #val) == ")" then
print(temp.." "..val)
temp = nil
else
temp = temp.." "..val
end
elseif val:sub(1,1) == "(" then
temp = val
else
print(val)
end
end
This code behaves exactly like your own, except that when it encounters a substring that starts with an opening bracket, it will save it to temp variable. Then it will concatenate new values to temp until a substring with the closing bracket at the end of it is encountered. At that point the whole string saved to temp will be printed and temp is set to nil and the loop is continued normally.
So there is just a special case coded for when a string with brackets comes by.
This may not be the most efficient implementation, but it works. Also this assumes that the separators are spaces, since when the strings are concatenated to temp variable, they will be concatenated with an ordinary space. This does not handle nested brackets.
This was just a quick demonstration of the idea however so I believe you can fix these shortcomings on your own as you need to if you use it.

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

Delphi 7 boolean equations aren't working

I have a program written in Delphi 7 that appears to be experiencing some logic issues. the following line never gives a true value even when my watch window says it should.
Seq^.step[1] :=
(PlcStart^ and (not Seq^.Step[2])) or
(RetryDelay^.Done and (not Seq^.Step[2])) or
(Seq^.Step[1] and (not Seq^.Step[reset_]));
my watch window shows that (PlcStart^ and (not Seq^.Step[2])) or (RetryDelay^.Done and (not Seq^.Step[2])) or (Seq^.Step[1] and (not Seq^.Step[reset_])) is true but the value of Seq^.Step[1] never gets set to true.
The real strange part is that I have a number of programs with the exact same line that all appear to be working correctly.
Seq^.step[1] :=
(PlcStart^ and (not Seq^.Step[2])) or
(RetryDelay^.Done and (not Seq^.Step[2])) or
(Seq^.Step[1] and (not Seq^.Step[reset_]));
I'm not familiar with Delphi but I am familiar with boolean logic. If I'm reading this right your're saying:
(A ∧ ¬B) ∨ (C ∧ ¬B) ∨ (D ∧ ¬E)
in javascript that's:
(a && !b) || (c && !b) || (d && !e)
Using http://mustpax.github.io/Truth-Table-Generator/ to generate a truth table and converting "false" to "0" and "true" to "1", we get the truth table:
a b c d e (a & !b) | (c & !b) | (d & !e)
1 1 1 1 1 0
0 1 1 1 1 0
1 0 1 1 1 1
0 0 1 1 1 1
1 1 0 1 1 0
0 1 0 1 1 0
1 0 0 1 1 1
0 0 0 1 1 0
1 1 1 0 1 0
0 1 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 1 0 0 1 0
0 1 0 0 1 0
1 0 0 0 1 1
0 0 0 0 1 0
1 1 1 1 0 1
0 1 1 1 0 1
1 0 1 1 0 1
0 0 1 1 0 1
1 1 0 1 0 1
0 1 0 1 0 1
1 0 0 1 0 1
0 0 0 1 0 1
1 1 1 0 0 0
0 1 1 0 0 0
1 0 1 0 0 1
0 0 1 0 0 1
1 1 0 0 0 0
0 1 0 0 0 0
1 0 0 0 0 1
0 0 0 0 0 0
This table may or may not be correct, I haven't verified it. You can go through it and decide for yourself. Anyway, assuming it is correct, you could check the expected output for your given input and verify whether your expectations are correct.

Resources