Skip to content

Commit

Permalink
redesign of sym table
Browse files Browse the repository at this point in the history
  • Loading branch information
marsninja committed Sep 16, 2023
1 parent 442bb9f commit 003be7f
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 20 deletions.
73 changes: 60 additions & 13 deletions jaclang/jac/passes/blue/sym_tab_build_pass.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Ast build pass for Jaseci Ast."""
import jaclang.jac.absyntree as ast
from jaclang.jac.passes import Pass
from jaclang.jac.symtable import Symbol, SymbolTable
from jaclang.jac.symtable import SymbolHitType, SymbolTable


class SymTabBuildPass(Pass):
Expand All @@ -11,14 +11,20 @@ def before_pass(self) -> None:
"""Before pass."""
self.cur_sym_tab = SymbolTable()

def register_unique_name(self, name: str, typ: str, node: ast.AstNode) -> None:
"""Register unique name."""
if not self.cur_sym_tab.insert(Symbol(name, node), fresh_only=True):
original = self.cur_sym_tab.lookup(name)
self.error(
f"Name used for {typ} '{name}' already declared "
f"on line {original.decl.line if original else self.ice()}",
)
def already_declared_err(self, name: str, typ: str, original: ast.AstNode) -> None:
"""Already declared error."""
self.error(
f"Name used for {typ} '{name}' already declared on line {original.line}"
)

def resolve_ability_symtab_name(self, node: ast.Ability) -> str:
"""Resolve ability name in symbol table."""
return (
f"{node.arch_attached.parent.name.value}.{node.py_resolve_name()}"
if node.arch_attached
and isinstance(node.arch_attached.parent, ast.Architype)
else node.py_resolve_name()
)

def enter_module(self, node: ast.Module) -> None:
"""Sub objects.
Expand Down Expand Up @@ -75,7 +81,13 @@ def enter_test(self, node: ast.Test) -> None:
body: CodeBlock,
sym_tab: Optional[SymbolTable],
"""
self.register_unique_name(node.name.value, "test", node)
if collide := self.cur_sym_tab.insert(
name=node.name.value,
sym_hit=SymbolHitType.DECL,
node=node,
single=True,
):
self.already_declared_err(node.name.value, "test", collide)
self.cur_sym_tab = self.cur_sym_tab.push_scope()
node.sym_tab = self.cur_sym_tab

Expand Down Expand Up @@ -151,7 +163,13 @@ def enter_architype(self, node: ast.Architype) -> None:
body: Optional[ArchBlock],
sym_tab: Optional[SymbolTable],
"""
self.register_unique_name(node.name.value, "architype", node)
if collide := self.cur_sym_tab.insert(
name=node.name.value,
sym_hit=SymbolHitType.DECL,
node=node,
single=True,
):
self.already_declared_err(node.name.value, "architype", collide)
self.cur_sym_tab = self.cur_sym_tab.push_scope()
node.sym_tab = self.cur_sym_tab

Expand Down Expand Up @@ -211,7 +229,14 @@ def enter_ability(self, node: ast.Ability) -> None:
sym_tab: Optional[SymbolTable],
arch_attached: Optional[ArchBlock],
"""
self.register_unique_name(node.py_resolve_name(), "ability", node)
ability_name = self.resolve_ability_symtab_name(node)
if collide := self.cur_sym_tab.insert(
name=ability_name,
sym_hit=SymbolHitType.DECL,
node=node,
single=True,
):
self.already_declared_err(ability_name, "ability", collide)
self.cur_sym_tab = self.cur_sym_tab.push_scope()
node.sym_tab = self.cur_sym_tab

Expand Down Expand Up @@ -242,6 +267,22 @@ def enter_ability_def(self, node: ast.AbilityDef) -> None:
body: CodeBlock,
sym_tab: Optional[SymbolTable],
"""
ability_name = node.ability.py_resolve_name()
if node.target:
owner = node.target.names[-1]
if not isinstance(owner, ast.ArchRef):
self.error("Expected reference to Architype!")
owner = ""
else:
owner = owner.py_resolve_name()
ability_name = f"{owner}.{ability_name}"
if collide := self.cur_sym_tab.insert(
name=ability_name,
sym_hit=SymbolHitType.DEFN,
node=node,
single=True,
):
self.already_declared_err(ability_name, "ability def", collide)
node.sym_tab = self.cur_sym_tab

def enter_event_signature(self, node: ast.EventSignature) -> None:
Expand Down Expand Up @@ -301,7 +342,13 @@ def enter_enum(self, node: ast.Enum) -> None:
body: Optional['EnumBlock'],
sym_tab: Optional[SymbolTable],
"""
self.register_unique_name(node.name.value, "enum", node)
if collide := self.cur_sym_tab.insert(
name=node.name.value,
sym_hit=SymbolHitType.DECL,
node=node,
single=True,
):
self.already_declared_err(node.name.value, "enum", collide)
self.cur_sym_tab = self.cur_sym_tab.push_scope()
node.sym_tab = self.cur_sym_tab

Expand Down
55 changes: 48 additions & 7 deletions jaclang/jac/symtable.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
"""Jac Symbol Table."""
from __future__ import annotations

from enum import Enum
from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
import jaclang.jac.absyntree as ast


class SymbolHitType(Enum):
"""Symbol types."""

DECL = "decl"
DEFN = "defn"
USE = "use"


class Symbol:
"""Symbol."""

def __init__(
self,
name: str,
decl: ast.AstNode,
typ: Optional[type] = None,
decl: Optional[ast.AstNode] = None,
defn: Optional[list[ast.AstNode]] = None,
uses: Optional[list[ast.AstNode]] = None,
) -> None:
Expand Down Expand Up @@ -42,12 +51,44 @@ def lookup(self, name: str, deep: bool = True) -> Optional[Symbol]:
return self.parent.lookup(name, deep)
return None

def insert(self, sym: Symbol, fresh_only: bool = False) -> bool:
"""Set a variable in the symbol table."""
if fresh_only and sym.name in self.tab:
return False
self.tab[sym.name] = sym
return True
def insert(
self,
name: str,
sym_hit: SymbolHitType,
node: ast.AstNode,
single: bool = False,
) -> Optional[ast.AstNode]:
"""Set a variable in the symbol table.
Returns original symbol single check fails.
"""
if single:
if (
sym_hit == SymbolHitType.DECL
and name in self.tab
and self.tab[name].decl
):
return self.tab[name].decl
elif (
sym_hit == SymbolHitType.DEFN
and name in self.tab
and len(self.tab[name].defn)
):
return self.tab[name].defn[-1]
elif (
sym_hit == SymbolHitType.USE
and name in self.tab
and len(self.tab[name].uses)
):
return self.tab[name].uses[-1]
if name not in self.tab:
self.tab[name] = Symbol(name=name)
if sym_hit == SymbolHitType.DECL:
self.tab[name].decl = node
elif sym_hit == SymbolHitType.DEFN:
self.tab[name].defn.append(node)
elif sym_hit == SymbolHitType.USE:
self.tab[name].uses.append(node)

def push_scope(self) -> SymbolTable:
"""Push a new scope onto the symbol table."""
Expand Down

0 comments on commit 003be7f

Please sign in to comment.