Skip to content

Commit

Permalink
#19 [program] added MetaTable and used it
Browse files Browse the repository at this point in the history
  • Loading branch information
vityaman committed Feb 9, 2024
1 parent 1e370c1 commit 01bdc9b
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 44 deletions.
1 change: 1 addition & 0 deletions sleepy/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .error import SleepyError
from .meta_table import UID, Identifiable, MetaTable
from .source_location import SourceLocation
30 changes: 30 additions & 0 deletions sleepy/core/meta_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from abc import ABC, abstractproperty
from typing import Generic, NewType, TypeVar

UID = NewType("UID", int)

T = TypeVar("T")


class Identifiable(ABC):
@abstractproperty
def uid(self) -> UID:
raise NotImplementedError


class MetaTable(Generic[T]):
def __init__(self) -> None:
self.entries: dict[UID, T] = {}

def __getitem__(self, key: Identifiable) -> T:
try:
return self.entries[key.uid]
except KeyError as e:
e.add_note(f"key: {key!r}")
raise

def __setitem__(self, key: Identifiable, value: T) -> None:
if key.uid in self.entries:
message = f"can't assign {value}, to key with id {key.uid}: {key!r}"
raise KeyError(message)
self.entries[key.uid] = value
1 change: 0 additions & 1 deletion sleepy/program/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
Program,
ProgramNode,
Symbol,
SymbolId,
)
from .unit import ProgramUnit
from .visitor import Visitor
10 changes: 6 additions & 4 deletions sleepy/program/bindings.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from abc import ABC, abstractmethod
from typing import override

from sleepy.core import MetaTable

from .representation import Expression, Symbol


Expand All @@ -17,14 +19,14 @@ def resolve(self, symbol: Symbol) -> Expression:
class BasicBindings(Bindings):
def __init__(
self,
expressions: dict[int, Expression] | None = None,
expressions: MetaTable[Expression] | None = None,
) -> None:
self.expressions = expressions or {}
self.expressions = expressions or MetaTable()

@override
def bind(self, symbol: Symbol, expression: Expression) -> None:
self.expressions[symbol.uid] = expression
self.expressions[symbol] = expression

@override
def resolve(self, symbol: Symbol) -> Expression:
return self.expressions[symbol.uid]
return self.expressions[symbol]
6 changes: 2 additions & 4 deletions sleepy/program/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,5 @@ def __init__(self) -> None:
self.namespace = LocalNamespace()
self.bindings = BasicBindings()
for intrinsic in intrinsics:
self.bindings.bind(
self.namespace.define(intrinsic.name),
intrinsic,
)
defined = self.namespace.define(intrinsic.name)
self.bindings.bind(defined, intrinsic)
19 changes: 19 additions & 0 deletions sleepy/program/exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from sleepy.core import SleepyError


class SemanticError(SleepyError):
pass


class NamespaceError(SleepyError):
pass


class DefinitionError(NamespaceError):
def __init__(self, name: str, reason: str) -> None:
super().__init__(f"failed to define a name {name}: {reason}")


class NameNotFoundError(NamespaceError):
def __init__(self, name: str) -> None:
super().__init__(f"failed to resolve a name {name}: not found")
21 changes: 1 addition & 20 deletions sleepy/program/namespace.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,10 @@
from abc import ABC, abstractmethod
from typing import override

from sleepy.core import SleepyError

from .exception import DefinitionError, NameNotFoundError
from .representation import Symbol


class NamespaceError(SleepyError):
pass


class DefinitionError(NamespaceError):
def __init__(self, name: str, reason: str) -> None:
self.name = name
super().__init__(f"Failed to define a name {name}: {reason}")


class NameNotFoundError(NamespaceError):
def __init__(self, name: str) -> None:
self.name = name
super().__init__(
f"Failed to resolve a name {name}: not found",
)


class Namespace(ABC):
@abstractmethod
def resolved(self, name: str) -> Symbol:
Expand Down
10 changes: 6 additions & 4 deletions sleepy/program/representation.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from dataclasses import dataclass
from typing import override

SymbolId = int
from sleepy.core import UID, Identifiable


class ProgramNode:
class ProgramNode(Identifiable):
@property
def uid(self) -> SymbolId:
return id(self)
@override
def uid(self) -> UID:
return UID(id(self))


class Expression(ProgramNode):
Expand Down
12 changes: 4 additions & 8 deletions sleepy/syntax/s2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ def visit_conditional(self, tree: IfExpressionAST) -> Conditional:
@override
def visit_application(self, tree: ApplicationAST) -> ProgramNode:
return Application(
invokable=self.visit_expression(
tree.invokable.expression,
),
invokable=self.visit_expression(tree.invokable.expression),
args=[self.visit_expression(arg) for arg in tree.args.expressions],
)

Expand All @@ -81,10 +79,7 @@ def visit_lambda(self, tree: LambdaAST) -> Closure:
self.bindings.bind(parameter.name, parameter)

closure = Closure(parameters, statements=[])
self.bindings.bind(
self.namespace.define(Symbol("self")),
closure,
)
self.bindings.bind(self.namespace.define(Symbol("self")), closure)

closure.statements = [
self.visit_expression(expression)
Expand All @@ -103,7 +98,8 @@ def visit_kind(self, tree: KindAST) -> Kind:
match tree.name.name:
case "int":
return Kind("int")
raise NotImplementedError
case _:
raise NotImplementedError

@override
def visit_integer(self, tree: IntegerAST) -> Integer:
Expand Down
8 changes: 5 additions & 3 deletions sleepy/tafka/emit.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.abc import Generator
from typing import override
from typing import TYPE_CHECKING, override

from sleepy.program import (
Application,
Expand All @@ -11,7 +11,6 @@
Kind,
Program,
Symbol,
SymbolId,
Visitor,
)
from sleepy.program.unit import ProgramUnit
Expand Down Expand Up @@ -40,6 +39,9 @@
from sleepy.tafka.representation import Kind as TafKind
from sleepy.tafka.representation.rvalue import And, Invokation, Or

if TYPE_CHECKING:
from sleepy.core import UID

UniqueNameSequence = Generator[str, None, None]


Expand All @@ -52,7 +54,7 @@ def __init__(self, unit: ProgramUnit) -> None:
self.var_names = map(str, range(10000000))
self.lbl_names = map(str, range(10000000))

self.vars: dict[SymbolId, Var] = {}
self.vars: dict[UID, Var] = {}
self.procedures: list[Procedure] = []

self.current_block = self.main
Expand Down

0 comments on commit 01bdc9b

Please sign in to comment.