Skip to content

Commit

Permalink
codegen: change the way inline modules are generated
Browse files Browse the repository at this point in the history
  • Loading branch information
StunxFS committed Jun 28, 2024
1 parent a60623f commit c02d7ba
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 95 deletions.
1 change: 1 addition & 0 deletions bsc/AST.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def __init__(
self.stmts = stmts
self.has_body = stmts != None
self.is_main = is_main
self.is_method = False
self.sym = None
self.pos = pos

Expand Down
6 changes: 4 additions & 2 deletions bsc/astgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ def extern_pkg(self, *nodes):
return ExternPkg(pkg_name, alias_name, pos)

def mod_decl(self, *nodes):
access_modifier = self.get_access_modifier(nodes)
pos = self.mkpos(nodes[0] or nodes[1])
access_modifier = self.get_access_modifier(nodes[0])
pos = self.mkpos(nodes[1])
name = nodes[2].name
is_inline = len(nodes) > 3
decls = []
Expand All @@ -92,6 +92,8 @@ def mod_decl(self, *nodes):
access_modifier, name, Scope(self.mod_sym.scope, True), False,
is_inline
)
if is_inline:
mod_sym.pos = pos
if not is_inline:
self.source_file_deps.append(mod_sym)
return ModDecl(access_modifier, name, is_inline, decls, pos, mod_sym)
Expand Down
56 changes: 39 additions & 17 deletions bsc/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def __init__(self, ctx):
self.ctx = ctx
self.modules = []

self.cur_file = None
self.cur_module = None
self.cur_decls = []
self.cur_fn = None
Expand All @@ -24,9 +25,18 @@ def gen_files(self, source_files):
render.render_modules()

def gen_file(self, file):
self.cur_file = file
self.cur_module = LuaModule(file.mod_sym.name)
self.gen_decls(file.decls)
self.cur_module.decls = self.cur_decls

module_fields = []
for sym in file.mod_sym.scope.syms:
if sym.access_modifier.is_public():
module_fields.append(
LuaTableField(LuaIdent(sym.name), LuaIdent(sym.name))
)
self.cur_decls.append(LuaReturn(LuaTable(module_fields)))
self.cur_module.stmts = self.cur_decls
self.modules.append(self.cur_module)
self.cur_decls = []

Expand All @@ -46,27 +56,35 @@ def gen_decl(self, decl):

def gen_mod_decl(self, decl):
if decl.is_inline:
self.cur_decls.append(LuaAssignment([LuaIdent(decl.name)], []))
old_decls = self.cur_decls

self.cur_decls = []
self.gen_decls(decl.decls)
old_decls.append(
LuaModule(decl.sym.codegen_qualname(), self.cur_decls, True)

module_fields = []
for sym in decl.sym.scope.syms:
if sym.access_modifier.is_public():
module_fields.append(
LuaTableField(LuaIdent(sym.name), LuaIdent(sym.name))
)
self.cur_decls.append(
LuaAssignment([LuaIdent(decl.name)], [LuaTable(module_fields)],
False)
)

mod_decls = self.cur_decls
self.cur_decls = old_decls
self.cur_decls.append(LuaBlock(mod_decls))
else:
self.cur_decls.append(
LuaModule(
decl.sym.codegen_qualname(), [], False,
lua_filename = decl.name
)
LuaModule(decl.sym.name, [], False, lua_filename = decl.name)
)

def gen_const_decl(self, decl):
is_local = decl.is_local
name = decl.name if is_local else decl.sym.codegen_qualname()
lua_assign = LuaAssignment([LuaIdent(name)], [self.gen_expr(decl.expr)],
is_local)
if is_local:
name = decl.name if decl.is_local else decl.sym.name
lua_assign = LuaAssignment([LuaIdent(name)], [self.gen_expr(decl.expr)])
if decl.is_local:
self.cur_block.add_stmt(lua_assign)
else:
self.cur_decls.append(lua_assign)
Expand All @@ -76,8 +94,7 @@ def gen_enum_decl(self, decl):
for i, f in enumerate(decl.fields):
fields.append(LuaTableField(LuaIdent(f.name), LuaNumberLit(str(i))))
self.cur_decls.append(
LuaAssignment([LuaIdent(decl.sym.codegen_qualname())],
[LuaTable(fields)], False)
LuaAssignment([LuaIdent(decl.sym).name], [LuaTable(fields)], False)
)
self.gen_decls(decl.decls)

Expand All @@ -86,7 +103,10 @@ def gen_fn_decl(self, decl):
args = []
for arg in decl.args:
args.append(LuaIdent(arg.name))
luafn = LuaFunction(decl.sym.codegen_qualname(), args)
luafn = LuaFunction(
decl.sym.codegen_qualname(), args,
is_associated = decl.sym.is_associated()
)
for arg in decl.args:
if arg.default_value != None:
left = LuaIdent(arg.name)
Expand Down Expand Up @@ -182,9 +202,11 @@ def gen_expr(self, expr):
return LuaBooleanLit(leftb or rightb)
return LuaBinaryExpr(left, expr.op.to_lua_op(), right)
elif isinstance(expr, Ident):
if isinstance(expr.sym, Object):
if isinstance(
expr.sym, Object
) and expr.sym.level != ObjectLevel.static:
return LuaIdent(expr.name)
if expr.sym != None: return LuaIdent(expr.sym.codegen_name())
if expr.sym != None: return LuaIdent(expr.sym.name)
return LuaIdent(expr.name)
elif isinstance(expr, BlockExpr):
old_block = self.cur_block
Expand Down
11 changes: 6 additions & 5 deletions bsc/lua_ast/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# LICENSE file.

class LuaModule:
def __init__(self, name, decls = [], is_inline = False, lua_filename = ""):
def __init__(self, name, stmts = [], is_inline = False, lua_filename = ""):
self.name = name
self.decls = decls
self.stmts = stmts.copy()
self.is_inline = is_inline
self.lua_filename = lua_filename

Expand All @@ -19,9 +19,10 @@ def __init__(self, fields):
self.fields = fields

class LuaFunction:
def __init__(self, name, args):
def __init__(self, name, args, is_associated = False):
self.name = name
self.args = args
self.is_associated = is_associated
self.block = LuaBlock()

# Statements
Expand All @@ -47,8 +48,8 @@ def __init__(self, cond, is_else, stmts):
self.stmts = stmts

class LuaBlock:
def __init__(self):
self.stmts = []
def __init__(self, stmts = []):
self.stmts = stmts.copy()

def add_stmt(self, stmt):
self.stmts.append(stmt)
Expand Down
105 changes: 48 additions & 57 deletions bsc/lua_ast/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,71 +34,26 @@ def render_module(self, module):
"-- WARNING: DO NOT MODIFY MANUALLY! YOUR CHANGES WILL BE OVERWRITTEN --\n"
)

self.writeln(f"local {module.name} = {{}} -- package\n")
self.render_decls(module.decls)
self.writeln(f"return {module.name}\n")
self.render_stmts(module.stmts)

with open(f"{BSC_OUT_DIR}/{module.name}.lua", "w") as f:
f.write(str(self.lua_file))
self.lua_file.clear()

def render_decls(self, decls):
for decl in decls:
self.render_decl(decl)

def render_decl(self, decl):
if isinstance(decl, LuaModule):
self.render_mod(decl)
elif isinstance(decl, LuaTable):
self.render_table(decl)
elif isinstance(decl, LuaAssignment):
self.render_assign_decl(decl)
elif isinstance(decl, LuaFunction):
self.render_fn_decl(decl)

def render_mod(self, decl):
if decl.is_inline:
self.writeln(f"{decl.name} = {{}} -- inline module\n")
self.render_decls(decl.decls)
self.writeln(f"-- end module `{decl.name}`\n")
else:
self.writeln(
f"{decl.name} = require(\"{BSC_OUT_DIR}.{decl.lua_filename}\") -- load module file\n"
)

def render_fn_decl(self, decl):
self.write(f"function {decl.name}(")
for i, arg in enumerate(decl.args):
self.write(arg.name)
if i < len(decl.args) - 1:
self.write(", ")
self.writeln(")")
self.indent += 1
self.render_stmts(decl.block.stmts)
self.indent -= 1
self.writeln("end\n")

def render_assign_decl(self, decl):
if decl.is_local:
self.write("local ")
for i, left in enumerate(decl.lefts):
self.render_ident(left)
if i < len(decl.lefts) - 1:
self.write(", ")
if len(decl.rights) > 0:
self.write(" = ")
for i, right in enumerate(decl.rights):
self.render_expr(right)
if i < len(decl.rights) - 1:
self.write(", ")
self.writeln()

def render_stmts(self, stmts):
for stmt in stmts:
self.render_stmt(stmt)

def render_stmt(self, stmt):
if isinstance(stmt, LuaWhile):
if isinstance(stmt, LuaModule):
self.render_mod(stmt)
elif isinstance(stmt, LuaFunction):
self.render_fn_stmt(stmt)
elif isinstance(stmt, LuaTable):
self.render_table(stmt)
elif isinstance(stmt, LuaAssignment):
self.render_assign_stmt(stmt)
elif isinstance(stmt, LuaWhile):
self.write("while ")
self.render_expr(stmt.cond)
self.writeln(" do")
Expand Down Expand Up @@ -130,22 +85,58 @@ def render_stmt(self, stmt):
self.indent += 1
self.render_stmts(stmt.stmts)
self.indent -= 1
self.writeln("end")
self.writeln("end\n")
elif isinstance(stmt, LuaAssignment):
self.render_assign_decl(stmt)
self.render_assign_stmt(stmt)
elif isinstance(stmt, LuaReturn):
self.write("return")
if stmt.expr != None:
self.write(" ")
self.render_expr(stmt.expr)
self.writeln()

def render_mod(self, stmt):
self.writeln(
f"local {stmt.name} = require(\"{BSC_OUT_DIR}.{stmt.lua_filename}\") -- load module file\n"
)

def render_fn_stmt(self, stmt):
if not stmt.is_associated:
self.write("local ")
self.write(f"function {stmt.name}(")
for i, arg in enumerate(stmt.args):
self.write(arg.name)
if i < len(stmt.args) - 1:
self.write(", ")
self.writeln(")")
self.indent += 1
self.render_stmts(stmt.block.stmts)
self.indent -= 1
self.writeln("end\n")

def render_assign_stmt(self, stmt):
if stmt.is_local: self.write("local ")
for i, left in enumerate(stmt.lefts):
self.render_ident(left)
if i < len(stmt.lefts) - 1:
self.write(", ")
if len(stmt.rights) > 0:
self.write(" = ")
for i, right in enumerate(stmt.rights):
self.render_expr(right)
if i < len(stmt.rights) - 1:
self.write(", ")
self.writeln()

def render_expr(self, expr):
if isinstance(expr, LuaParenExpr):
self.write("(")
self.render_expr(expr.expr)
self.write(")")
elif isinstance(expr, LuaTable):
if len(expr.fields) == 0:
self.writeln("{}")
return
self.writeln("{")
self.indent += 1
for i, field in enumerate(expr.fields):
Expand Down
Loading

0 comments on commit c02d7ba

Please sign in to comment.