Improve compiler
parent
4c449fab62
commit
beb2e9eaae
|
@ -13,7 +13,7 @@
|
|||
--]]
|
||||
|
||||
vm16.Comp = {}
|
||||
vm16.Comp.version = "1.6"
|
||||
vm16.Comp.version = "1.8"
|
||||
|
||||
local function error_msg(err)
|
||||
local t = string.split(err, "\001")
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
--[[
|
||||
|
||||
VM16 BLL Compiler
|
||||
=================
|
||||
|
||||
Copyright (C) 2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Constant Expression parser
|
||||
|
||||
]]--
|
||||
|
||||
local T_NUMBER = vm16.T_NUMBER
|
||||
|
||||
local BConstEx = vm16.BExpr
|
||||
|
||||
function BConstEx:bconstex_init()
|
||||
self:bexpr_init()
|
||||
end
|
||||
|
||||
--[[
|
||||
const_expression:
|
||||
= const_term
|
||||
| const_term '+' const_expression
|
||||
| const_term '-' const_expression
|
||||
]]--
|
||||
function BConstEx:const_expression()
|
||||
local opnd1 = self:const_term()
|
||||
local val = self:tk_peek().val
|
||||
if val == "+" then
|
||||
self:tk_match()
|
||||
local opnd2 = self:const_expression()
|
||||
return opnd1 + opnd2
|
||||
elseif val == "-" then
|
||||
self:tk_match()
|
||||
local opnd2 = self:const_expression()
|
||||
return opnd1 - opnd2
|
||||
end
|
||||
return opnd1
|
||||
end
|
||||
|
||||
--[[
|
||||
const_term:
|
||||
= const_factor
|
||||
| const_factor '*' const_term
|
||||
| const_factor '/' const_term
|
||||
]]--
|
||||
function BConstEx:const_term()
|
||||
local opnd1 = self:const_factor()
|
||||
local val = self:tk_peek().val
|
||||
if val == "*" then
|
||||
self:tk_match()
|
||||
local opnd2 = self:const_term()
|
||||
return math.floor(opnd1 * opnd2)
|
||||
elseif val == "/" then
|
||||
self:tk_match()
|
||||
local opnd2 = self:const_term()
|
||||
return math.floor(opnd1 / opnd2)
|
||||
end
|
||||
return opnd1
|
||||
end
|
||||
|
||||
--[[
|
||||
const_factor:
|
||||
= '(' const_expression ')'
|
||||
| number
|
||||
| CONST
|
||||
]]--
|
||||
function BConstEx:const_factor()
|
||||
local tok = self:tk_peek()
|
||||
if tok.type == T_NUMBER then
|
||||
self:tk_match()
|
||||
return tok.val
|
||||
elseif self:sym_is_const(tok.val) then
|
||||
self:tk_match()
|
||||
return tonumber(string.sub(self:sym_get_const(tok.val), 2))
|
||||
elseif tok.val == "(" then
|
||||
self:tk_match("(")
|
||||
local res = self:const_expression()
|
||||
self:tk_match(")")
|
||||
return res
|
||||
else
|
||||
self:error_msg(string.format("Syntax error at '%s'", tok.val or ""))
|
||||
return tok.val or ""
|
||||
end
|
||||
end
|
||||
|
||||
vm16.BConstEx = BConstEx
|
|
@ -138,6 +138,7 @@ unary:
|
|||
| '~' postfix
|
||||
| '*' postfix
|
||||
| '&' postfix
|
||||
| 'sizeof' '(' variable ')'
|
||||
]]--
|
||||
function BExpr:unary()
|
||||
local val = self:tk_peek().val
|
||||
|
@ -171,6 +172,16 @@ function BExpr:unary()
|
|||
return reg
|
||||
end
|
||||
return "#" .. opnd
|
||||
elseif val == "sizeof" then
|
||||
self:tk_match("sizeof")
|
||||
self:tk_match("(")
|
||||
local ident = (self:tk_match(T_IDENT) or {}).val
|
||||
if not self:sym_get_var(ident) then
|
||||
self:error_msg(string.format("Unknown variable '%s'", ident or ""))
|
||||
end
|
||||
local size = self:sym_get_var_size(ident)
|
||||
self:tk_match(")")
|
||||
return "#" .. size
|
||||
end
|
||||
return self:postfix()
|
||||
end
|
||||
|
|
|
@ -20,10 +20,10 @@ local T_NEWFILE = vm16.T_NEWFILE
|
|||
local T_STRING = vm16.T_STRING
|
||||
local T_ENDFILE = vm16.T_ENDFILE
|
||||
|
||||
local BPars = vm16.BExpr:new({})
|
||||
local BPars = vm16.BConstEx:new({})
|
||||
|
||||
function BPars:bpars_init()
|
||||
self:bexpr_init()
|
||||
self:bconstex_init()
|
||||
end
|
||||
|
||||
--[[
|
||||
|
@ -43,6 +43,7 @@ definition:
|
|||
= 'var' var_def
|
||||
| 'static' 'var' var_def
|
||||
| 'const' const_def
|
||||
| 'static' 'const' const_def
|
||||
| 'func' func_def
|
||||
| 'static' 'func' func_def
|
||||
| T_NEWFILE
|
||||
|
@ -62,6 +63,9 @@ function BPars:definition()
|
|||
elseif tok.val == "func" then
|
||||
self:tk_match("func")
|
||||
self:func_def(true)
|
||||
elseif tok.val == "const" then
|
||||
self:tk_match("const")
|
||||
self:const_def(true)
|
||||
else
|
||||
self:error_msg(string.format("Unexpected item '%s'", tok.val))
|
||||
end
|
||||
|
@ -105,10 +109,12 @@ function BPars:var_def(static)
|
|||
local ident = self:ident()
|
||||
local val = self:tk_peek().val
|
||||
local is_array = val == "["
|
||||
local old_ident
|
||||
|
||||
if static then
|
||||
local old_ident = ident
|
||||
old_ident = ident
|
||||
local postfix = is_array and "[]" or ""
|
||||
ident = self:sym_add_filelocal(ident, is_array)
|
||||
ident = self:sym_get_filelocal_ref(ident)
|
||||
self:add_debugger_info("lvar", self.lineno, ident, old_ident .. postfix)
|
||||
else
|
||||
local postfix = is_array and "[]" or ""
|
||||
|
@ -117,17 +123,21 @@ function BPars:var_def(static)
|
|||
self:switch_to_var_def()
|
||||
self:set_global(ident)
|
||||
if is_array then
|
||||
local size = self:array_def(ident)
|
||||
if static then
|
||||
self:sym_add_filelocal(ident, true)
|
||||
-- post-define array size
|
||||
self:sym_add_filelocal(old_ident, true, size) -- name without postfix
|
||||
self:sym_add_filelocal(ident, true, size)
|
||||
else
|
||||
self:sym_add_global(ident, true)
|
||||
self:sym_add_global(ident, true, size)
|
||||
end
|
||||
self:array_def(ident)
|
||||
self:tk_match(";")
|
||||
self:reset_reg_use()
|
||||
else
|
||||
if static then
|
||||
self:sym_add_filelocal(ident)
|
||||
-- post-define array size
|
||||
self:sym_add_filelocal(old_ident, false, 1) -- name without postfix
|
||||
self:sym_add_filelocal(ident, false, 1)
|
||||
else
|
||||
self:sym_add_global(ident)
|
||||
end
|
||||
|
@ -145,14 +155,14 @@ end
|
|||
|
||||
--[[
|
||||
const_def:
|
||||
= ident '=' number ';' def_list
|
||||
= ident '=' const_expression ';' def_list
|
||||
]]--
|
||||
function BPars:const_def()
|
||||
function BPars:const_def(static)
|
||||
self:switch_to_var_def()
|
||||
local ident = self:ident()
|
||||
self:tk_match("=")
|
||||
local right = '#' .. self:number()
|
||||
self:sym_add_const(ident, right, "global")
|
||||
local right = '#' .. self:const_expression()
|
||||
self:sym_add_const(ident, right, static and "local" or "global")
|
||||
self:tk_match(";")
|
||||
self:reset_reg_use()
|
||||
self:switch_to_func_def()
|
||||
|
@ -162,23 +172,24 @@ end
|
|||
array_def:
|
||||
= '[' ']' '=' '{' const_list '}'
|
||||
= '[' ']' '=' STRING
|
||||
= '[' number ']' '=' '{' const_list '}'
|
||||
= '[' number ']'
|
||||
= '[' const_expression ']' '=' '{' const_list '}'
|
||||
= '[' const_expression ']'
|
||||
]]--
|
||||
function BPars:array_def(ident)
|
||||
self:tk_match("[")
|
||||
local size = 0
|
||||
if self:tk_peek().val ~= ']' then
|
||||
size = self:number()
|
||||
size = self:const_expression()
|
||||
end
|
||||
self:tk_match("]")
|
||||
if self:tk_peek().val ~= '=' and size > 0 then
|
||||
self:add_data(ident)
|
||||
while size > 1 do
|
||||
local num = size
|
||||
while num > 1 do
|
||||
self:append_val(0)
|
||||
size = size - 1
|
||||
num = num - 1
|
||||
end
|
||||
return
|
||||
return size
|
||||
end
|
||||
self:tk_match("=")
|
||||
if self:tk_peek().type == T_STRING then
|
||||
|
@ -189,19 +200,21 @@ function BPars:array_def(ident)
|
|||
self:add_string(ident, tok.val)
|
||||
else
|
||||
self:tk_match("{")
|
||||
self:const_list(ident, size)
|
||||
size = self:const_list(ident, size)
|
||||
self:tk_match("}")
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
--[[
|
||||
const_list:
|
||||
number { ',' const_list }
|
||||
const_expression { ',' const_list }
|
||||
]]--
|
||||
function BPars:const_list(ident, size)
|
||||
local num = self:number()
|
||||
local num = self:const_expression()
|
||||
self:add_data(ident, num)
|
||||
size = size - 1
|
||||
local realsize = 1
|
||||
while self:tk_peek().val == ',' do
|
||||
self:tk_match(",")
|
||||
|
||||
|
@ -214,12 +227,16 @@ function BPars:const_list(ident, size)
|
|||
self:append_val(tok.val)
|
||||
end
|
||||
size = size - 1
|
||||
realsize = realsize + 1
|
||||
end
|
||||
|
||||
while size > 0 do
|
||||
self:append_val(0)
|
||||
size = size - 1
|
||||
realsize = realsize + 1
|
||||
end
|
||||
return realsize
|
||||
|
||||
end
|
||||
|
||||
--[[
|
||||
|
|
|
@ -17,7 +17,7 @@ local KEYWORDS = {var=1, func=1, ["while"]=1, ["return"]=1, input=1, output=1,
|
|||
["for"]=1, ["switch"]=1, ["case"]=1, ["break"]=1, ["continue"]=1, ["goto"]=1,
|
||||
["and"]=1, ["or"]=1, ["not"]=1, ["xor"]=1, ["mod"]=1,
|
||||
A=1, B=1, C=1, D=1, X=1, Y=1, PC=1, SP=1,
|
||||
import=1, pragma=1, _asm_=1}
|
||||
import=1, pragma=1, _asm_=1, sizeof=1}
|
||||
|
||||
local BSym = vm16.BScan:new({})
|
||||
|
||||
|
@ -47,9 +47,9 @@ function BSym:sym_add_local(ident, array_size)
|
|||
end
|
||||
self.stack_size = self.stack_size + 1
|
||||
if array_size then
|
||||
self.locals[ident] = {type = "array", ref = self.stack_size, offs = array_size - 1}
|
||||
self.locals[ident] = {type = "array", ref = self.stack_size, offs = array_size - 1, size = array_size}
|
||||
else
|
||||
self.locals[ident] = {type = "var", ref = self.stack_size}
|
||||
self.locals[ident] = {type = "var", ref = self.stack_size, size = 1}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -73,13 +73,13 @@ end
|
|||
-------------------------------------------------------------------------------
|
||||
-- Globals
|
||||
-------------------------------------------------------------------------------
|
||||
function BSym:sym_add_global(ident, is_array)
|
||||
function BSym:sym_add_global(ident, is_array, array_size)
|
||||
if self.globals[ident] then
|
||||
self:error_msg(string.format("Redefinition of '%s'", ident))
|
||||
elseif KEYWORDS[ident] then
|
||||
self:error_msg(string.format("'%s' is a protected keyword", ident))
|
||||
end
|
||||
self.globals[ident] = {type = is_array and "array" or "var"}
|
||||
self.globals[ident] = {type = is_array and "array" or "var", size = array_size or 1}
|
||||
end
|
||||
|
||||
function BSym:sym_is_global(val)
|
||||
|
@ -107,16 +107,21 @@ function BSym:next_file_for_local_vars()
|
|||
self.file_locals = {}
|
||||
end
|
||||
|
||||
function BSym:sym_add_filelocal(ident, is_array)
|
||||
function BSym:sym_add_filelocal(ident, is_array, array_size)
|
||||
if self.file_locals[ident] then
|
||||
self:error_msg(string.format("Redefinition of '%s'", ident))
|
||||
elseif KEYWORDS[ident] then
|
||||
self:error_msg(string.format("'%s' is a protected keyword", ident))
|
||||
end
|
||||
self.file_locals[ident] = {type = is_array and "array" or "var", ref = ident .. "@" .. self.file_locals_cnt}
|
||||
self.file_locals[ident] = {type = is_array and "array" or "var",
|
||||
ref = ident .. "@" .. self.file_locals_cnt, size = array_size or 1}
|
||||
return self.file_locals[ident].ref
|
||||
end
|
||||
|
||||
function BSym:sym_get_filelocal_ref(ident)
|
||||
return ident .. "@" .. self.file_locals_cnt
|
||||
end
|
||||
|
||||
function BSym:sym_get_filelocal(ident)
|
||||
local item = self.file_locals[ident]
|
||||
if item then
|
||||
|
@ -232,4 +237,14 @@ function BSym:sym_get_var(ident)
|
|||
return self:sym_get_local(ident) or self:sym_get_filelocal(ident) or self:sym_get_global(ident)
|
||||
end
|
||||
|
||||
function BSym:sym_get_var_size(ident)
|
||||
if self:sym_get_local(ident) then
|
||||
return self.locals[ident].size
|
||||
elseif self:sym_get_filelocal(ident) then
|
||||
return self.file_locals[ident].size
|
||||
elseif self:sym_get_global(ident) then
|
||||
return self.globals[ident].size
|
||||
end
|
||||
end
|
||||
|
||||
vm16.BSym = BSym
|
||||
|
|
1
init.lua
1
init.lua
|
@ -36,6 +36,7 @@ dofile(MP.."/bcomp/bgenerator.lua")
|
|||
dofile(MP.."/bcomp/bscanner.lua")
|
||||
dofile(MP.."/bcomp/bsymbols.lua")
|
||||
dofile(MP.."/bcomp/bexpression.lua")
|
||||
dofile(MP.."/bcomp/bconst_expr.lua")
|
||||
dofile(MP.."/bcomp/bparser.lua")
|
||||
dofile(MP.."/bcomp/bcompiler.lua")
|
||||
dofile(MP.."/bcomp/libc.lua")
|
||||
|
|
|
@ -212,7 +212,7 @@ function Lut:is_return_line(file, address)
|
|||
DBG("Lut:is_return_line", address)
|
||||
if address then
|
||||
local lineno = self.addr2lineno[address]
|
||||
return lineno and self.step_out[file][lineno]
|
||||
return lineno and self.step_out[file] and self.step_out[file][lineno]
|
||||
end
|
||||
DBG("Lut:is_return_line", "oops")
|
||||
end
|
||||
|
|
|
@ -67,7 +67,7 @@ local function format_watch(pos, mem)
|
|||
if item.name == "" then
|
||||
out[#out + 1] = "----------------:----------"
|
||||
else
|
||||
local val = vm16.peek(mem.cpu_pos, item.addr)
|
||||
local val = vm16.peek(mem.cpu_pos, item.addr or 0)
|
||||
local s = minetest.formspec_escape(string.format("%-16s: %04X %d", item.name, val, val))
|
||||
out[#out + 1] = s
|
||||
end
|
||||
|
|
|
@ -122,6 +122,12 @@ Licensed under the GNU GPLv3 (See LICENSE.txt)
|
|||
|
||||
## History
|
||||
|
||||
### API v3.5 / Core v2.7.4 / ASM v2.5 / Compiler v1.8 / Debugger v1.3 (2022-07-08)
|
||||
|
||||
- Compiler: Add constant expressions
|
||||
- Compiler: Add sizeof operator
|
||||
- Compiler: Add static constants
|
||||
|
||||
### API v3.5 / Core v2.7.4 / ASM v2.5 / Compiler v1.7 / Debugger v1.3 (2022-07-08)
|
||||
|
||||
- Add file popup menu to the debugger
|
||||
|
|
|
@ -24,6 +24,7 @@ dofile(MP.."/bcomp/bgenerator.lua")
|
|||
dofile(MP.."/bcomp/bscanner.lua")
|
||||
dofile(MP.."/bcomp/bsymbols.lua")
|
||||
dofile(MP.."/bcomp/bexpression.lua")
|
||||
dofile(MP.."/bcomp/bconst_expr.lua")
|
||||
dofile(MP.."/bcomp/bparser.lua")
|
||||
dofile(MP.."/bcomp/bcompiler.lua")
|
||||
dofile(MP.."/programmer/lib.lua")
|
||||
|
@ -105,3 +106,4 @@ compile2("test12.c") -- Pointers
|
|||
compile2("test13.c") -- Function local arrays
|
||||
compile2("test14.c") -- Function local arrays
|
||||
compile2("test15.c") -- comparison vs. expression
|
||||
compile2("test16.c") -- const-expr, sizeof
|
||||
|
|
|
@ -3499,4 +3499,4 @@ brnch 25 009D: "@lbl10"
|
|||
svar 27 2: "@num_stack_var@"
|
||||
func 30 00A0: "loop"
|
||||
svar 30 0: "@num_stack_var@"
|
||||
endf 31 00AB: "test15.c"
|
||||
endf 32 00AB: "test15.c"
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import "stdio.asm"
|
||||
|
||||
const MAX1 = 10;
|
||||
const MAX2 = 2 * MAX1;
|
||||
static const MAX3 = (MAX2 + 1) / 2;
|
||||
|
||||
var arr1[MAX1];
|
||||
var arr2[MAX3+1] = {0,0,0,0};
|
||||
static var arr3[2] = {0,0,0,0};
|
||||
|
||||
func init() {
|
||||
var arr4[3];
|
||||
|
||||
putnum(MAX1);
|
||||
putchar(' ');
|
||||
putnum(MAX2);
|
||||
putchar(' ');
|
||||
putnum(MAX3);
|
||||
putchar(' ');
|
||||
putnum(sizeof(arr1));
|
||||
putchar(' ');
|
||||
putnum(sizeof(arr2));
|
||||
putchar(' ');
|
||||
putnum(sizeof(arr3));
|
||||
putchar(' ');
|
||||
putnum(sizeof(arr4));
|
||||
}
|
||||
|
||||
func loop() {
|
||||
}
|
|
@ -24,6 +24,7 @@ dofile(MP.."/bcomp/bgenerator.lua")
|
|||
dofile(MP.."/bcomp/bscanner.lua")
|
||||
dofile(MP.."/bcomp/bsymbols.lua")
|
||||
dofile(MP.."/bcomp/bexpression.lua")
|
||||
dofile(MP.."/bcomp/bconst_expr.lua")
|
||||
dofile(MP.."/bcomp/bparser.lua")
|
||||
dofile(MP.."/bcomp/bcompiler.lua")
|
||||
dofile(MP.."/programmer/lib.lua")
|
||||
|
@ -227,4 +228,4 @@ end
|
|||
--test_lookup("test08.c")
|
||||
--compile_and_assemble("test01.c")
|
||||
--beduino_compile("test09.c")
|
||||
beduino_compile("test15.c")
|
||||
beduino_compile("test16.c")
|
||||
|
|
Loading…
Reference in New Issue