semantic: separate assignments from definitions
Variables are no longer implicitly defined
This commit is contained in:
parent
c2faff23e1
commit
49bb3f6aaa
3 changed files with 39 additions and 11 deletions
|
|
@ -6,9 +6,9 @@ from pprint import pprint
|
||||||
|
|
||||||
from . import semantic
|
from . import semantic
|
||||||
from .errors import CompilationError
|
from .errors import CompilationError
|
||||||
|
from .lexer import Lexer, Tokens
|
||||||
from .logger import rootLogger, LogLevel
|
from .logger import rootLogger, LogLevel
|
||||||
from .parser import Parser
|
from .parser import Parser
|
||||||
from .lexer import Lexer, Tokens
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -19,14 +19,17 @@ def main():
|
||||||
|
|
||||||
data = """
|
data = """
|
||||||
{
|
{
|
||||||
byte = 42;
|
let byte: uint32 = 42;
|
||||||
}
|
}
|
||||||
|
let byte: uint32;
|
||||||
|
|
||||||
2 + 8 - 1 * (byte = 3 + 5)
|
2 + 8 - 1 * (byte = 3 + 5)
|
||||||
/ (byte = 255) + byte;
|
/ (byte = 255) + byte;
|
||||||
byte = byte + byte;
|
byte = byte + byte;
|
||||||
{
|
{
|
||||||
a = byte;
|
let a: uint32 = byte;
|
||||||
}
|
}
|
||||||
|
{ let b: uint32; }
|
||||||
"""
|
"""
|
||||||
if not args.mock:
|
if not args.mock:
|
||||||
data = sys.stdin.read().strip()
|
data = sys.stdin.read().strip()
|
||||||
|
|
|
||||||
|
|
@ -370,6 +370,13 @@ class Definition(Assignment):
|
||||||
def pure(self) -> bool:
|
def pure(self) -> bool:
|
||||||
return self.value is None
|
return self.value is None
|
||||||
|
|
||||||
|
def semantic_analysis(self, context: semantic.Context):
|
||||||
|
super(Assignment, self).semantic_analysis(context)
|
||||||
|
name = self.identifier.value
|
||||||
|
variable = context.define_variable(name, type_identifier=self.type_identifier, value=self.value)
|
||||||
|
self.variable = variable
|
||||||
|
logger.debug(f"Added variable {variable} to context {context.fully_qualified_name()}")
|
||||||
|
|
||||||
|
|
||||||
Number = Float | Integer
|
Number = Float | Integer
|
||||||
Value = BinaryOperation | Number | Variable | Expression
|
Value = BinaryOperation | Number | Variable | Expression
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import abc
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from . import nodes
|
from . import nodes
|
||||||
|
from .errors import SemanticAnalysisError
|
||||||
from .logger import Logger
|
from .logger import Logger
|
||||||
from .typechecking import typecheck
|
from .typechecking import typecheck
|
||||||
|
|
||||||
|
|
@ -39,11 +40,12 @@ class Type(SymbolABC):
|
||||||
|
|
||||||
class Variable(SymbolABC):
|
class Variable(SymbolABC):
|
||||||
@typecheck
|
@typecheck
|
||||||
def __init__(self, context: Context, name: str, value: nodes.Value | None = None):
|
def __init__(self, context: Context, name: str, value: nodes.Value | None = None, typedef: Type | None = None):
|
||||||
super().__init__(context, name, value)
|
super().__init__(context, name, value)
|
||||||
|
self.type = typedef if typedef is not None else context.get_type("__unknown")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.__class__.__name__}({self.name})"
|
return f"{self.__class__.__name__}({self.name} : {self.type.fully_qualified_name()})"
|
||||||
|
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
|
|
@ -79,13 +81,29 @@ class Context:
|
||||||
def get_variable(self, name: str) -> Variable | None:
|
def get_variable(self, name: str) -> Variable | None:
|
||||||
return self._resolve_symbol("variables", name)
|
return self._resolve_symbol("variables", name)
|
||||||
|
|
||||||
def set_variable(self, name: str, value: nodes.Value) -> Variable:
|
def define_variable(self, name: str, type_identifier: nodes.Identifier, value: nodes.Value) -> Variable:
|
||||||
variable: Variable
|
|
||||||
if name in self.variables:
|
if name in self.variables:
|
||||||
|
raise SemanticAnalysisError(value.location())
|
||||||
|
|
||||||
|
typedef = self.get_type(type_identifier.value)
|
||||||
|
if typedef is None:
|
||||||
|
raise SemanticAnalysisError(location=type_identifier.location(),
|
||||||
|
message=f"Unknown type '{type_identifier.value}'")
|
||||||
|
|
||||||
|
variable = Variable(self, name, value, typedef)
|
||||||
|
|
||||||
|
self.variables[name] = variable
|
||||||
|
|
||||||
|
return variable
|
||||||
|
|
||||||
|
def set_variable(self, name: str, value: nodes.Value) -> Variable:
|
||||||
|
assert value is not None
|
||||||
|
|
||||||
|
if name not in self.variables:
|
||||||
|
raise SemanticAnalysisError(value.location(),
|
||||||
|
message=f"Can't assign a value to undeclared variable '{name}'")
|
||||||
variable = self.variables[name]
|
variable = self.variables[name]
|
||||||
variable.definitions += [value]
|
variable.definitions += [value]
|
||||||
else:
|
|
||||||
variable = Variable(self, name, value)
|
|
||||||
|
|
||||||
self.variables[name] = variable
|
self.variables[name] = variable
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue