Skip to content

Commit

Permalink
bsc: sort imported modules by dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
StunxFS committed Jun 11, 2024
1 parent 530ba7a commit 244592d
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 14 deletions.
3 changes: 2 additions & 1 deletion bsc/AST.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ def __str__(self):
return f"Pos(file='{self.file}', line={self.line}, column={self.column}, len={self.len}, pos={self.pos})"

class SourceFile:
def __init__(self, file, decls, mod_sym):
def __init__(self, file, decls, mod_sym, deps = []):
self.file = file
self.mod_sym = mod_sym
self.decls = decls
self.deps = deps

# Declarations

Expand Down
46 changes: 43 additions & 3 deletions bsc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import os

from bsc import sym, report
from bsc.AST import BasicType
from bsc import report, utils
from bsc.AST import BasicType, ModDecl
from bsc.prefs import Prefs
from bsc.astgen import AstGen
from bsc.sema import Sema
Expand Down Expand Up @@ -72,10 +72,11 @@ def compile(self):
def import_modules(self):
for sf in self.source_files:
self.import_modules_from_decls(sf.mod_sym, sf.decls)
self.resolve_deps()

def import_modules_from_decls(self, parent, decls):
for decl in decls:
if isinstance(decl, AST.ModDecl):
if isinstance(decl, ModDecl):
if decl.is_inline:
self.import_modules_from_decls(parent, decl.decls)
else:
Expand All @@ -97,10 +98,49 @@ def import_module(self, parent, decl):
else:
report.error(f"module `{decl.name}` not found", decl.pos)

def resolve_deps(self):
g = self.module_graph()
g_resolved = g.resolve()
self.vlog(
f"-----= resolved dependencies graph =-----\n{g_resolved.display()}"
)
self.vlog("-----------------------------------------")
cycles = g_resolved.display_cycles()
if len(cycles) > 1:
utils.error(
f"import cycle detected between the following modules:\n{cycles}"
)
self.vlog("----------= imported modules =-----------")
for node in g_resolved.nodes:
self.vlog(f"> {node.name}")
self.vlog("-----------------------------------------")
source_files = self.source_files
self.source_files = []
for node in g_resolved.nodes:
for sf in source_files:
if sf.mod_sym.name == node.name:
self.source_files.append(sf)
self.vlog("module dependencies resolved...")

def module_graph(self):
g = utils.DepGraph()
for sf in self.source_files:
deps = []
for dep in sf.deps:
dep.parent = sf.mod_sym
deps.append(dep.qualname())
g.add(sf.mod_sym.qualname(), deps)
return g

def parse_input(self):
self.parse_file(self.prefs.pkg_name, self.prefs.input, is_pkg = True)

def parse_file(self, mod_name, file, is_pkg = False, parent_mod = None):
self.source_files.append(
self.astgen.parse_file(mod_name, file, is_pkg, parent_mod)
)

def vlog(self, s):
if self.prefs.is_verbose:
bsc_log = utils.bold(utils.green("[bsc-log]"))
print(f"{bsc_log} {s}")
17 changes: 10 additions & 7 deletions bsc/astgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def __init__(self, ctx):
self.ctx = ctx
self.file = ""
self.source_file = None
self.source_file_deps = []
self.mod_sym = None

def parse_file(self, mod_name, file, is_pkg = False, parent_mod = None):
Expand All @@ -30,7 +31,7 @@ def parse_file(self, mod_name, file, is_pkg = False, parent_mod = None):
)
self.source_file = SourceFile(
self.file, self.transform(bs_parser.parse(open(file).read())),
self.mod_sym
self.mod_sym, deps = self.source_file_deps
)
try:
if is_pkg:
Expand All @@ -40,6 +41,7 @@ def parse_file(self, mod_name, file, is_pkg = False, parent_mod = None):
parent_mod.scope.add_sym(self.source_file.mod_sym)
except utils.CompilerError as e:
utils.error(e.args[0])
self.source_file_deps = []
return self.source_file

def mkpos(self, token):
Expand All @@ -61,19 +63,20 @@ def extern_pkg(self, *nodes):
def mod_decl(self, *nodes):
access_modifier = self.get_access_modifier(nodes)
pos = self.mkpos(nodes[0] or nodes[1])
name = nodes[2].name
is_inline = nodes[3] != None
decls = []
if is_inline:
decls = list(nodes[4:-1])
if not is_inline:
else:
pos += nodes[2].pos
mod_sym = Module(
access_modifier, nodes[2].name, Scope(self.mod_sym.scope, True),
False, is_inline
)
return ModDecl(
access_modifier, nodes[2].name, is_inline, decls, pos, mod_sym
access_modifier, name, Scope(self.mod_sym.scope, True), False,
is_inline
)
if not is_inline:
self.source_file_deps.append(mod_sym)
return ModDecl(access_modifier, name, is_inline, decls, pos, mod_sym)

def enum_decl(self, *nodes):
pos = self.mkpos(nodes[1])
Expand Down
10 changes: 8 additions & 2 deletions bsc/prefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,30 @@ def __init__(self):
self.is_library = False

self.pkg_name = ""
self.is_verbose = False

def parse_args(self):
parser = argparse.ArgumentParser(
prog = 'bsc', description = 'The BlueScript compiler'
)
parser.add_argument('INPUT', help = "the input file", nargs = 1)
parser.add_argument(
'--pkg-name', action = 'store', metavar = 'pkg_name', help =
'specifies the name of the package being compiled (by default the name of the given file or directory will be used)'
)
parser.add_argument(
'--lib', action = 'store_true',
help = 'specifies whether the input is a library or not'
)
parser.add_argument(
'--pkg-name', action = 'store', metavar = 'pkg_name', help =
'specifies the name of the package being compiled (by default the name of the given file or directory will be used)'
'-v', '--verbose', action = 'store_true',
help = 'Enable verbosity in the compiler while compiling'
)
args = parser.parse_args()

self.is_library = args.lib
self.pkg_name = args.pkg_name or ""
self.is_verbose = args.verbose

# check input file
self.input = args.INPUT[0]
Expand Down
1 change: 0 additions & 1 deletion bsc/sema.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ def check_mod_decl(self, decl):
old_sym = self.cur_sym
old_mod = self.cur_mod
if self.first_pass:
decl.sym.parent = self.cur_sym
if decl.is_inline:
self.add_sym(decl.sym, decl.pos)
self.cur_mod = decl.sym
Expand Down

0 comments on commit 244592d

Please sign in to comment.