Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
alessiostalla committed Sep 9, 2022
2 parents 94b8b7e + 6636110 commit 76352ca
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 170 deletions.
33 changes: 8 additions & 25 deletions pylasu/model/naming.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass, field
from typing import TypeVar, Generic, Optional, List
from typing import TypeVar, Generic, Optional, List, Dict


@dataclass
Expand Down Expand Up @@ -57,29 +57,12 @@ class Symbol(PossiblyNamed):

@dataclass
class Scope:
# local symbols
symbols: List[Symbol] = field(default_factory=list)
# parent scope
symbols: Dict[str, List[Symbol]] = field(default_factory=list)
parent: Optional['Scope'] = field(default=None)

# retrieve symbols from name, type or both
def lookup(self, symbol_name: str = None, symbol_type: type = Symbol) -> List[Symbol]:
# retrieve symbols from current scope
local_symbols: List[Symbol] = self.__symbols(symbol_name, symbol_type)
# retrieve symbols from upper scopes
upper_symbols: List[Symbol] = self.parent.lookup(symbol_name, symbol_type) if self.parent else []
# concatenate symbols with locals first
return local_symbols + upper_symbols

def __symbols(self, symbol_name: str = None, symbol_type: type = Symbol):
def __check_symbol_name(symbol: Symbol) -> bool:
# compare symbol name, ignore test if undefined (True)
return symbol.name == symbol_name if symbol_name else True

def __check_symbol_type(symbol: Symbol) -> bool:
# compare symbol type, ignore test if undefined (True)
return isinstance(symbol, symbol_type) if symbol_type else True

# retrieve symbols from name, type or both
return [symbol for symbol in self.symbols if
__check_symbol_name(symbol) and __check_symbol_type(symbol)]
def lookup(self, symbol_name: str, symbol_type: type = Symbol) -> Optional[Symbol]:
return next((symbol for symbol in self.symbols.get(symbol_name, []) if isinstance(symbol, symbol_type)),
self.parent.lookup(symbol_name, symbol_type) if self.parent is not None else None)

def add(self, symbol: Symbol):
self.symbols[symbol.name] = self.symbols.get(symbol.name, []) + [symbol]
201 changes: 56 additions & 145 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,148 +74,59 @@ def test_node_properties(self):
with self.assertRaises(StopIteration):
next(n for n, _ in node.properties if n == "origin")

def test_scope_lookup_symbol_by_name_found(self):
local_symbol_0 = SomeSymbol(name="a", index=0)
local_symbol_1 = SomeSymbol(name="a", index=1)
upper_symbol_0 = SomeSymbol(name="b", index=2)
upper_symbol_1 = SomeSymbol(name="a", index=3)
root_symbol_0 = SomeSymbol(name="a", index=4)
root_symbol_1 = SomeSymbol(name="b", index=5)
scope = Scope(symbols=[local_symbol_0, local_symbol_1],
parent=Scope(symbols=[upper_symbol_0, upper_symbol_1],
parent=Scope(symbols=[root_symbol_0, root_symbol_1],
parent=None)))
# retrieve all symbols with name 'a'
result = scope.lookup("a")
self.assertEquals(len(result), 4)
self.assertEquals(result[0], local_symbol_0)
self.assertEquals(result[1], local_symbol_1)
self.assertEquals(result[2], upper_symbol_1)
self.assertEquals(result[3], root_symbol_0)

def test_scope_lookup_symbol_by_name_not_found(self):
local_symbol = SomeSymbol(name="a", index=0)
upper_symbol = SomeSymbol(name="b", index=1)
root_symbol = SomeSymbol(name="c", index=2)
scope = Scope(symbols=[local_symbol],
parent=Scope(symbols=[upper_symbol],
parent=Scope(symbols=[root_symbol],
parent=None)))
# retrieve all symbols with name 'd'
result = scope.lookup("d")
self.assertEquals(len(result), 0)

def test_scope_lookup_symbol_by_type_found(self):
local_symbol_0 = Symbol(name="a")
local_symbol_1 = SomeSymbol(name="b", index=0)
upper_symbol_0 = SomeSymbol(name="a", index=1)
upper_symbol_1 = Symbol(name="a")
root_symbol_0 = Symbol(name="a")
root_symbol_1 = SomeSymbol(name="b", index=2)
scope = Scope(symbols=[local_symbol_0, local_symbol_1],
parent=Scope(symbols=[upper_symbol_0, upper_symbol_1],
parent=Scope(symbols=[root_symbol_0, root_symbol_1],
parent=None)))
# retrieve all symbols of type SomeSymbol
result = scope.lookup(symbol_type=SomeSymbol)
self.assertEquals(len(result), 3)
self.assertEquals(result[0], local_symbol_1)
self.assertEquals(result[1], upper_symbol_0)
self.assertEquals(result[2], root_symbol_1)
# retrieve all symbols of type Symbol
result = scope.lookup(symbol_type=Symbol)
self.assertEquals(len(result), 6)
self.assertEquals(result[0], local_symbol_0)
self.assertEquals(result[1], local_symbol_1)
self.assertEquals(result[2], upper_symbol_0)
self.assertEquals(result[3], upper_symbol_1)
self.assertEquals(result[4], root_symbol_0)
self.assertEquals(result[5], root_symbol_1)

def test_scope_lookup_symbol_by_type_not_found(self):
local_symbol = Symbol(name="a")
upper_symbol = Symbol(name="b")
root_symbol = Symbol(name="c")
scope = Scope(symbols=[local_symbol],
parent=Scope(symbols=[upper_symbol],
parent=Scope(symbols=[root_symbol],
parent=None)))
# retrieve all symbols of type SomeSymbol
result = scope.lookup(symbol_type=SomeSymbol)
self.assertEquals(len(result), 0)

# retrieve all symbols of type Symbol
result = scope.lookup(symbol_type=Symbol)
self.assertEquals(len(result), 3)
self.assertEquals(result[0], local_symbol)
self.assertEquals(result[1], upper_symbol)
self.assertEquals(result[2], root_symbol)

def test_scope_lookup_symbol_by_name_and_type_found(self):
local_symbol_0 = Symbol(name="a")
local_symbol_1 = SomeSymbol(name="b", index=0)
upper_symbol_0 = SomeSymbol(name="a", index=1)
upper_symbol_1 = Symbol(name="b")
root_symbol_0 = Symbol(name="a")
root_symbol_1 = SomeSymbol(name="b", index=2)
scope = Scope(symbols=[local_symbol_0, local_symbol_1],
parent=Scope(symbols=[upper_symbol_0, upper_symbol_1],
parent=Scope(symbols=[root_symbol_0, root_symbol_1],
parent=None)))
# retrieve all symbols of type SomeSymbol with name 'a'
result = scope.lookup(symbol_name="a", symbol_type=SomeSymbol)
self.assertEquals(len(result), 1)
self.assertEquals(result[0], upper_symbol_0)
# retrieve all symbols of type SomeSymbol with name 'b'
result = scope.lookup(symbol_name="b", symbol_type=SomeSymbol)
self.assertEquals(len(result), 2)
self.assertEquals(result[0], local_symbol_1)
self.assertEquals(result[1], root_symbol_1)

def test_scope_lookup_symbol_by_name_and_type_not_found(self):
local_symbol_0 = Symbol(name="a")
local_symbol_1 = SomeSymbol(name="b", index=0)
upper_symbol_0 = SomeSymbol(name="a", index=1)
upper_symbol_1 = Symbol(name="b")
root_symbol_0 = Symbol(name="a")
root_symbol_1 = SomeSymbol(name="b", index=2)
scope = Scope(symbols=[local_symbol_0, local_symbol_1],
parent=Scope(symbols=[upper_symbol_0, upper_symbol_1],
parent=Scope(symbols=[root_symbol_0, root_symbol_1],
parent=None)))
# retrieve all symbols of type SomeSymbol with name 'c'
result = scope.lookup(symbol_name="c", symbol_type=SomeSymbol)
self.assertEquals(len(result), 0)
# retrieve all symbols of type AnotherSymbol with name 'a'
result = scope.lookup(symbol_name="a", symbol_type=AnotherSymbol)
self.assertEquals(len(result), 0)

def test_scope_lookup_with_default_arguments(self):
local_symbol_0 = Symbol(name="a")
local_symbol_1 = SomeSymbol(name="b", index=0)
upper_symbol_0 = SomeSymbol(name="a", index=1)
upper_symbol_1 = Symbol(name="b")
root_symbol_0 = Symbol(name="a")
root_symbol_1 = SomeSymbol(name="b", index=2)
scope = Scope(symbols=[local_symbol_0, local_symbol_1],
parent=Scope(symbols=[upper_symbol_0, upper_symbol_1],
parent=Scope(symbols=[root_symbol_0, root_symbol_1],
parent=None)))
# retrieve all symbols of type Symbol with name None
result = scope.lookup(symbol_name=None, symbol_type=Symbol)
self.assertEquals(len(result), 6)
self.assertEquals(result[0], local_symbol_0)
self.assertEquals(result[1], local_symbol_1)
self.assertEquals(result[2], upper_symbol_0)
self.assertEquals(result[3], upper_symbol_1)
self.assertEquals(result[4], root_symbol_0)
self.assertEquals(result[5], root_symbol_1)
# retrieve all symbols of type Symbol with name ''
result = scope.lookup(symbol_name='', symbol_type=Symbol)
self.assertEquals(len(result), 6)
self.assertEquals(result[0], local_symbol_0)
self.assertEquals(result[1], local_symbol_1)
self.assertEquals(result[2], upper_symbol_0)
self.assertEquals(result[3], upper_symbol_1)
self.assertEquals(result[4], root_symbol_0)
self.assertEquals(result[5], root_symbol_1)
def test_scope_lookup_0(self):
"""Symbol found in local scope with name and default type"""
local_symbol = SomeSymbol(name='a', index=0)
scope = Scope(symbols={'a': [local_symbol]}, parent=Scope(symbols={'a': [SomeSymbol(name='a', index=1)]}))
result = scope.lookup(symbol_name='a')
self.assertEquals(result, local_symbol)
self.assertIsInstance(result, Symbol)

def test_scope_lookup_1(self):
"""Symbol found in upper scope with name and default type"""
upper_symbol = SomeSymbol(name='a', index=0)
scope = Scope(symbols={'b': [SomeSymbol(name='b', index=0)]}, parent=Scope(symbols={'a': [upper_symbol]}))
result = scope.lookup(symbol_name='a')
self.assertEquals(result, upper_symbol)
self.assertIsInstance(result, Symbol)

def test_scope_lookup_2(self):
"""Symbol not found with name and default type"""
scope = Scope(symbols={'b': [SomeSymbol(name='b', index=0)]},
parent=Scope(symbols={'b': [SomeSymbol(name='b', index=1)]}))
result = scope.lookup(symbol_name='a')
self.assertIsNone(result)

def test_scope_lookup_3(self):
"""Symbol found in local scope with name and type"""
pass

def test_scope_lookup_4(self):
"""Symbol found in upper scope with name and type"""
upper_symbol = SomeSymbol(name='a', index=0)
scope = Scope(symbols={'b': [SomeSymbol(name='b', index=0)]}, parent=Scope(symbols={'a': [upper_symbol]}))
result = scope.lookup(symbol_name='a', symbol_type=SomeSymbol)
self.assertEquals(result, upper_symbol)
self.assertIsInstance(result, SomeSymbol)

def test_scope_lookup_5(self):
"""Symbol found in upper scope with name and type (local with different type)"""
upper_symbol = SomeSymbol(name='a', index=0)
scope = Scope(symbols={'a': [AnotherSymbol(name='a', index=0)]}, parent=Scope(symbols={'a': [upper_symbol]}))
result = scope.lookup(symbol_name='a', symbol_type=SomeSymbol)
self.assertEquals(result, upper_symbol)
self.assertIsInstance(result, SomeSymbol)

def test_scope_lookup_6(self):
"""Symbol not found with name and type (different name)"""
scope = Scope(symbols={'b': [SomeSymbol(name='b', index=0)]},
parent=Scope(symbols={'b': [SomeSymbol(name='b', index=1)]}))
result = scope.lookup(symbol_name='a', symbol_type=SomeSymbol)
self.assertIsNone(result)

def test_scope_lookup_7(self):
"""Symbol not found with name and type (different type)"""
scope = Scope(symbols={'a': [SomeSymbol(name='a', index=0)]},
parent=Scope(symbols={'a': [SomeSymbol(name='a', index=1)]}))
result = scope.lookup(symbol_name='a', symbol_type=AnotherSymbol)
self.assertIsNone(result)

0 comments on commit 76352ca

Please sign in to comment.