issue #98 removing new parser code as migrated to ravi-compiler project

arrays
Dibyendu Majumdar 4 years ago
parent bfaf2a3cef
commit 5834e4c78f

@ -52,13 +52,11 @@ endif ()
include_directories("${PROJECT_SOURCE_DIR}/include")
# define the Lua core source files
set(RAVI_AST_SOURCES src/ravi_ast_parse.c src/ravi_ast_print.c src/ravi_ast_typecheck.c)
set(LUA_CORE_SRCS src/lapi.c src/lcode.c src/lctype.c src/ldebug.c src/ldo.c src/ldump.c
src/lfunc.c src/lgc.c src/llex.c src/lmem.c src/lobject.c src/lopcodes.c
src/lparser.c src/lstate.c src/lstring.c src/ltable.c src/ltm.c src/lundump.c
src/lvm.c src/lzio.c src/ravi_jit.c src/ltests.c src/ravi_profile.c
src/ravi_membuf.c src/ravi_jitshared.c src/bit.c src/ravi_alloc.c
${RAVI_AST_SOURCES})
src/ravi_membuf.c src/ravi_jitshared.c src/bit.c src/ravi_alloc.c)
# define the Lua library source files
set(LUA_LIB_SRCS src/lauxlib.c src/lbaselib.c src/lbitlib.c src/lcorolib.c src/ldblib.c src/liolib.c
src/lmathlib.c src/loslib.c src/ltablib.c src/lstrlib.c src/loadlib.c src/linit.c src/lutf8lib.c)
@ -149,7 +147,7 @@ if (LLVM_JIT)
set_property(SOURCE ${DMR_C_JIT_SRCS} src/ravi_llvmcodegen.cpp ${RAVI_C_SYMBOL_PARSER}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/llvm-backend")
set_property(SOURCE ${DMR_C_SRCS} ${DMR_C_JIT_SRCS} ${RAVI_AST_SOURCES}
set_property(SOURCE ${DMR_C_SRCS} ${DMR_C_JIT_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/src")
set_property(
@ -177,7 +175,7 @@ elseif (OMR_JIT)
set_property(SOURCE ${DMR_C_JIT_SRCS} ${RAVI_C_SYMBOL_PARSER} ${OMR_JIT_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/omrjit-backend")
set_property(SOURCE ${DMR_C_SRCS} ${DMR_C_JIT_SRCS} ${RAVI_AST_SOURCES}
set_property(SOURCE ${DMR_C_SRCS} ${DMR_C_JIT_SRCS}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/src")
set_property(SOURCE ${DMR_C_JIT_SRCS} ${OMR_JIT_SRCS} ${RAVI_C_SYMBOL_PARSER}
@ -190,7 +188,7 @@ else ()
set(DMR_C_SRCS ${DMR_C_SRCS_COMMON})
set(EMBEDDED_DMRC OFF)
set_property(SOURCE ${DMR_C_SRCS_COMMON} ${RAVI_AST_SOURCES}
set_property(SOURCE ${DMR_C_SRCS_COMMON}
APPEND
PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/dmr_c/src")

@ -96,7 +96,6 @@ History
- Implemented Eclipse OMR JIT backend
- Created `Ravi with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
* 2019
- `New parser, type checker for Ravi <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-new-parser-codegenerator.html>`_ - work in progress
- New language feature - `defer` statement
- New JIT backend `MIR <https://github.com/vnmakarov/mir>`_.

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)

@ -17,7 +17,6 @@ Contents:
ravi-omr-instructions
ravi-llvm-instructions
ravi-dmrc
ravi-new-parser-codegenerator
lua-introduction
lua_bytecode_reference
lua-parser

@ -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

@ -96,7 +96,6 @@ History
- Implemented Eclipse OMR JIT backend
- Created `Ravi with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
* 2019
- `New parser, type checker for Ravi <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-new-parser-codegenerator.html>`_ - work in progress
- New language feature - `defer` statement
- New JIT backend `MIR <https://github.com/vnmakarov/mir>`_.

@ -59,7 +59,6 @@ static const luaL_Reg loadedlibs[] = {
{LUA_BITLIBNAME, luaopen_bit32},
#endif
{LUAJIT_BITLIBNAME, luaopen_bit },
{LUA_ASTLIBNAME, raviopen_ast_library},
{NULL, NULL}
};

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…
Cancel
Save