Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request boriel-basic#626 from boriel/feature/refactorize_s…
Browse files Browse the repository at this point in the history
…ymbols_to_use_base_ID

refact: subclass FUNCTION from ID
  • Loading branch information
boriel committed Oct 23, 2022
2 parents a010ca2 + a1c14fb commit 33c1ad6
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 17 deletions.
10 changes: 4 additions & 6 deletions src/api/symboltable/symboltable.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,6 @@ def declare(self, id_: str, lineno: int, entry) -> Optional[SymbolVAR]:
if isinstance(entry, symbols.TYPE):
return entry # If it's a type declaration, we're done

# HINT: The following should be done by the respective callers!
# entry.callable = None # True if function, strings or arrays
# entry.class_ = None # TODO: important

entry.mangled = self.make_child_namespace(self.current_namespace, entry.name) # Mangled name
entry.type_ = type_ # type_ now reflects entry sigil (i.e. a$ => 'string' type) if any
entry.scopeRef = self.current_scope
Expand All @@ -144,7 +140,9 @@ def make_child_namespace(parent_namespace: str, child_namespace: str) -> str:
# -------------------------------------------------------------------------
# Symbol Table Checks
# -------------------------------------------------------------------------
def check_is_declared(self, id_: str, lineno: int, classname="identifier", scope=None, show_error=True) -> bool:
def check_is_declared(
self, id_: str, lineno: int, classname: str = "identifier", scope=None, show_error=True
) -> bool:
"""Checks if the given id is already defined in any scope
or raises a Syntax Error.
Expand Down Expand Up @@ -713,7 +711,7 @@ def declare_array(self, id_: str, lineno: int, type_, bounds, default_value=None
)
return entry

def declare_func(self, id_: str, lineno: int, type_=None, class_=CLASS.function):
def declare_func(self, id_: str, lineno: int, type_=None, class_=CLASS.function) -> Optional[symbols.FUNCTION]:
"""Declares a function in the current scope.
Checks whether the id exist or not (error if exists).
And creates the entry at the symbol table.
Expand Down
6 changes: 5 additions & 1 deletion src/arch/z80/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,11 @@ def visit_FUNCTION(self, node):
elif local_var.class_ == CLASS.const or local_var.scope == SCOPE.parameter:
continue
else: # Local vars always defaults to 0, so if 0 we do nothing
if local_var.default_value is not None and local_var.default_value != 0:
if (
not isinstance(local_var, symbols.FUNCTION)
and local_var.default_value is not None
and local_var.default_value != 0
):
if isinstance(local_var.default_value, symbols.CONST) and local_var.default_value.token == "CONST":
self.ic_lvarx(local_var.type_, local_var.offset, [self.traverse_const(local_var.default_value)])
else:
Expand Down
31 changes: 23 additions & 8 deletions src/symbols/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,42 @@

from src.api.constants import CLASS, CONVENTION
from src.symbols.block import SymbolBLOCK
from src.symbols.id_ import SymbolID
from src.symbols.paramlist import SymbolPARAMLIST
from src.symbols.var import SymbolVAR
from src.symbols.type_ import SymbolTYPE


class SymbolFUNCTION(SymbolVAR):
class SymbolFUNCTION(SymbolID):
"""This class expands VAR top denote Function declarations"""

local_symbol_table = None
convention: CONVENTION

def __init__(self, varname, lineno, offset=None, type_=None, class_=CLASS.unknown):
super().__init__(varname, lineno, offset, type_=type_, class_=class_)
callable: bool
forwarded: bool

def __init__(
self,
name: str,
lineno: int,
filename: str = None,
type_: Optional[SymbolTYPE] = None,
class_: CLASS = CLASS.unknown,
):
super().__init__(name=name, lineno=lineno, filename=filename, type_=type_)
assert class_ in {CLASS.unknown, CLASS.function, CLASS.sub}
self._class = class_
self.reset()

def reset(self, lineno=None, offset=None, type_=None):
def reset(self, lineno=None, type_=None):
"""This is called when we need to reinitialize the instance state"""
self.lineno = self.lineno if lineno is None else lineno
self.type_ = self.type_ if type_ is None else type_
self.offset = self.offset if offset is None else offset

self.callable = True
self.params = SymbolPARAMLIST()
self.body = SymbolBLOCK()
self.local_symbol_table = None
self.convention = CONVENTION.unknown
self.forwarded = False # True if declared (with DECLARE) in advance (functions or subs)

@property
def params(self) -> SymbolPARAMLIST:
Expand Down Expand Up @@ -81,3 +92,7 @@ def body(self, value: Optional[SymbolBLOCK]):

def __repr__(self):
return f"FUNC:{self.name}"

@property
def t(self):
return self.mangled
3 changes: 1 addition & 2 deletions src/symbols/var.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,14 @@ class SymbolVAR(SymbolID):

def __init__(self, varname: str, lineno: int, offset=None, type_=None, class_: CLASS = CLASS.unknown):
super().__init__(name=varname, lineno=lineno, filename=global_.FILENAME, type_=type_)

assert class_ in {CLASS.unknown, CLASS.const, CLASS.var, CLASS.array}
self.class_ = class_ # variable "class": var, label, function, etc. TODO: should be CLASS.var
self.offset = offset # If local variable or parameter, +/- offset from top of the stack
self.default_value = None # If defined, variable will be initialized with this value (Arrays = List of Bytes)
self.byref = False # By default, it's a global var
self.alias = None # If not None, this var is an alias of another
self.aliased_by: List[Symbol] = [] # Which variables are an alias of this one
self.callable = None # For functions, subs, arrays and strings this will be True
self.forwarded = False # True if declared (with DECLARE) in advance (functions or subs)

@property
def byref(self):
Expand Down

0 comments on commit 33c1ad6

Please sign in to comment.