semantic: separate assignments from definitions

Variables are no longer implicitly defined
This commit is contained in:
Antoine Viallon 2023-05-23 00:57:31 +02:00
parent c2faff23e1
commit 49bb3f6aaa
Signed by: aviallon
GPG key ID: D126B13AB555E16F
3 changed files with 39 additions and 11 deletions

View file

@ -6,9 +6,9 @@ from pprint import pprint
from . import semantic
from .errors import CompilationError
from .lexer import Lexer, Tokens
from .logger import rootLogger, LogLevel
from .parser import Parser
from .lexer import Lexer, Tokens
def main():
@ -19,14 +19,17 @@ def main():
data = """
{
byte = 42;
let byte: uint32 = 42;
}
let byte: uint32;
2 + 8 - 1 * (byte = 3 + 5)
/ (byte = 255) + byte;
byte = byte + byte;
{
a = byte;
let a: uint32 = byte;
}
{ let b: uint32; }
"""
if not args.mock:
data = sys.stdin.read().strip()

View file

@ -370,6 +370,13 @@ class Definition(Assignment):
def pure(self) -> bool:
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
Value = BinaryOperation | Number | Variable | Expression

View file

@ -4,6 +4,7 @@ import abc
from typing import Literal
from . import nodes
from .errors import SemanticAnalysisError
from .logger import Logger
from .typechecking import typecheck
@ -39,11 +40,12 @@ class Type(SymbolABC):
class Variable(SymbolABC):
@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)
self.type = typedef if typedef is not None else context.get_type("__unknown")
def __str__(self):
return f"{self.__class__.__name__}({self.name})"
return f"{self.__class__.__name__}({self.name} : {self.type.fully_qualified_name()})"
class Context:
@ -79,13 +81,29 @@ class Context:
def get_variable(self, name: str) -> Variable | None:
return self._resolve_symbol("variables", name)
def set_variable(self, name: str, value: nodes.Value) -> Variable:
variable: Variable
def define_variable(self, name: str, type_identifier: nodes.Identifier, value: nodes.Value) -> Variable:
if name in self.variables:
variable = self.variables[name]
variable.definitions += [value]
else:
variable = Variable(self, name, value)
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.definitions += [value]
self.variables[name] = variable