issue #98 removing new parser code as migrated to ravi-compiler project
parent
bfaf2a3cef
commit
5834e4c78f
File diff suppressed because it is too large
Load Diff
@ -1,89 +0,0 @@
|
||||
# Test AST construction
|
||||
|
||||
local function dotest(code)
|
||||
local x = ast.parse(code)
|
||||
print('--[[' .. code .. '\n]]')
|
||||
print(x:tostring())
|
||||
print '--'
|
||||
end
|
||||
|
||||
local x
|
||||
|
||||
dotest 'return'
|
||||
dotest 'return 1'
|
||||
dotest 'return 42, 4.2, true, "hello"'
|
||||
dotest 'return a'
|
||||
dotest 'return 1+2'
|
||||
dotest 'return 2^3-5*4'
|
||||
|
||||
dotest 'return 0.0'
|
||||
dotest 'return 0'
|
||||
dotest 'return -0//1'
|
||||
dotest 'return 3^-1'
|
||||
dotest 'return (1 + 1)^(50 + 50)'
|
||||
dotest 'return (-2)^(31 - 2)'
|
||||
dotest 'return (-3^0 + 5) // 3.0'
|
||||
dotest 'return -3 % 5'
|
||||
dotest 'return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3'
|
||||
dotest 'return -((2^8 + -(-1)) % 8)//2 * 4 - 3'
|
||||
dotest 'return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD'
|
||||
dotest 'return ~(~0xFF0 | 0xFF0)'
|
||||
dotest 'return ~~-100024.0'
|
||||
dotest 'return ((100 << 6) << -4) >> 2'
|
||||
|
||||
dotest 'return 2^3^2 == 2^(3^2)'
|
||||
dotest 'return 2^3*4 == (2^3)*4'
|
||||
dotest 'return 2.0^-2 == 1/4 and -2^- -2 == - - -4'
|
||||
dotest 'return not nil and 2 and not(2>3 or 3<2)'
|
||||
dotest 'return -3-1-5 == 0+0-9'
|
||||
dotest 'return -2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0'
|
||||
dotest 'return -3%5 == 2 and -3+5 == 2'
|
||||
dotest 'return 2*1+3/3 == 3 and 1+2 .. 3*1 == "33"'
|
||||
dotest 'return not(2+1 > 3*1) and "a".."b" > "a"'
|
||||
|
||||
dotest 'return "7" .. 3 << 1 == 146'
|
||||
dotest 'return 10 >> 1 .. "9" == 0'
|
||||
dotest 'return 10 | 1 .. "9" == 27'
|
||||
|
||||
dotest 'return 0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4'
|
||||
dotest 'return 0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4'
|
||||
dotest 'return 0xF0 & 0x0F + 1 == 0x10'
|
||||
|
||||
dotest 'return 3^4//2^3//5 == 2'
|
||||
|
||||
dotest 'return -3+4*5//2^3^2//9+4%10/3 == (-3)+(((4*5)//(2^(3^2)))//9)+((4%10)/3)'
|
||||
|
||||
dotest 'return not ((true or false) and nil)'
|
||||
dotest 'return true or false and nil'
|
||||
|
||||
-- old bug
|
||||
dotest 'return (((1 or false) and true) or false) == true'
|
||||
dotest 'return (((nil and true) or false) and true) == false'
|
||||
|
||||
dotest 'return -(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75'
|
||||
dotest 'return (b or a)+1 == 2 and (10 or a)+1 == 11'
|
||||
dotest 'return ((2<3) or 1) == true and (2<3 and 4) == 4'
|
||||
|
||||
dotest 'return (x>y) and x or y == 2'
|
||||
dotest 'return (x>y) and x or y == 2'
|
||||
|
||||
dotest 'function x() for i = 1, 10 do; print(i); end end'
|
||||
|
||||
dotest 'function x() local a=1; function y() return function() return a end end; end'
|
||||
|
||||
dotest 'return @integer 1'
|
||||
dotest 'return @string "hello"'
|
||||
dotest 'return @table {}'
|
||||
dotest 'return @integer[] {}'
|
||||
dotest 'return @number[] {}'
|
||||
dotest 'return @closure function() end'
|
||||
dotest 'return @number 54.4'
|
||||
dotest 'return @User.Type a'
|
||||
|
||||
dotest 'for i=1,10 do print(i+1) end return'
|
||||
dotest 'for i=1.0, 10.0 do print(i+4.2) end return'
|
||||
|
||||
dotest 'return {1,2,3}'
|
||||
|
||||
dotest 'local a: integer return {1+a}'
|
||||
dotest 'return {[1] = a}'
|
@ -1,954 +0,0 @@
|
||||
function()
|
||||
return
|
||||
function()
|
||||
--locals a, y, a, z
|
||||
local
|
||||
--[symbols]
|
||||
a --local symbol ?
|
||||
--[expressions]
|
||||
1
|
||||
local
|
||||
--[symbols]
|
||||
y --local symbol function
|
||||
--[expressions]
|
||||
function()
|
||||
--upvalues a
|
||||
return
|
||||
function()
|
||||
--upvalues a
|
||||
return
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --upvalue ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
end
|
||||
local
|
||||
--[symbols]
|
||||
a --local symbol ?
|
||||
--[expressions]
|
||||
5
|
||||
local
|
||||
--[symbols]
|
||||
z --local symbol function
|
||||
--[expressions]
|
||||
function()
|
||||
--upvalues a
|
||||
return
|
||||
function()
|
||||
--upvalues a
|
||||
return
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --upvalue ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
end
|
||||
return
|
||||
--[suffixed expr start] closure
|
||||
--[primary start] closure
|
||||
y --local symbol function
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
,
|
||||
--[suffixed expr start] closure
|
||||
--[primary start] closure
|
||||
z --local symbol function
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
function(
|
||||
a --local symbol ?
|
||||
,
|
||||
b --local symbol ?
|
||||
,
|
||||
c --local symbol ?
|
||||
,
|
||||
d --local symbol ?
|
||||
,
|
||||
e --local symbol ?
|
||||
)
|
||||
--locals a, b, c, d, e
|
||||
if
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
==
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
b --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[binary expr end]
|
||||
then
|
||||
goto l1
|
||||
elseif
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
==
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
c --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[binary expr end]
|
||||
then
|
||||
goto l2
|
||||
elseif
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
==
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
d --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[binary expr end]
|
||||
then
|
||||
goto l2
|
||||
else
|
||||
if
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
==
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
e --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[binary expr end]
|
||||
then
|
||||
goto l3
|
||||
else
|
||||
goto l3
|
||||
end
|
||||
end
|
||||
::l1::
|
||||
::l2::
|
||||
::l3::
|
||||
::l4::
|
||||
end
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
function(
|
||||
a --local symbol ?
|
||||
)
|
||||
--locals a
|
||||
while
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
<
|
||||
10
|
||||
--[binary expr end]
|
||||
do
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
+
|
||||
1
|
||||
--[binary expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
function(
|
||||
a --local symbol ?
|
||||
)
|
||||
--locals a
|
||||
::L2::
|
||||
if
|
||||
--[unary expr start] any
|
||||
not
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
<
|
||||
10
|
||||
--[binary expr end]
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
then
|
||||
goto L1
|
||||
end
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
a --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
+
|
||||
1
|
||||
--[binary expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
goto L2
|
||||
::L1::
|
||||
end
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
function()
|
||||
--[expression statement start]
|
||||
--[expression list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] closure
|
||||
function()
|
||||
end
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[function call start] any
|
||||
(
|
||||
{ --[table constructor start] table
|
||||
--[indexed assign start] any
|
||||
--[value start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
f --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[function call start] any
|
||||
(
|
||||
)
|
||||
--[function call end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[value end]
|
||||
--[indexed assign end]
|
||||
} --[table constructor end]
|
||||
)
|
||||
--[function call end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
end
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
function()
|
||||
--locals sum, j, k
|
||||
local
|
||||
--[symbols]
|
||||
sum --local symbol ?
|
||||
for
|
||||
j --local symbol integer
|
||||
=
|
||||
1
|
||||
,
|
||||
500
|
||||
do
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
sum --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
0.0000000000000000
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
for
|
||||
k --local symbol integer
|
||||
=
|
||||
1
|
||||
,
|
||||
10000
|
||||
do
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
sum --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
--[binary expr start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
sum --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
+
|
||||
--[binary expr start] number
|
||||
1.0000000000000000
|
||||
/
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
--[binary expr start] integer
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
k --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
*
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
k --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[binary expr end]
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[binary expr end]
|
||||
--[binary expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
end
|
||||
end
|
||||
return
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
sum --local symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
end
|
||||
|
||||
function()
|
||||
--locals a
|
||||
local
|
||||
--[symbols]
|
||||
a --local symbol integer
|
||||
return
|
||||
--[binary expr start] integer
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
a --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
+
|
||||
3
|
||||
--[binary expr end]
|
||||
end
|
||||
|
||||
function()
|
||||
--locals i
|
||||
local
|
||||
--[symbols]
|
||||
i --local symbol integer
|
||||
return
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
t --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] any
|
||||
[
|
||||
--[binary expr start] number
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
i --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
/
|
||||
5
|
||||
--[binary expr end]
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
|
||||
function()
|
||||
--locals t
|
||||
local
|
||||
--[symbols]
|
||||
t --local symbol integer[]
|
||||
return
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer[]
|
||||
t --local symbol integer[]
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] integer
|
||||
[
|
||||
0
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
f --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[function call start] any
|
||||
(
|
||||
)
|
||||
--[function call end]
|
||||
--[Y index start] any
|
||||
[
|
||||
1
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
x --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[field selector start] any
|
||||
.
|
||||
'y'
|
||||
--[field selector end]
|
||||
--[Y index start] any
|
||||
[
|
||||
1
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
|
||||
function()
|
||||
--locals t
|
||||
local
|
||||
--[symbols]
|
||||
t --local symbol integer[]
|
||||
if
|
||||
--[suffixed expr start] boolean
|
||||
--[primary start] boolean
|
||||
--[binary expr start] boolean
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer[]
|
||||
t --local symbol integer[]
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] integer
|
||||
[
|
||||
1
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
==
|
||||
5
|
||||
--[binary expr end]
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
then
|
||||
return
|
||||
true
|
||||
end
|
||||
return
|
||||
false
|
||||
end
|
||||
|
||||
function()
|
||||
--locals t, len
|
||||
local
|
||||
--[symbols]
|
||||
t --local symbol table
|
||||
local
|
||||
--[symbols]
|
||||
len --local symbol integer
|
||||
--[expressions]
|
||||
--[unary expr start] integer
|
||||
@integer
|
||||
--[unary expr start] any
|
||||
#
|
||||
--[suffixed expr start] table
|
||||
--[primary start] table
|
||||
t --local symbol table
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
--[unary expr end]
|
||||
return
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
len --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
|
||||
function()
|
||||
return
|
||||
function(
|
||||
t --local symbol table
|
||||
,
|
||||
i --local symbol integer
|
||||
)
|
||||
--locals t, i
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
i --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
--[unary expr start] integer
|
||||
@integer
|
||||
--[unary expr start] any
|
||||
#
|
||||
--[suffixed expr start] table
|
||||
--[primary start] table
|
||||
t --local symbol table
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
--[unary expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
end
|
||||
end
|
||||
|
||||
function()
|
||||
matmul --global symbol ?
|
||||
=
|
||||
function(
|
||||
a --local symbol table
|
||||
,
|
||||
b --local symbol table
|
||||
)
|
||||
--locals a, b, m, n, p, x, c, i, xi, j, sum, ai, cj, k
|
||||
--[expression statement start]
|
||||
--[expression list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
assert --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[function call start] any
|
||||
(
|
||||
--[binary expr start] any
|
||||
--[unary expr start] integer
|
||||
@integer
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
--[unary expr start] any
|
||||
#
|
||||
--[suffixed expr start] any
|
||||
--[primary start] table
|
||||
a --local symbol table
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] any
|
||||
[
|
||||
1
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
==
|
||||
--[unary expr start] any
|
||||
#
|
||||
--[suffixed expr start] table
|
||||
--[primary start] table
|
||||
b --local symbol table
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
--[binary expr end]
|
||||
)
|
||||
--[function call end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
local
|
||||
--[symbols]
|
||||
m --local symbol integer
|
||||
,
|
||||
n --local symbol integer
|
||||
,
|
||||
p --local symbol integer
|
||||
,
|
||||
x --local symbol table
|
||||
--[expressions]
|
||||
--[unary expr start] integer
|
||||
@integer
|
||||
--[unary expr start] any
|
||||
#
|
||||
--[suffixed expr start] table
|
||||
--[primary start] table
|
||||
a --local symbol table
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
--[unary expr end]
|
||||
,
|
||||
--[unary expr start] integer
|
||||
@integer
|
||||
--[unary expr start] any
|
||||
#
|
||||
--[suffixed expr start] any
|
||||
--[primary start] table
|
||||
a --local symbol table
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] any
|
||||
[
|
||||
1
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
--[unary expr end]
|
||||
,
|
||||
--[unary expr start] integer
|
||||
@integer
|
||||
--[unary expr start] any
|
||||
#
|
||||
--[suffixed expr start] any
|
||||
--[primary start] table
|
||||
b --local symbol table
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] any
|
||||
[
|
||||
1
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
--[unary expr end]
|
||||
,
|
||||
{ --[table constructor start] table
|
||||
} --[table constructor end]
|
||||
local
|
||||
--[symbols]
|
||||
c --local symbol table
|
||||
--[expressions]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
matrix --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[field selector start] any
|
||||
.
|
||||
'T'
|
||||
--[field selector end]
|
||||
--[function call start] any
|
||||
(
|
||||
--[suffixed expr start] table
|
||||
--[primary start] table
|
||||
b --local symbol table
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
)
|
||||
--[function call end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
for
|
||||
i --local symbol integer
|
||||
=
|
||||
1
|
||||
,
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
m --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
do
|
||||
local
|
||||
--[symbols]
|
||||
xi --local symbol number[]
|
||||
--[expressions]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
table --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[field selector start] any
|
||||
.
|
||||
'numarray'
|
||||
--[field selector end]
|
||||
--[function call start] any
|
||||
(
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
p --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
,
|
||||
0.0000000000000000
|
||||
)
|
||||
--[function call end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] table
|
||||
x --local symbol table
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] any
|
||||
[
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
i --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
--[suffixed expr start] number[]
|
||||
--[primary start] number[]
|
||||
xi --local symbol number[]
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
for
|
||||
j --local symbol integer
|
||||
=
|
||||
1
|
||||
,
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
p --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
do
|
||||
local
|
||||
--[symbols]
|
||||
sum --local symbol number
|
||||
,
|
||||
ai --local symbol number[]
|
||||
,
|
||||
cj --local symbol number[]
|
||||
--[expressions]
|
||||
0.0000000000000000
|
||||
,
|
||||
--[unary expr start] number[]
|
||||
@number[]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] table
|
||||
a --local symbol table
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] any
|
||||
[
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
i --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
,
|
||||
--[unary expr start] number[]
|
||||
@number[]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
--[suffixed expr start] any
|
||||
--[primary start] table
|
||||
c --local symbol table
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] any
|
||||
[
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
j --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[unary expr end]
|
||||
for
|
||||
k --local symbol integer
|
||||
=
|
||||
1
|
||||
,
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
n --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
do
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] number
|
||||
--[primary start] number
|
||||
sum --local symbol number
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
--[binary expr start] number
|
||||
--[suffixed expr start] number
|
||||
--[primary start] number
|
||||
sum --local symbol number
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
+
|
||||
--[binary expr start] number
|
||||
--[suffixed expr start] number
|
||||
--[primary start] number[]
|
||||
ai --local symbol number[]
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] number
|
||||
[
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
k --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
*
|
||||
--[suffixed expr start] number
|
||||
--[primary start] number[]
|
||||
cj --local symbol number[]
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] number
|
||||
[
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
k --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[binary expr end]
|
||||
--[binary expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
end
|
||||
--[expression statement start]
|
||||
--[var list start]
|
||||
--[suffixed expr start] number
|
||||
--[primary start] number[]
|
||||
xi --local symbol number[]
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[Y index start] number
|
||||
[
|
||||
--[suffixed expr start] integer
|
||||
--[primary start] integer
|
||||
j --local symbol integer
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
]
|
||||
--[Y index end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
= --[var list end]
|
||||
--[expression list start]
|
||||
--[suffixed expr start] number
|
||||
--[primary start] number
|
||||
sum --local symbol number
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
end
|
||||
end
|
||||
return
|
||||
--[suffixed expr start] table
|
||||
--[primary start] table
|
||||
x --local symbol table
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
return
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
matmul --global symbol ?
|
||||
--[primary end]
|
||||
--[suffixed expr end]
|
||||
end
|
||||
|
@ -1,145 +0,0 @@
|
||||
local function doast(str)
|
||||
local x, msg = ast.parse(str)
|
||||
if not x then error(msg) end
|
||||
print(x:tostring())
|
||||
end
|
||||
|
||||
local str =
|
||||
[[return function()
|
||||
local a = 1
|
||||
|
||||
local function y()
|
||||
return function()
|
||||
return a
|
||||
end
|
||||
end
|
||||
|
||||
local a = 5
|
||||
|
||||
local function z()
|
||||
return function()
|
||||
return a
|
||||
end
|
||||
end
|
||||
|
||||
return y, z
|
||||
end
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str =
|
||||
[[return function (a, b, c, d, e)
|
||||
if a == b then goto l1
|
||||
elseif a == c then goto l2
|
||||
elseif a == d then goto l2
|
||||
else if a == e then goto l3
|
||||
else goto l3
|
||||
end
|
||||
end
|
||||
::l1:: ::l2:: ::l3:: ::l4::
|
||||
end
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str =
|
||||
[[return function (a) while a < 10 do a = a + 1 end end
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
-- Note that the while loop above is supposed to ultimately
|
||||
-- generate same code as below
|
||||
str=
|
||||
[[return function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1;
|
||||
goto L2; ::L1:: end
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[return function ()
|
||||
(function () end){f()}
|
||||
end
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[return function ()
|
||||
local sum
|
||||
for j = 1,500 do
|
||||
sum = 0.0
|
||||
for k = 1,10000 do
|
||||
sum = sum + 1.0/(k*k)
|
||||
end
|
||||
end
|
||||
return sum
|
||||
end
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[local a: integer return a+3
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[local i: integer; return t[i/5]
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[local t: integer[]; return t[0]
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[return f()[1]
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[return x.y[1]
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[local t: integer[]
|
||||
if (t[1] == 5) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[local t: table
|
||||
local len: integer = #t
|
||||
return len
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[return function(t: table, i: integer)
|
||||
i = #t
|
||||
end
|
||||
]]
|
||||
doast(str)
|
||||
|
||||
str=
|
||||
[[function matmul(a: table, b: table)
|
||||
assert(@integer(#a[1]) == #b);
|
||||
local m: integer, n: integer, p: integer, x: table = #a, #a[1], #b[1], {};
|
||||
local c: table = matrix.T(b); -- transpose for efficiency
|
||||
for i = 1, m do
|
||||
local xi: number[] = table.numarray(p, 0.0)
|
||||
x[i] = xi
|
||||
for j = 1, p do
|
||||
local sum: number, ai: number[], cj: number[] = 0.0, @number[](a[i]), @number[](c[j]);
|
||||
-- for luajit, caching c[j] or not makes no difference; lua is not so clever
|
||||
for k = 1, n do sum = sum + ai[k] * cj[k] end
|
||||
xi[j] = sum;
|
||||
end
|
||||
end
|
||||
return x
|
||||
end
|
||||
return matmul
|
||||
]]
|
||||
doast(str)
|
@ -1,94 +0,0 @@
|
||||
New Parser and Code Generator for Ravi
|
||||
======================================
|
||||
|
||||
Status
|
||||
------
|
||||
The basic parser and type checker have been implemented. However the ``defer`` statement is not yet done.
|
||||
Progress is very slow but things are moving every now and then when I get time.
|
||||
|
||||
Usage
|
||||
-----
|
||||
The parse tree can be generated as follows::
|
||||
|
||||
tree, errmessage = ast.parse 'some lua code'
|
||||
if not tree then
|
||||
print(errmessage)
|
||||
else
|
||||
print(tree:tostring())
|
||||
end
|
||||
|
||||
Examples::
|
||||
|
||||
tree, errmessage = ast.parse 'print "hello"'
|
||||
if not tree then
|
||||
print(errmessage)
|
||||
else
|
||||
print(tree:tostring())
|
||||
end
|
||||
|
||||
This generates output::
|
||||
|
||||
function()
|
||||
--[expression statement start]
|
||||
--[expression list start]
|
||||
--[suffixed expr start] any
|
||||
--[primary start] any
|
||||
print --global symbol ?
|
||||
--[primary end]
|
||||
--[suffix list start]
|
||||
--[function call start] any
|
||||
(
|
||||
'hello'
|
||||
)
|
||||
--[function call end]
|
||||
--[suffix list end]
|
||||
--[suffixed expr end]
|
||||
--[expression list end]
|
||||
--[expression statement end]
|
||||
end
|
||||
|
||||
For more examples please see:
|
||||
|
||||
* `ravi-tests/ravi_test_ast.lua <https://github.com/dibyendumajumdar/ravi/blob/master/ravi-tests/ravi_test_ast.lua>`_
|
||||
* `ravi-tests/ravi_test_ast2.lua <https://github.com/dibyendumajumdar/ravi/blob/master/ravi-tests/ravi_test_ast2.lua>`_.
|
||||
|
||||
If you run these scripts the parse AST will be dumped to stdout.
|
||||
|
||||
Design Notes
|
||||
------------
|
||||
|
||||
These are some design notes on the new parser / code generator.
|
||||
|
||||
There will be several phases:
|
||||
|
||||
1. Convert input into syntax tree - this will look very much like the input source, i.e. there will be fornum loops, if statements,
|
||||
while and repeat loops etc. During this phase only the types for literals and local decalarations will be known. MOSTLY DONE.
|
||||
2. The next phase will be a type checking phase. In this phase types will be derive for expressions, and also type assertions will be
|
||||
added where required such as unpon function entry, and after function calls. But the overall syntax tree will still resemble the input
|
||||
source except for the additional instructions. MOSTLY DONE.
|
||||
3. Third phase will be to assign virtual registers; first to locals, and then to temporaries. For simplicity I will probably keep the
|
||||
temporaries and locals in separate ranges.
|
||||
4. Next phase will be linearize the instructions - during this phase the loops, if statements etc will get translated to equivalent of
|
||||
conditional and unconditional jumps. We will probably create intermediate structures that can easily map to Ravi bytecodes.
|
||||
5. In the first phase we will stop here, generate byte code and finish.
|
||||
6. The next phase will be translate into basic blocks.
|
||||
7. Following that we will construct a CFG, perform dominator analysis and convert to SSA form.
|
||||
8. Hopefully as a result of above we can do some simple optimizations and then emit the bytecode at the end.
|
||||
|
||||
Some other things
|
||||
-----------------
|
||||
1. Locals that are used as up-values or passed or overwritten by function calls should be marked as having 'escaped'.
|
||||
Having this knowledge will enable backend JIT to use the stack for values that cannot escape.
|
||||
2. During code generation it will be good to know which registers are type constant - i.e. their types do not change. register allocation
|
||||
should be designed / implemented so that we try to avoid over-writing type data where possible. This will allow backend JIT
|
||||
to generate more optimized code.
|
||||
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
The new Ravi Parser and Code Generator implementation is in:
|
||||
|
||||
* `ravi_ast_parse.c <https://github.com/dibyendumajumdar/ravi/blob/master/src/ravi_ast_parse.c>`_ - contains the parser that builds AST
|
||||
* `ravi_ast_print.c <https://github.com/dibyendumajumdar/ravi/blob/master/src/ravi_ast_print.c>`_ - contains utilities for printing out the AST
|
||||
* `ravi_ast_typecheck.c <https://github.com/dibyendumajumdar/ravi/blob/master/src/ravi_ast_typecheck.c>`_ - contains the type checking phase of the parser
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,520 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2018-2020 Dibyendu Majumdar
|
||||
*/
|
||||
|
||||
#include <ravi_ast.h>
|
||||
#include "ravi_ast.h"
|
||||
|
||||
static const char *type_name(ravitype_t tt) {
|
||||
switch (tt) {
|
||||
case RAVI_TANY:
|
||||
return "any";
|
||||
case RAVI_TNIL:
|
||||
return "nil";
|
||||
case RAVI_TBOOLEAN:
|
||||
return "boolean";
|
||||
case RAVI_TNUMFLT:
|
||||
return "number";
|
||||
case RAVI_TNUMINT:
|
||||
return "integer";
|
||||
case RAVI_TTABLE:
|
||||
return "table";
|
||||
case RAVI_TSTRING:
|
||||
return "string";
|
||||
case RAVI_TARRAYINT:
|
||||
return "integer[]";
|
||||
case RAVI_TARRAYFLT:
|
||||
return "number[]";
|
||||
case RAVI_TFUNCTION:
|
||||
return "closure";
|
||||
case RAVI_TUSERDATA:
|
||||
return "";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static void printf_buf(membuff_t *buf, const char *format, ...) {
|
||||
static const char *PADDING = " ";
|
||||
char tbuf[128] = {0};
|
||||
va_list ap;
|
||||
const char *cp;
|
||||
va_start(ap, format);
|
||||
for (cp = format; *cp; cp++) {
|
||||
if (cp[0] == '%' && cp[1] == 'p') { /* padding */
|
||||
int level = va_arg(ap, int);
|
||||
snprintf(tbuf, sizeof tbuf, "%.*s", level, PADDING);
|
||||
membuff_add_string(buf, tbuf);
|
||||
cp++;
|
||||
}
|
||||
else if (cp[0] == '%' && cp[1] == 't') { /* TString */
|
||||
const TString *ts;
|
||||
ts = va_arg(ap, const TString *);
|
||||
const char *s = getstr(ts);
|
||||
membuff_add_string(buf, s);
|
||||
cp++;
|
||||
}
|
||||
else if (cp[0] == '%' && cp[1] == 'T') { /* struct var_type */
|
||||
const struct var_type *type;
|
||||
type = va_arg(ap, const struct var_type *);
|
||||
if (type->type_code == RAVI_TUSERDATA) {
|
||||
const char *s = getstr(type->type_name);
|
||||
membuff_add_string(buf, s);
|
||||
}
|
||||
else {
|
||||
membuff_add_string(buf, type_name(type->type_code));
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
else if (cp[0] == '%' && cp[1] == 's') { /* const char * */
|
||||
const char *s;
|
||||
s = va_arg(ap, const char *);
|
||||
membuff_add_string(buf, s);
|
||||
cp++;
|
||||
}
|
||||
else if (cp[0] == '%' && cp[1] == 'c') { /* comment */
|
||||
const char *s;
|
||||
s = va_arg(ap, const char *);
|
||||
membuff_add_fstring(buf, "--%s", s);
|
||||
cp++;
|
||||
}
|
||||
else if (cp[0] == '%' && cp[1] == 'i') { /* integer */
|
||||
lua_Integer i;
|
||||
i = va_arg(ap, lua_Integer);
|
||||
membuff_add_longlong(buf, i);
|
||||
cp++;
|
||||
}
|
||||
else if (cp[0] == '%' && cp[1] == 'f') { /* float */
|
||||
double d;
|
||||
d = va_arg(ap, double);
|
||||
membuff_add_fstring(buf, "%.16f", d);
|
||||
cp++;
|
||||
}
|
||||
else if (cp[0] == '%' && cp[1] == 'b') { /* boolean */
|
||||
lua_Integer i;
|
||||
i = va_arg(ap, lua_Integer);
|
||||
membuff_add_bool(buf, i != 0);
|
||||
cp++;
|
||||
}
|
||||
else {
|
||||
membuff_add_char(buf, *cp);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
static void print_ast_node_list(membuff_t *buf, struct ast_node_list *list, int level, const char *delimiter) {
|
||||
struct ast_node *node;
|
||||
bool is_first = true;
|
||||
FOR_EACH_PTR(list, node) {
|
||||
if (is_first)
|
||||
is_first = false;
|
||||
else if (delimiter)
|
||||
printf_buf(buf, "%p%s\n", level, delimiter);
|
||||
raviA_print_ast_node(buf, node, level + 1);
|
||||
}
|
||||
END_FOR_EACH_PTR(node);
|
||||
}
|
||||
|
||||
static void print_statement_list(membuff_t *buf, struct ast_node_list *statement_list, int level) {
|
||||
print_ast_node_list(buf, statement_list, level + 1, NULL);
|
||||
}
|
||||
|
||||
static inline const char *get_as_str(const TString *ts) { return ts ? getstr(ts) : ""; }
|
||||
|
||||
static void print_symbol(membuff_t *buf, struct lua_symbol *sym, int level) {
|
||||
switch (sym->symbol_type) {
|
||||
case SYM_GLOBAL: {
|
||||
printf_buf(buf, "%p%t %c %s %s\n", level, sym->var.var_name, "global symbol",
|
||||
raviY_typename(sym->value_type.type_code), get_as_str(sym->value_type.type_name));
|
||||
break;
|
||||
}
|
||||
case SYM_LOCAL: {
|
||||
printf_buf(buf, "%p%t %c %s %s\n", level, sym->var.var_name, "local symbol",
|
||||
raviY_typename(sym->value_type.type_code), get_as_str(sym->value_type.type_name));
|
||||
break;
|
||||
}
|
||||
case SYM_UPVALUE: {
|
||||
printf_buf(buf, "%p%t %c %s %s\n", level, sym->upvalue.var->var.var_name, "upvalue",
|
||||
raviY_typename(sym->upvalue.var->value_type.type_code),
|
||||
get_as_str(sym->upvalue.var->value_type.type_name));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_symbol_name(membuff_t *buf, struct lua_symbol *sym) {
|
||||
switch (sym->symbol_type) {
|
||||
case SYM_LOCAL:
|
||||
case SYM_GLOBAL: {
|
||||
printf_buf(buf, "%t", sym->var.var_name);
|
||||
break;
|
||||
}
|
||||
case SYM_UPVALUE: {
|
||||
printf_buf(buf, "%t", sym->upvalue.var->var.var_name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_symbol_list(membuff_t *buf, struct lua_symbol_list *list, int level, const char *delimiter) {
|
||||
struct lua_symbol *node;
|
||||
bool is_first = true;
|
||||
FOR_EACH_PTR(list, node) {
|
||||
if (is_first)
|
||||
is_first = false;
|
||||
else if (delimiter)
|
||||
printf_buf(buf, "%p%s\n", level, delimiter);
|
||||
print_symbol(buf, node, level + 1);
|
||||
}
|
||||
END_FOR_EACH_PTR(node);
|
||||
}
|
||||
|
||||
static void print_symbol_names(membuff_t *buf, struct lua_symbol_list *list) {
|
||||
struct lua_symbol *node;
|
||||
bool is_first = true;
|
||||
FOR_EACH_PTR(list, node) {
|
||||
if (is_first)
|
||||
is_first = false;
|
||||
else
|
||||
printf_buf(buf, ", ");
|
||||
print_symbol_name(buf, node);
|
||||
}
|
||||
END_FOR_EACH_PTR(node);
|
||||
}
|
||||
|
||||
static const char *get_unary_opr_str(UnOpr op) {
|
||||
switch (op) {
|
||||
case OPR_NOT:
|
||||
return "not";
|
||||
case OPR_MINUS:
|
||||
return "-";
|
||||
case OPR_BNOT:
|
||||
return "~";
|
||||
case OPR_LEN:
|
||||
return "#";
|
||||
case OPR_TO_INTEGER:
|
||||
return "@integer";
|
||||
case OPR_TO_NUMBER:
|
||||
return "@number";
|
||||
case OPR_TO_INTARRAY:
|
||||
return "@integer[]";
|
||||
case OPR_TO_NUMARRAY:
|
||||
return "@number[]";
|
||||
case OPR_TO_TABLE:
|
||||
return "@table";
|
||||
case OPR_TO_CLOSURE:
|
||||
return "@closure";
|
||||
case OPR_TO_STRING:
|
||||
return "@string";
|
||||
case OPR_TO_TYPE:
|
||||
return "@<usertype>";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_binary_opr_str(BinOpr op) {
|
||||
switch (op) {
|
||||
case OPR_ADD:
|
||||
return "+";
|
||||
case OPR_SUB:
|
||||
return "-";
|
||||
case OPR_MUL:
|
||||
return "*";
|
||||
case OPR_MOD:
|
||||
return "%";
|
||||
case OPR_POW:
|
||||
return "^";
|
||||
case OPR_DIV:
|
||||
return "/";
|
||||
case OPR_IDIV:
|
||||
return "//";
|
||||
case OPR_BAND:
|
||||
return "&";
|
||||
case OPR_BOR:
|
||||
return "|";
|
||||
case OPR_BXOR:
|
||||
return "~";
|
||||
case OPR_SHL:
|
||||
return "<<";
|
||||
case OPR_SHR:
|
||||
return ">>";
|
||||
case OPR_CONCAT:
|
||||
return "..";
|
||||
case OPR_NE:
|
||||
return "~=";
|
||||
case OPR_EQ:
|
||||
return "==";
|
||||
case OPR_LT:
|
||||
return "<";
|
||||
case OPR_LE:
|
||||
return "<=";
|
||||
case OPR_GT:
|
||||
return ">";
|
||||
case OPR_GE:
|
||||
return ">=";
|
||||
case OPR_AND:
|
||||
return "and";
|
||||
case OPR_OR:
|
||||
return "or";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void raviA_print_ast_node(membuff_t *buf, struct ast_node *node, int level) {
|
||||
switch (node->type) {
|
||||
case AST_FUNCTION_EXPR: {
|
||||
if (node->function_expr.args) {
|
||||
printf_buf(buf, "%pfunction(\n", level);
|
||||
print_symbol_list(buf, node->function_expr.args, level + 1, ",");
|
||||
printf_buf(buf, "%p)\n", level);
|
||||
}
|
||||
else {
|
||||
printf_buf(buf, "%pfunction()\n", level);
|
||||
}
|
||||
if (node->function_expr.locals) {
|
||||
printf_buf(buf, "%p%c ", level, "locals ");
|
||||
print_symbol_names(buf, node->function_expr.locals);
|
||||
printf_buf(buf, "\n");
|
||||
}
|
||||
if (node->function_expr.upvalues) {
|
||||
printf_buf(buf, "%p%c ", level, "upvalues ");
|
||||
print_symbol_names(buf, node->function_expr.upvalues);
|
||||
printf_buf(buf, "\n");
|
||||
}
|
||||
print_statement_list(buf, node->function_expr.function_statement_list, level);
|
||||
printf_buf(buf, "%pend\n", level);
|
||||
break;
|
||||
}
|
||||
case AST_NONE:
|
||||
break;
|
||||
case AST_RETURN_STMT: {
|
||||
printf_buf(buf, "%preturn\n", level);
|
||||
print_ast_node_list(buf, node->return_stmt.expr_list, level + 1, ",");
|
||||
break;
|
||||
}
|
||||
case AST_LOCAL_STMT: {
|
||||
printf_buf(buf, "%plocal\n", level);
|
||||
printf_buf(buf, "%p%c\n", level, "[symbols]");
|
||||
print_symbol_list(buf, node->local_stmt.var_list, level + 1, ",");
|
||||
if (node->local_stmt.expr_list) {
|
||||
printf_buf(buf, "%p%c\n", level, "[expressions]");
|
||||
print_ast_node_list(buf, node->local_stmt.expr_list, level + 1, ",");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AST_FUNCTION_STMT: {
|
||||
raviA_print_ast_node(buf, node->function_stmt.name, level);
|
||||
if (node->function_stmt.selectors) {
|
||||
printf_buf(buf, "%p%c\n", level + 1, "[selectors]");
|
||||
print_ast_node_list(buf, node->function_stmt.selectors, level + 2, NULL);
|
||||
}
|
||||
if (node->function_stmt.method_name) {
|
||||
printf_buf(buf, "%p%c\n", level + 1, "[method name]");
|
||||
raviA_print_ast_node(buf, node->function_stmt.method_name, level + 2);
|
||||
}
|
||||
printf_buf(buf, "%p=\n", level + 1);
|
||||
raviA_print_ast_node(buf, node->function_stmt.function_expr, level + 2);
|
||||
break;
|
||||
}
|
||||
case AST_LABEL_STMT: {
|
||||
printf_buf(buf, "%p::%t::\n", level, node->label_stmt.symbol->label.label_name);
|
||||
break;
|
||||
}
|
||||
case AST_GOTO_STMT: {
|
||||
printf_buf(buf, "%pgoto %t\n", level, node->goto_stmt.name);
|
||||
break;
|
||||
}
|
||||
case AST_DO_STMT: {
|
||||
printf_buf(buf, "%pdo\n", level);
|
||||
print_ast_node_list(buf, node->do_stmt.do_statement_list, level + 1, NULL);
|
||||
printf_buf(buf, "%pend\n", level);
|
||||
break;
|
||||
}
|
||||
case AST_EXPR_STMT: {
|
||||
printf_buf(buf, "%p%c\n", level, "[expression statement start]");
|
||||
if (node->expression_stmt.var_expr_list) {
|
||||
printf_buf(buf, "%p%c\n", level + 1, "[var list start]");
|
||||
print_ast_node_list(buf, node->expression_stmt.var_expr_list, level + 2, ",");
|
||||
printf_buf(buf, "%p= %c\n", level + 1, "[var list end]");
|
||||
}
|
||||
printf_buf(buf, "%p%c\n", level + 1, "[expression list start]");
|
||||
print_ast_node_list(buf, node->expression_stmt.expr_list, level + 2, ",");
|
||||
printf_buf(buf, "%p%c\n", level + 1, "[expression list end]");
|
||||
printf_buf(buf, "%p%c\n", level, "[expression statement end]");
|
||||
break;
|
||||
}
|
||||
case AST_IF_STMT: {
|
||||
struct ast_node *test_then_block;
|
||||
bool is_first = true;
|
||||
FOR_EACH_PTR(node->if_stmt.if_condition_list, test_then_block) {
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
printf_buf(buf, "%pif\n", level);
|
||||
}
|
||||
else
|
||||
printf_buf(buf, "%pelseif\n", level);
|
||||
raviA_print_ast_node(buf, test_then_block->test_then_block.condition, level + 1);
|
||||
printf_buf(buf, "%pthen\n", level);
|
||||
print_ast_node_list(buf, test_then_block->test_then_block.test_then_statement_list, level + 1, NULL);
|
||||
}
|
||||
END_FOR_EACH_PTR(node);
|
||||
if (node->if_stmt.else_block) {
|
||||
printf_buf(buf, "%pelse\n", level);
|
||||
print_ast_node_list(buf, node->if_stmt.else_statement_list, level + 1, NULL);
|
||||
}
|
||||
printf_buf(buf, "%pend\n", level);
|
||||
break;
|
||||
}
|
||||
case AST_WHILE_STMT: {
|
||||
printf_buf(buf, "%pwhile\n", level);
|
||||
raviA_print_ast_node(buf, node->while_or_repeat_stmt.condition, level + 1);
|
||||
printf_buf(buf, "%pdo\n", level);
|
||||
print_ast_node_list(buf, node->while_or_repeat_stmt.loop_statement_list, level + 1, NULL);
|
||||
printf_buf(buf, "%pend\n", level);
|
||||
break;
|
||||
}
|
||||
case AST_REPEAT_STMT: {
|
||||
printf_buf(buf, "%prepeat\n", level);
|
||||
print_ast_node_list(buf, node->while_or_repeat_stmt.loop_statement_list, level + 1, NULL);
|
||||
printf_buf(buf, "%puntil\n", level);
|
||||
raviA_print_ast_node(buf, node->while_or_repeat_stmt.condition, level + 1);
|
||||
printf_buf(buf, "%p%c\n", level, "[repeat end]");
|
||||
break;
|
||||
}
|
||||
case AST_FORIN_STMT: {
|
||||
printf_buf(buf, "%pfor\n", level);
|
||||
print_symbol_list(buf, node->for_stmt.symbols, level + 1, ",");
|
||||
printf_buf(buf, "%pin\n", level);
|
||||
print_ast_node_list(buf, node->for_stmt.expr_list, level + 1, ",");
|
||||
printf_buf(buf, "%pdo\n", level);
|
||||
print_statement_list(buf, node->for_stmt.for_statement_list, level + 1);
|
||||
printf_buf(buf, "%pend\n", level);
|
||||
break;
|
||||
}
|
||||
case AST_FORNUM_STMT: {
|
||||
printf_buf(buf, "%pfor\n", level);
|
||||
print_symbol_list(buf, node->for_stmt.symbols, level + 1, NULL);
|
||||
printf_buf(buf, "%p=\n", level);
|
||||
print_ast_node_list(buf, node->for_stmt.expr_list, level + 1, ",");
|
||||
printf_buf(buf, "%pdo\n", level);
|
||||
print_statement_list(buf, node->for_stmt.for_statement_list, level + 1);
|
||||
printf_buf(buf, "%pend\n", level);
|
||||
break;
|
||||
}
|
||||
case AST_SUFFIXED_EXPR: {
|
||||
printf_buf(buf, "%p%c %T\n", level, "[suffixed expr start]", &node->suffixed_expr.type);
|
||||
printf_buf(buf, "%p%c %T\n", level+1, "[primary start]", &node->suffixed_expr.primary_expr->common_expr.type);
|
||||
raviA_print_ast_node(buf, node->suffixed_expr.primary_expr, level + 2);
|
||||
printf_buf(buf, "%p%c\n", level+1, "[primary end]");
|
||||
if (node->suffixed_expr.suffix_list) {
|
||||
printf_buf(buf, "%p%c\n", level+1, "[suffix list start]");
|
||||
print_ast_node_list(buf, node->suffixed_expr.suffix_list, level + 2, NULL);
|
||||
printf_buf(buf, "%p%c\n", level+1, "[suffix list end]");
|
||||
}
|
||||
printf_buf(buf, "%p%c\n", level, "[suffixed expr end]");
|
||||
break;
|
||||
}
|
||||
case AST_FUNCTION_CALL_EXPR: {
|
||||
printf_buf(buf, "%p%c %T\n", level, "[function call start]", &node->function_call_expr.type);
|
||||
if (node->function_call_expr.method_name) {
|
||||
printf_buf(buf, "%p: %t (\n", level + 1, node->function_call_expr.method_name);
|
||||
}
|
||||
else {
|
||||
printf_buf(buf, "%p(\n", level + 1);
|
||||
}
|
||||
print_ast_node_list(buf, node->function_call_expr.arg_list, level + 2, ",");
|
||||
printf_buf(buf, "%p)\n", level + 1);
|
||||
printf_buf(buf, "%p%c\n", level, "[function call end]");
|
||||
break;
|
||||
}
|
||||
case AST_SYMBOL_EXPR: {
|
||||
print_symbol(buf, node->symbol_expr.var, level + 1);
|
||||
break;
|
||||
}
|
||||
case AST_BINARY_EXPR: {
|
||||
printf_buf(buf, "%p%c %T\n", level, "[binary expr start]", &node->binary_expr.type);
|
||||
raviA_print_ast_node(buf, node->binary_expr.expr_left, level + 1);
|
||||
printf_buf(buf, "%p%s\n", level, get_binary_opr_str(node->binary_expr.binary_op));
|
||||
raviA_print_ast_node(buf, node->binary_expr.expr_right, level + 1);
|
||||
printf_buf(buf, "%p%c\n", level, "[binary expr end]");
|
||||
break;
|
||||
}
|
||||
case AST_UNARY_EXPR: {
|
||||
printf_buf(buf, "%p%c %T\n", level, "[unary expr start]", &node->unary_expr.type);
|
||||
printf_buf(buf, "%p%s\n", level, get_unary_opr_str(node->unary_expr.unary_op));
|
||||
raviA_print_ast_node(buf, node->unary_expr.expr, level + 1);
|
||||
printf_buf(buf, "%p%c\n", level, "[unary expr end]");
|
||||
break;
|
||||
}
|
||||
case AST_LITERAL_EXPR: {
|
||||
printf_buf(buf, "%p", level);
|
||||
switch (node->literal_expr.type.type_code) {
|
||||
case RAVI_TNIL:
|
||||
printf_buf(buf, "nil");
|
||||
break;
|
||||
case RAVI_TBOOLEAN:
|
||||
printf_buf(buf, "%b", node->literal_expr.u.i);
|
||||
break;
|
||||
case RAVI_TNUMINT:
|
||||
printf_buf(buf, "%i", node->literal_expr.u.i);
|
||||
break;
|
||||
case RAVI_TNUMFLT:
|
||||
printf_buf(buf, "%f", node->literal_expr.u.n);
|
||||
break;
|
||||
case RAVI_TSTRING:
|
||||
printf_buf(buf, "'%t'", node->literal_expr.u.s);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
printf_buf(buf, "\n");
|
||||
break;
|
||||
}
|
||||
case AST_FIELD_SELECTOR_EXPR: {
|
||||
printf_buf(buf, "%p%c %T\n", level, "[field selector start]", &node->index_expr.type);
|
||||
printf_buf(buf, "%p.\n", level + 1);
|
||||
raviA_print_ast_node(buf, node->index_expr.expr, level + 2);
|
||||
printf_buf(buf, "%p%c\n", level, "[field selector end]");
|
||||
break;
|
||||
}
|
||||
case AST_Y_INDEX_EXPR: {
|
||||
printf_buf(buf, "%p%c %T\n", level, "[Y index start]", &node->index_expr.type);
|
||||
printf_buf(buf, "%p[\n", level + 1);
|
||||
raviA_print_ast_node(buf, node->index_expr.expr, level + 2);
|
||||
printf_buf(buf, "%p]\n", level + 1);
|
||||
printf_buf(buf, "%p%c\n", level, "[Y index end]");
|
||||
break;
|
||||
}
|
||||
case AST_INDEXED_ASSIGN_EXPR: {
|
||||
printf_buf(buf, "%p%c %T\n", level, "[indexed assign start]", &node->indexed_assign_expr.type);
|
||||
if (node->indexed_assign_expr.index_expr) {
|
||||
printf_buf(buf, "%p%c\n", level, "[index start]");
|
||||
raviA_print_ast_node(buf, node->indexed_assign_expr.index_expr, level + 1);
|
||||
printf_buf(buf, "%p%c\n", level, "[index end]");
|
||||
}
|
||||
printf_buf(buf, "%p%c\n", level, "[value start]");
|
||||
raviA_print_ast_node(buf, node->indexed_assign_expr.value_expr, level + 1);
|
||||
printf_buf(buf, "%p%c\n", level, "[value end]");
|
||||
printf_buf(buf, "%p%c\n", level, "[indexed assign end]");
|
||||
break;
|
||||
}
|
||||
case AST_TABLE_EXPR: {
|
||||
printf_buf(buf, "%p{ %c %T\n", level, "[table constructor start]", &node->table_expr.type);
|
||||
print_ast_node_list(buf, node->table_expr.expr_list, level + 1, ",");
|
||||
printf_buf(buf, "%p} %c\n", level, "[table constructor end]");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf_buf(buf, "%pUnsupported node type %d\n", level, node->type);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
@ -1,476 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2018-2020 Dibyendu Majumdar
|
||||
*/
|
||||
#include <ravi_ast.h>
|
||||
#include "ravi_ast.h"
|
||||
|
||||
/* Type checker - WIP */
|
||||
static void typecheck_ast_node(struct ast_container *container, struct ast_node *function, struct ast_node *node);
|
||||
|
||||
/* Type checker - WIP */
|
||||
static void typecheck_ast_list(struct ast_container *container, struct ast_node *function, struct ast_node_list *list) {
|
||||
struct ast_node *node;
|
||||
FOR_EACH_PTR(list, node) { typecheck_ast_node(container, function, node); }
|
||||
END_FOR_EACH_PTR(node);
|
||||
}
|
||||
|
||||
/* Type checker - WIP */
|
||||
static void typecheck_unaryop(struct ast_container *container, struct ast_node *function, struct ast_node *node) {
|
||||
UnOpr op = node->unary_expr.unary_op;
|
||||
typecheck_ast_node(container, function, node->unary_expr.expr);
|
||||
ravitype_t subexpr_type = node->unary_expr.expr->common_expr.type.type_code;
|
||||
switch (op) {
|
||||
case OPR_MINUS:
|
||||
if (subexpr_type == RAVI_TNUMINT) {
|
||||
set_type(node->unary_expr.type, RAVI_TNUMINT);
|
||||
}
|
||||
else if (subexpr_type == RAVI_TNUMFLT) {
|
||||
set_type(node->unary_expr.type, RAVI_TNUMFLT);
|
||||
}
|
||||
break;
|
||||
case OPR_LEN:
|
||||
if (subexpr_type == RAVI_TARRAYINT || subexpr_type == RAVI_TARRAYFLT) {
|
||||
set_type(node->unary_expr.type, RAVI_TNUMINT);
|
||||
}
|
||||
break;
|
||||
case OPR_TO_INTEGER:
|
||||
set_type(node->unary_expr.type, RAVI_TNUMINT);
|
||||
break;
|
||||
case OPR_TO_NUMBER:
|
||||
set_type(node->unary_expr.type, RAVI_TNUMFLT);
|
||||
break;
|
||||
case OPR_TO_CLOSURE:
|
||||
set_type(node->unary_expr.type, RAVI_TFUNCTION);
|
||||
break;
|
||||
case OPR_TO_STRING:
|
||||
set_type(node->unary_expr.type, RAVI_TSTRING);
|
||||
break;
|
||||
case OPR_TO_INTARRAY:
|
||||
set_type(node->unary_expr.type, RAVI_TARRAYINT);
|
||||
if (node->unary_expr.expr->type == AST_TABLE_EXPR) {
|
||||
set_type(node->unary_expr.expr->table_expr.type, RAVI_TARRAYINT);
|
||||
}
|
||||
break;
|
||||
case OPR_TO_NUMARRAY:
|
||||
set_type(node->unary_expr.type, RAVI_TARRAYFLT);
|
||||
if (node->unary_expr.expr->type == AST_TABLE_EXPR) {
|
||||
set_type(node->unary_expr.expr->table_expr.type, RAVI_TARRAYFLT);
|
||||
}
|
||||
break;
|
||||
case OPR_TO_TABLE:
|
||||
set_type(node->unary_expr.type, RAVI_TTABLE);
|
||||
break;
|
||||
case OPR_TO_TYPE:
|
||||
lua_assert(node->unary_expr.type.type_name != NULL); // Should already be set by the parser
|
||||
set_typecode(node->unary_expr.type, RAVI_TUSERDATA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Type checker - WIP */
|
||||
static void typecheck_binaryop(struct ast_container *container, struct ast_node *function, struct ast_node *node) {
|
||||
BinOpr op = node->binary_expr.binary_op;
|
||||
struct ast_node *e1 = node->binary_expr.expr_left;
|
||||
struct ast_node *e2 = node->binary_expr.expr_right;
|
||||
typecheck_ast_node(container, function, e1);
|
||||
typecheck_ast_node(container, function, e2);
|
||||
switch (op) {
|
||||
case OPR_ADD:
|
||||
case OPR_SUB:
|
||||
case OPR_MUL:
|
||||
case OPR_DIV:
|
||||
if (e1->common_expr.type.type_code == RAVI_TNUMFLT && e2->common_expr.type.type_code == RAVI_TNUMFLT)
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMFLT);
|
||||
else if (e1->common_expr.type.type_code == RAVI_TNUMFLT && e2->common_expr.type.type_code == RAVI_TNUMINT)
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMFLT);
|
||||
else if (e1->common_expr.type.type_code == RAVI_TNUMINT && e2->common_expr.type.type_code == RAVI_TNUMFLT)
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMFLT);
|
||||
else if (op != OPR_DIV && e1->common_expr.type.type_code == RAVI_TNUMINT &&
|
||||
e2->common_expr.type.type_code == RAVI_TNUMINT)
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMINT);
|
||||
else if (op == OPR_DIV && e1->common_expr.type.type_code == RAVI_TNUMINT &&
|
||||
e2->common_expr.type.type_code == RAVI_TNUMINT)
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMFLT);
|
||||
break;
|
||||
case OPR_IDIV:
|
||||
if (e1->common_expr.type.type_code == RAVI_TNUMINT && e2->common_expr.type.type_code == RAVI_TNUMINT)
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMINT);
|
||||
// FIXME missing cases
|
||||
break;
|
||||
case OPR_BAND:
|
||||
case OPR_BOR:
|
||||
case OPR_BXOR:
|
||||
case OPR_SHL:
|
||||
case OPR_SHR:
|
||||
if ((e1->common_expr.type.type_code == RAVI_TNUMFLT || e1->common_expr.type.type_code == RAVI_TNUMINT) &&
|
||||
(e2->common_expr.type.type_code == RAVI_TNUMFLT || e2->common_expr.type.type_code == RAVI_TNUMINT))
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMINT);
|
||||
break;
|
||||
case OPR_EQ:
|
||||
case OPR_NE:
|
||||
case OPR_GE:
|
||||
case OPR_GT:
|
||||
case OPR_LE:
|
||||
case OPR_LT:
|
||||
/* This case is not handled in default parser - why? */
|
||||
if ((e1->common_expr.type.type_code == RAVI_TNUMINT || e1->common_expr.type.type_code == RAVI_TNUMFLT ||
|
||||
e1->common_expr.type.type_code == RAVI_TBOOLEAN) &&
|
||||
(e2->common_expr.type.type_code == RAVI_TNUMFLT || e2->common_expr.type.type_code == RAVI_TNUMINT ||
|
||||
e2->common_expr.type.type_code == RAVI_TBOOLEAN))
|
||||
set_typecode(node->binary_expr.type, RAVI_TBOOLEAN);
|
||||
break;
|
||||
case OPR_POW:
|
||||
if ((e1->common_expr.type.type_code == RAVI_TNUMFLT || e1->common_expr.type.type_code == RAVI_TNUMINT) &&
|
||||
(e2->common_expr.type.type_code == RAVI_TNUMFLT || e2->common_expr.type.type_code == RAVI_TNUMINT))
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMFLT);
|
||||
break;
|
||||
case OPR_MOD:
|
||||
if (e1->common_expr.type.type_code == RAVI_TNUMINT && e2->common_expr.type.type_code == RAVI_TNUMINT)
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMINT);
|
||||
else if ((e1->common_expr.type.type_code == RAVI_TNUMINT && e2->common_expr.type.type_code == RAVI_TNUMFLT) ||
|
||||
(e1->common_expr.type.type_code == RAVI_TNUMFLT && e2->common_expr.type.type_code == RAVI_TNUMINT))
|
||||
set_typecode(node->binary_expr.type, RAVI_TNUMFLT);
|
||||
break;
|
||||
default:
|
||||
set_typecode(node->binary_expr.type, RAVI_TANY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_unindexable_type(struct var_type *type) {
|
||||
switch (type->type_code) {
|
||||
case RAVI_TNUMFLT:
|
||||
case RAVI_TNUMINT:
|
||||
case RAVI_TBOOLEAN:
|
||||
case RAVI_TNIL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Suffixed expression examples:
|
||||
* f()[1]
|
||||
* x[1][2]
|
||||
* x.y[1]
|
||||
*/
|
||||
static void typecheck_suffixedexpr(struct ast_container *container, struct ast_node *function, struct ast_node *node) {
|
||||
typecheck_ast_node(container, function, node->suffixed_expr.primary_expr);
|
||||
struct ast_node *prev_node = node->suffixed_expr.primary_expr;
|
||||
struct ast_node *this_node;
|
||||
FOR_EACH_PTR(node->suffixed_expr.suffix_list, this_node) {
|
||||
typecheck_ast_node(container, function, this_node);
|
||||
if (this_node->type == AST_Y_INDEX_EXPR) {
|
||||
if (prev_node->common_expr.type.type_code == RAVI_TARRAYFLT) {
|
||||
if (this_node->index_expr.expr->common_expr.type.type_code == RAVI_TNUMINT) {
|
||||
set_typecode(this_node->index_expr.type, RAVI_TNUMFLT);
|
||||
}
|
||||
else {
|
||||
// FIXME Error
|
||||
}
|
||||
}
|
||||
else if (prev_node->common_expr.type.type_code == RAVI_TARRAYINT) {
|
||||
if (this_node->index_expr.expr->common_expr.type.type_code == RAVI_TNUMINT) {
|
||||
set_typecode(this_node->index_expr.type, RAVI_TNUMINT);
|
||||
}
|
||||
else {
|
||||
// FIXME Error
|
||||
}
|
||||
}
|
||||
else if (is_unindexable_type(&prev_node->common_expr.type)) {
|
||||
// FIXME Error
|
||||
}
|
||||
}
|
||||
prev_node = this_node;
|
||||
}
|
||||
END_FOR_EACH_PTR(node);
|
||||
copy_type(node->suffixed_expr.type, prev_node->common_expr.type);
|
||||
}
|
||||
|
||||
static void insert_cast(struct ast_container *container, struct ast_node *expr, UnOpr opcode, ravitype_t target_type) {
|
||||
/* convert the node to @integer node, the original content of node goes into the subexpr */
|
||||
struct ast_node *copy_expr = dmrC_allocator_allocate(&container->ast_node_allocator, 0);
|
||||
*copy_expr = *expr;
|
||||
expr->type = AST_UNARY_EXPR;
|
||||
expr->unary_expr.expr = copy_expr;
|
||||
expr->unary_expr.unary_op = opcode;
|
||||
set_typecode(expr->unary_expr.type, target_type);
|
||||
}
|
||||
|
||||
static void typecheck_var_assignment(struct ast_container *container, struct var_type *var_type, struct ast_node *expr,
|
||||
const char *var_name) {
|
||||
if (var_type->type_code == RAVI_TANY)
|
||||
// Any value can be assigned to type ANY
|
||||
return;
|
||||
|
||||
struct var_type *expr_type = &expr->common_expr.type;
|
||||
|
||||
if (var_type->type_code == RAVI_TNUMINT) {
|
||||
/* if the expr is of type number or # operator then insert @integer operator */
|
||||
if (expr_type->type_code == RAVI_TNUMFLT ||
|
||||
(expr->type == AST_UNARY_EXPR && expr->unary_expr.unary_op == OPR_LEN)) {
|
||||
insert_cast(container, expr, OPR_TO_INTEGER, RAVI_TNUMINT);
|
||||
}
|
||||
else if (expr_type->type_code != RAVI_TNUMINT) {
|
||||
fprintf(stderr, "Assignment to local symbol %s is not type compatible\n", var_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (var_type->type_code == RAVI_TNUMFLT) {
|
||||
if (expr_type->type_code == RAVI_TNUMINT) {
|
||||
/* cast to number */
|
||||
insert_cast(container, expr, OPR_TO_NUMBER, RAVI_TNUMFLT);
|
||||
}
|
||||
else if (expr_type->type_code != RAVI_TNUMFLT) {
|
||||
fprintf(stderr, "Assignment to local symbol %s is not type compatible\n", var_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// all other types must strictly match
|
||||
if (!is_type_same(*var_type, *expr_type)) { // We should probably check type convert-ability here
|
||||
fprintf(stderr, "Assignment to local symbol %s is not type compatible\n", var_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void typecheck_local_statement(struct ast_container *container, struct ast_node *function,
|
||||
struct ast_node *node) {
|
||||
// The local vars should already be annotated
|
||||
// We need to typecheck the expressions to the right of =
|
||||
// Then we need to ensure that the assignments are valid
|
||||
// We can perhaps insert type assertions where we have a mismatch?
|
||||
|
||||
typecheck_ast_list(container, function, node->local_stmt.expr_list);
|
||||
|
||||
struct lua_symbol *var;
|
||||
struct ast_node *expr;
|
||||
PREPARE_PTR_LIST(node->local_stmt.var_list, var);
|
||||
PREPARE_PTR_LIST(node->local_stmt.expr_list, expr);
|
||||
|
||||
for (;;) {
|
||||
if (!var || !expr)
|
||||
break;
|
||||
|
||||
struct var_type *var_type = &var->value_type;
|
||||
const char *var_name = getstr(var->var.var_name);
|
||||
|
||||
typecheck_var_assignment(container, var_type, expr, var_name);
|
||||
|
||||
NEXT_PTR_LIST(var);
|
||||
NEXT_PTR_LIST(expr);
|
||||
}
|
||||
}
|
||||
|
||||
static void typecheck_expr_statement(struct ast_container *container, struct ast_node *function,
|
||||
struct ast_node *node) {
|
||||
if (node->expression_stmt.var_expr_list)
|
||||
typecheck_ast_list(container, function, node->expression_stmt.var_expr_list);
|
||||
typecheck_ast_list(container, function, node->expression_stmt.expr_list);
|
||||
|
||||
if (!node->expression_stmt.var_expr_list)
|
||||
return;
|
||||
|
||||
struct ast_node *var;
|
||||
struct ast_node *expr;
|
||||
PREPARE_PTR_LIST(node->expression_stmt.var_expr_list, var);
|
||||
PREPARE_PTR_LIST(node->local_stmt.expr_list, expr);
|
||||
|
||||
for (;;) {
|
||||
if (!var || !expr)
|
||||
break;
|
||||
|
||||
struct var_type *var_type = &var->common_expr.type;
|
||||
const char *var_name = ""; // FIXME how do we get this?
|
||||
|
||||
typecheck_var_assignment(container, var_type, expr, var_name);
|
||||
|
||||
NEXT_PTR_LIST(var);
|
||||
NEXT_PTR_LIST(expr);
|
||||
}
|
||||
}
|
||||
|
||||
static void typecheck_for_in_statment(struct ast_container *container, struct ast_node *function,
|
||||
struct ast_node *node) {
|
||||
typecheck_ast_list(container, function, node->for_stmt.expr_list);
|
||||
typecheck_ast_list(container, function, node->for_stmt.for_statement_list);
|
||||
}
|
||||
|
||||
static void typecheck_for_num_statment(struct ast_container *container, struct ast_node *function,
|
||||
struct ast_node *node) {
|
||||
typecheck_ast_list(container, function, node->for_stmt.expr_list);
|
||||
struct ast_node *expr;
|
||||
enum { I = 1, F = 2, A = 4 }; /* bits representing integer, number, any */
|
||||
int index_type = 0;
|
||||
FOR_EACH_PTR(node->for_stmt.expr_list, expr) {
|
||||
switch (expr->common_expr.type.type_code) {
|
||||
case RAVI_TNUMFLT:
|
||||
index_type |= F;
|
||||
break;
|
||||
case RAVI_TNUMINT:
|
||||
index_type |= I;
|
||||
break;
|
||||
default:
|
||||
index_type |= A;
|
||||
break;
|
||||
}
|
||||
if ((index_type & A) != 0)
|
||||
break;
|
||||
}
|
||||
END_FOR_EACH_PTR(expr);
|
||||
if ((index_type & A) == 0) { /* not any */
|
||||
/* for I+F we use F */
|
||||
ravitype_t symbol_type = index_type == I ? RAVI_TNUMINT : RAVI_TNUMFLT;
|
||||
struct lua_symbol_list *symbols = node->for_stmt.symbols;
|
||||
struct lua_symbol *sym;
|
||||
/* actually there will be only index variable */
|
||||
FOR_EACH_PTR(symbols, sym) {
|
||||
if (sym->symbol_type == SYM_LOCAL) {
|
||||
set_typecode(sym->value_type, symbol_type);
|
||||
}
|
||||
else {
|
||||
assert(0); /* cannot happen */
|
||||
}
|
||||
}
|
||||
END_FOR_EACH_PTR(sym);
|
||||
}
|
||||
typecheck_ast_list(container, function, node->for_stmt.for_statement_list);
|
||||
}
|
||||
|
||||
static void typecheck_if_statement(struct ast_container *container, struct ast_node *function, struct ast_node *node) {
|
||||
struct ast_node *test_then_block;
|
||||
FOR_EACH_PTR(node->if_stmt.if_condition_list, test_then_block) {
|
||||
typecheck_ast_node(container, function, test_then_block->test_then_block.condition);
|
||||
typecheck_ast_list(container, function, test_then_block->test_then_block.test_then_statement_list);
|
||||
}
|
||||
END_FOR_EACH_PTR(node);
|
||||
if (node->if_stmt.else_statement_list) {
|
||||
typecheck_ast_list(container, function, node->if_stmt.else_statement_list);
|
||||
}
|
||||
}
|
||||
|
||||
static void typecheck_while_or_repeat_statement(struct ast_container *container, struct ast_node *function,
|
||||
struct ast_node *node) {
|
||||
typecheck_ast_node(container, function, node->while_or_repeat_stmt.condition);
|
||||
if (node->while_or_repeat_stmt.loop_statement_list) {
|
||||
typecheck_ast_list(container, function, node->while_or_repeat_stmt.loop_statement_list);
|
||||
}
|
||||
}
|
||||
|
||||
/* Type checker - WIP */
|
||||
static void typecheck_ast_node(struct ast_container *container, struct ast_node *function, struct ast_node *node) {
|
||||
switch (node->type) {
|
||||
case AST_FUNCTION_EXPR: {
|
||||
typecheck_ast_list(container, function, node->function_expr.function_statement_list);
|
||||
break;
|
||||
}
|
||||
case AST_NONE: {
|
||||
break;
|
||||
}
|
||||
case AST_RETURN_STMT: {
|
||||
typecheck_ast_list(container, function, node->return_stmt.expr_list);
|
||||
break;
|
||||
}
|
||||
case AST_LOCAL_STMT: {
|
||||
typecheck_local_statement(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_FUNCTION_STMT: {
|
||||
typecheck_ast_node(container, function, node->function_stmt.function_expr);
|
||||
break;
|
||||
}
|
||||
case AST_LABEL_STMT: {
|
||||
break;
|
||||
}
|
||||
case AST_GOTO_STMT: {
|
||||
break;
|
||||
}
|
||||
case AST_DO_STMT: {
|
||||
break;
|
||||
}
|
||||
case AST_EXPR_STMT: {
|
||||
typecheck_expr_statement(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_IF_STMT: {
|
||||
typecheck_if_statement(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_WHILE_STMT:
|
||||
case AST_REPEAT_STMT: {
|
||||
typecheck_while_or_repeat_statement(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_FORIN_STMT: {
|
||||
typecheck_for_in_statment(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_FORNUM_STMT: {
|
||||
typecheck_for_num_statment(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_SUFFIXED_EXPR: {
|
||||
typecheck_suffixedexpr(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_FUNCTION_CALL_EXPR: {
|
||||
if (node->function_call_expr.method_name) {
|
||||
}
|
||||
else {
|
||||
}
|
||||
typecheck_ast_list(container, function, node->function_call_expr.arg_list);
|
||||
break;
|
||||
}
|
||||
case AST_SYMBOL_EXPR: {
|
||||
/* symbol type should have been set when symbol was created */
|
||||
copy_type(node->symbol_expr.type, node->symbol_expr.var->value_type);
|
||||
break;
|
||||
}
|
||||
case AST_BINARY_EXPR: {
|
||||
typecheck_binaryop(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_UNARY_EXPR: {
|
||||
typecheck_unaryop(container, function, node);
|
||||
break;
|
||||
}
|
||||
case AST_LITERAL_EXPR: {
|
||||
/* type set during parsing */
|
||||
break;
|
||||
}
|
||||
case AST_FIELD_SELECTOR_EXPR: {
|
||||
typecheck_ast_node(container, function, node->index_expr.expr);
|
||||
break;
|
||||
}
|
||||
case AST_Y_INDEX_EXPR: {
|
||||
typecheck_ast_node(container, function, node->index_expr.expr);
|
||||
break;
|
||||
}
|
||||
case AST_INDEXED_ASSIGN_EXPR: {
|
||||
if (node->indexed_assign_expr.index_expr) {
|
||||
typecheck_ast_node(container, function, node->indexed_assign_expr.index_expr);
|
||||
}
|
||||
typecheck_ast_node(container, function, node->indexed_assign_expr.value_expr);
|
||||
copy_type(node->indexed_assign_expr.type, node->indexed_assign_expr.value_expr->common_expr.type);
|
||||
break;
|
||||
}
|
||||
case AST_TABLE_EXPR: {
|
||||
typecheck_ast_list(container, function, node->table_expr.expr_list);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Type checker - WIP */
|
||||
static void typecheck_function(struct ast_container *container, struct ast_node *func) {
|
||||
typecheck_ast_list(container, func, func->function_expr.function_statement_list);
|
||||
}
|
||||
|
||||
/* Type checker - WIP */
|
||||
void raviA_ast_typecheck(struct ast_container *container) {
|
||||
struct ast_node *main_function = container->main_function;
|
||||
typecheck_function(container, main_function);
|
||||
}
|
Loading…
Reference in new issue