Started code generation
This commit is contained in:
parent
b950ff80a2
commit
52225d49df
|
@ -0,0 +1,21 @@
|
||||||
|
// Kyler Olsen
|
||||||
|
// Source Code Test 3
|
||||||
|
// Fibonacci
|
||||||
|
// DuoDeca-Script Test
|
||||||
|
|
||||||
|
fn unused_func() -> int {unused_func = 0;}
|
||||||
|
|
||||||
|
fn main() -> int {
|
||||||
|
main = 0;
|
||||||
|
let a: unsigned = 0;
|
||||||
|
let b: unsigned = 0;
|
||||||
|
let c: unsigned = 0;
|
||||||
|
let out: @unsigned = 0x7FD;
|
||||||
|
|
||||||
|
while (True) {
|
||||||
|
$out = a;
|
||||||
|
c = b;
|
||||||
|
b = a;
|
||||||
|
a = b + c;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
# Kyler Olsen
|
||||||
|
# Jul 2024
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from .compiler_types import CompilerError
|
||||||
|
from . import syntactical_analyzer as sya
|
||||||
|
from . import semantical_analyzer as sma
|
||||||
|
|
||||||
|
CODE = (0x000, 0x6ff)
|
||||||
|
IO = (0x700, 0x7ff)
|
||||||
|
RAM = (0x800, 0xfff)
|
||||||
|
|
||||||
|
|
||||||
|
class CodeGenerationError(Exception): pass
|
||||||
|
|
||||||
|
|
||||||
|
class CodeGenerationNotImplemented(CompilerError):
|
||||||
|
|
||||||
|
_compiler_error_type = "Code Generation"
|
||||||
|
|
||||||
|
|
||||||
|
class _State:
|
||||||
|
|
||||||
|
memory: dict[sma.Symbol, int]
|
||||||
|
local: dict[sma.Symbol, int]
|
||||||
|
registers: dict[str, sma.Symbol | None]
|
||||||
|
_register_rotation: int
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.memory = dict()
|
||||||
|
self.local = dict()
|
||||||
|
self.registers = {
|
||||||
|
'D0': None,
|
||||||
|
'D1': None,
|
||||||
|
'D2': None,
|
||||||
|
'D3': None,
|
||||||
|
}
|
||||||
|
self._register_rotation = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def register_rotation(self) -> str:
|
||||||
|
for reg in self.registers:
|
||||||
|
if self.registers[reg] is None:
|
||||||
|
return reg
|
||||||
|
else:
|
||||||
|
try: return f"D{self._register_rotation}"
|
||||||
|
finally:
|
||||||
|
self._register_rotation += 1
|
||||||
|
self._register_rotation %= 4
|
||||||
|
|
||||||
|
def store_symbol(self, reg: str) -> str:
|
||||||
|
code = ""
|
||||||
|
symbol = self.registers[reg]
|
||||||
|
if symbol in self.local:
|
||||||
|
code += f"ldi {self.local[symbol]}\n"
|
||||||
|
code += "add MP SP MP\n"
|
||||||
|
code += f"str {reg}\n"
|
||||||
|
elif symbol in self.memory:
|
||||||
|
code += f"ldi {self.memory[symbol]}\n"
|
||||||
|
code += f"str {reg}\n"
|
||||||
|
return code
|
||||||
|
|
||||||
|
def load_symbol(self, symbol: sma.Symbol, reg: str | None = None) -> str:
|
||||||
|
code = ""
|
||||||
|
if reg is None:
|
||||||
|
reg = self.register_rotation
|
||||||
|
if self.registers[reg] is not None:
|
||||||
|
self.store_symbol(reg)
|
||||||
|
if symbol in self.local:
|
||||||
|
code += f"ldi {self.local[symbol]}\n"
|
||||||
|
code += "add MP SP MP\n"
|
||||||
|
code += f"lod {reg}\n"
|
||||||
|
elif symbol in self.memory:
|
||||||
|
code += f"ldi {self.memory[symbol]}\n"
|
||||||
|
code += f"lod {reg}\n"
|
||||||
|
else: raise CodeGenerationError(
|
||||||
|
f"Can not find memory of symbol: {symbol.name} ({hash(symbol)})")
|
||||||
|
return code
|
||||||
|
|
||||||
|
def gen_binary_exprs(self, expression: sya.BinaryExpression) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def gen_block(self, block: sma.CodeBlock) -> str:
|
||||||
|
code = ""
|
||||||
|
# for statement in block.code:
|
||||||
|
# if isinstance(statement, sya.BinaryExpression):
|
||||||
|
# code += self.gen_binary_exprs(statement)
|
||||||
|
return code
|
||||||
|
|
||||||
|
def gen_while(self, func: sma.WhileBlock) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def gen_func(self, func: sma.FunctionBlock) -> str:
|
||||||
|
self.local = dict()
|
||||||
|
memory = 0
|
||||||
|
for symbol in func.symbol_table.symbols:
|
||||||
|
self.local[symbol] = memory
|
||||||
|
memory += 1
|
||||||
|
code = f"{func.identifier.content}:\n"
|
||||||
|
code += f"\n; Initializing stack for function:"
|
||||||
|
code += f" {func.identifier.content}\nldi {memory}\n"
|
||||||
|
code += "sub SP SP MP\n\n"
|
||||||
|
|
||||||
|
for symbol in func.symbol_table.symbols:
|
||||||
|
if (
|
||||||
|
isinstance(symbol.definition, sya.LetStatement) and
|
||||||
|
symbol.definition.assignment is not None
|
||||||
|
):
|
||||||
|
if isinstance(symbol.definition.assignment, sya.StringLiteral):
|
||||||
|
raise CodeGenerationNotImplemented(
|
||||||
|
"Code Generation not yet implemented for "
|
||||||
|
"loading string literals",
|
||||||
|
symbol.definition.assignment.file_info,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
code += f"; Loading initial value for {symbol.name}\n"
|
||||||
|
code += f"ldi {symbol.definition.assignment.value}\n"
|
||||||
|
code += "sub SP SP MP\n"
|
||||||
|
|
||||||
|
code += self.gen_block(func.code)
|
||||||
|
|
||||||
|
code += "\n; Uninitializing stack for function:"
|
||||||
|
code += f" {func.identifier.content}\nldi {memory}\n"
|
||||||
|
code += "add SP SP MP\n"
|
||||||
|
|
||||||
|
return code
|
||||||
|
|
||||||
|
def code_generator(self, syntax_tree: sma.File, entry_name: str) -> str:
|
||||||
|
memory = RAM[0]
|
||||||
|
for symbol in syntax_tree.symbol_table.symbols:
|
||||||
|
if symbol.symbol_type == sma.SymbolType.variable:
|
||||||
|
self.memory[symbol] = memory
|
||||||
|
memory += 1 #symbol.definition.size
|
||||||
|
|
||||||
|
code = "; Generated by `pytd12dk` compiler\n"
|
||||||
|
code += f"; {datetime.now().isoformat()}\n"
|
||||||
|
code += "; Global variables use "
|
||||||
|
code += f"{memory - RAM[0]}/{RAM[1] - RAM[0]} bytes\n"
|
||||||
|
code += "\n.0x0\n"
|
||||||
|
code += f"ldi {RAM[1]}\nor SP MP ZR\n"
|
||||||
|
code += f"ldi :{entry_name}\nor PC MP ZR\n"
|
||||||
|
|
||||||
|
for child in syntax_tree.children:
|
||||||
|
if isinstance(child, sma.FunctionBlock):
|
||||||
|
code += f"\n{self.gen_func(child)}\n"
|
||||||
|
else:
|
||||||
|
raise CodeGenerationNotImplemented(
|
||||||
|
"Code Generation not yet implemented for: "
|
||||||
|
f"{child.__class__.__name__}.",
|
||||||
|
child.file_info,
|
||||||
|
)
|
||||||
|
|
||||||
|
return code
|
||||||
|
|
||||||
|
def code_generator(syntax_tree: sma.File, entry_name: str = 'main') -> str:
|
||||||
|
return _State().code_generator(syntax_tree, entry_name)
|
|
@ -8,6 +8,7 @@ from .compiler_types import CompilerError
|
||||||
from .lexer import lexer
|
from .lexer import lexer
|
||||||
from .syntactical_analyzer import syntactical_analyzer
|
from .syntactical_analyzer import syntactical_analyzer
|
||||||
from .semantical_analyzer import semantical_analyzer
|
from .semantical_analyzer import semantical_analyzer
|
||||||
|
from .code_generator import code_generator
|
||||||
|
|
||||||
def _compile(args: argparse.Namespace):
|
def _compile(args: argparse.Namespace):
|
||||||
tokens = lexer(args.input_file.read(), args.input_file.name)
|
tokens = lexer(args.input_file.read(), args.input_file.name)
|
||||||
|
@ -26,6 +27,11 @@ def _compile(args: argparse.Namespace):
|
||||||
if args.annotated_file:
|
if args.annotated_file:
|
||||||
args.annotated_file.write(annotated_syntax_tree.tree_str())
|
args.annotated_file.write(annotated_syntax_tree.tree_str())
|
||||||
|
|
||||||
|
assembly_code = code_generator(annotated_syntax_tree)
|
||||||
|
|
||||||
|
if args.assembly_file:
|
||||||
|
args.assembly_file.write(assembly_code)
|
||||||
|
|
||||||
def compile(args: argparse.Namespace):
|
def compile(args: argparse.Namespace):
|
||||||
try: _compile(args)
|
try: _compile(args)
|
||||||
except CompilerError as e: print(e.compiler_error())
|
except CompilerError as e: print(e.compiler_error())
|
||||||
|
|
|
@ -5,31 +5,31 @@ from enum import Enum
|
||||||
from typing import ClassVar
|
from typing import ClassVar
|
||||||
|
|
||||||
from .compiler_types import CompilerError, FileInfo
|
from .compiler_types import CompilerError, FileInfo
|
||||||
from . import syntactical_analyzer
|
from . import syntactical_analyzer as sya
|
||||||
|
|
||||||
|
|
||||||
type SymbolDefinitionTypes = (
|
type SymbolDefinitionTypes = (
|
||||||
InternalDefinition |
|
InternalDefinition |
|
||||||
syntactical_analyzer.FunctionParameter |
|
sya.FunctionParameter |
|
||||||
syntactical_analyzer.LetStatement |
|
sya.LetStatement |
|
||||||
ForPreDef |
|
ForPreDef |
|
||||||
syntactical_analyzer.StructBlock |
|
sya.StructBlock |
|
||||||
FunctionBlock |
|
FunctionBlock |
|
||||||
syntactical_analyzer.EnumBlock |
|
sya.EnumBlock |
|
||||||
FunctionReturnDefinition
|
FunctionReturnDefinition
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type SymbolReferenceTypes = (
|
type SymbolReferenceTypes = (
|
||||||
syntactical_analyzer.Identifier |
|
sya.Identifier |
|
||||||
syntactical_analyzer.StructBlock |
|
sya.StructBlock |
|
||||||
FunctionBlock |
|
FunctionBlock |
|
||||||
syntactical_analyzer.EnumBlock
|
sya.EnumBlock
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type Identifier = (
|
type Identifier = (
|
||||||
syntactical_analyzer.Identifier |
|
sya.Identifier |
|
||||||
CompoundIdentifier |
|
CompoundIdentifier |
|
||||||
AddressOfIdentifier |
|
AddressOfIdentifier |
|
||||||
DereferenceIdentifier
|
DereferenceIdentifier
|
||||||
|
@ -40,19 +40,19 @@ type NestableCodeBlock = ForBlock | WhileBlock | DoBlock | IfBlock
|
||||||
|
|
||||||
|
|
||||||
type IntermediateStatement = (
|
type IntermediateStatement = (
|
||||||
syntactical_analyzer.Expression |
|
sya.Expression |
|
||||||
syntactical_analyzer.LetStatement |
|
sya.LetStatement |
|
||||||
syntactical_analyzer.LoopStatements |
|
sya.LoopStatements |
|
||||||
syntactical_analyzer.NestableCodeBlock |
|
sya.NestableCodeBlock |
|
||||||
InternalDefinition |
|
InternalDefinition |
|
||||||
Identifier
|
Identifier
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type Statement = (
|
type Statement = (
|
||||||
syntactical_analyzer.Expression |
|
sya.Expression |
|
||||||
syntactical_analyzer.LetStatement |
|
sya.LetStatement |
|
||||||
syntactical_analyzer.LoopStatements |
|
sya.LoopStatements |
|
||||||
NestableCodeBlock |
|
NestableCodeBlock |
|
||||||
InternalDefinition |
|
InternalDefinition |
|
||||||
Identifier
|
Identifier
|
||||||
|
@ -71,68 +71,68 @@ type BlockHolder = (
|
||||||
|
|
||||||
|
|
||||||
BaseValues: tuple[type, ...] = (
|
BaseValues: tuple[type, ...] = (
|
||||||
syntactical_analyzer.BuiltInConst,
|
sya.BuiltInConst,
|
||||||
syntactical_analyzer.NumberLiteral,
|
sya.NumberLiteral,
|
||||||
syntactical_analyzer.CharLiteral,
|
sya.CharLiteral,
|
||||||
syntactical_analyzer.StringLiteral,
|
sya.StringLiteral,
|
||||||
syntactical_analyzer.Identifier,
|
sya.Identifier,
|
||||||
syntactical_analyzer.FunctionCall,
|
sya.FunctionCall,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
NestableCodeBlocks: tuple[type, ...] = (
|
NestableCodeBlocks: tuple[type, ...] = (
|
||||||
syntactical_analyzer.ForBlock,
|
sya.ForBlock,
|
||||||
syntactical_analyzer.WhileBlock,
|
sya.WhileBlock,
|
||||||
syntactical_analyzer.DoBlock,
|
sya.DoBlock,
|
||||||
syntactical_analyzer.IfBlock,
|
sya.IfBlock,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
HasOperands: tuple[type, ...] = (
|
HasOperands: tuple[type, ...] = (
|
||||||
syntactical_analyzer.UnaryExpression,
|
sya.UnaryExpression,
|
||||||
syntactical_analyzer.BinaryExpression,
|
sya.BinaryExpression,
|
||||||
syntactical_analyzer.TernaryExpression,
|
sya.TernaryExpression,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
AddRefTypes: tuple[type, ...] = (
|
AddRefTypes: tuple[type, ...] = (
|
||||||
syntactical_analyzer.UnaryExpression,
|
sya.UnaryExpression,
|
||||||
syntactical_analyzer.BinaryExpression,
|
sya.BinaryExpression,
|
||||||
syntactical_analyzer.TernaryExpression,
|
sya.TernaryExpression,
|
||||||
syntactical_analyzer.FunctionCall,
|
sya.FunctionCall,
|
||||||
syntactical_analyzer.Identifier,
|
sya.Identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
IncrementOperators: tuple[
|
IncrementOperators: tuple[
|
||||||
syntactical_analyzer.PostfixUnaryOperatorEnum |
|
sya.PostfixUnaryOperatorEnum |
|
||||||
syntactical_analyzer.PrefixUnaryOperatorEnum, ...
|
sya.PrefixUnaryOperatorEnum, ...
|
||||||
] = (
|
] = (
|
||||||
syntactical_analyzer.PostfixUnaryOperatorEnum.Increment,
|
sya.PostfixUnaryOperatorEnum.Increment,
|
||||||
syntactical_analyzer.PostfixUnaryOperatorEnum.Decrement,
|
sya.PostfixUnaryOperatorEnum.Decrement,
|
||||||
syntactical_analyzer.PrefixUnaryOperatorEnum.Increment,
|
sya.PrefixUnaryOperatorEnum.Increment,
|
||||||
syntactical_analyzer.PrefixUnaryOperatorEnum.Decrement,
|
sya.PrefixUnaryOperatorEnum.Decrement,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
PointerOperators: tuple[syntactical_analyzer.PrefixUnaryOperatorEnum, ...] = (
|
PointerOperators: tuple[sya.PrefixUnaryOperatorEnum, ...] = (
|
||||||
syntactical_analyzer.PrefixUnaryOperatorEnum.AddressOf,
|
sya.PrefixUnaryOperatorEnum.AddressOf,
|
||||||
syntactical_analyzer.PrefixUnaryOperatorEnum.Dereference,
|
sya.PrefixUnaryOperatorEnum.Dereference,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
AssignmentOperators: tuple[syntactical_analyzer.BinaryOperatorEnum, ...] = (
|
AssignmentOperators: tuple[sya.BinaryOperatorEnum, ...] = (
|
||||||
syntactical_analyzer.BinaryOperatorEnum.Assignment,
|
sya.BinaryOperatorEnum.Assignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.AdditionAssignment,
|
sya.BinaryOperatorEnum.AdditionAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.SubtractionAssignment,
|
sya.BinaryOperatorEnum.SubtractionAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.MultiplicationAssignment,
|
sya.BinaryOperatorEnum.MultiplicationAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.DivisionAssignment,
|
sya.BinaryOperatorEnum.DivisionAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.ModulusAssignment,
|
sya.BinaryOperatorEnum.ModulusAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.BitwiseANDAssignment,
|
sya.BinaryOperatorEnum.BitwiseANDAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.BitwiseORAssignment,
|
sya.BinaryOperatorEnum.BitwiseORAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.BitwiseXORAssignment,
|
sya.BinaryOperatorEnum.BitwiseXORAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.LeftShiftAssignment,
|
sya.BinaryOperatorEnum.LeftShiftAssignment,
|
||||||
syntactical_analyzer.BinaryOperatorEnum.RightShiftAssignment,
|
sya.BinaryOperatorEnum.RightShiftAssignment,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class UndeclaredVariable(SemanticError):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
variable: syntactical_analyzer.Identifier,
|
variable: sya.Identifier,
|
||||||
):
|
):
|
||||||
message = (
|
message = (
|
||||||
f"The variable '{variable.content}' is undeclared."
|
f"The variable '{variable.content}' is undeclared."
|
||||||
|
@ -175,17 +175,17 @@ class InvalidOperand(SemanticError):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
operator: (
|
operator: (
|
||||||
syntactical_analyzer.TernaryExpression |
|
sya.TernaryExpression |
|
||||||
syntactical_analyzer.BinaryExpression |
|
sya.BinaryExpression |
|
||||||
syntactical_analyzer.UnaryExpression |
|
sya.UnaryExpression |
|
||||||
syntactical_analyzer.Operator
|
sya.Operator
|
||||||
),
|
),
|
||||||
operand: IntermediateStatement | Statement,
|
operand: IntermediateStatement | Statement,
|
||||||
):
|
):
|
||||||
if isinstance(operator, (
|
if isinstance(operator, (
|
||||||
syntactical_analyzer.TernaryExpression,
|
sya.TernaryExpression,
|
||||||
syntactical_analyzer.BinaryExpression,
|
sya.BinaryExpression,
|
||||||
syntactical_analyzer.UnaryExpression,
|
sya.UnaryExpression,
|
||||||
)):
|
)):
|
||||||
message = (
|
message = (
|
||||||
f"The operand at '{operand}' is invalid for the "
|
f"The operand at '{operand}' is invalid for the "
|
||||||
|
@ -305,14 +305,14 @@ class InternalDefinition:
|
||||||
|
|
||||||
_index: ClassVar[int] = 0
|
_index: ClassVar[int] = 0
|
||||||
|
|
||||||
_identifier: syntactical_analyzer.Identifier
|
_identifier: sya.Identifier
|
||||||
_operand: syntactical_analyzer.Expression
|
_operand: sya.Expression
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
operand: syntactical_analyzer.Expression,
|
operand: sya.Expression,
|
||||||
):
|
):
|
||||||
self._identifier = syntactical_analyzer.Identifier(
|
self._identifier = sya.Identifier(
|
||||||
f"`{InternalDefinition._index}",
|
f"`{InternalDefinition._index}",
|
||||||
FileInfo("",0,0,0,0)
|
FileInfo("",0,0,0,0)
|
||||||
)
|
)
|
||||||
|
@ -320,11 +320,11 @@ class InternalDefinition:
|
||||||
InternalDefinition._index += 1
|
InternalDefinition._index += 1
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def identifier(self) -> syntactical_analyzer.Identifier:
|
def identifier(self) -> sya.Identifier:
|
||||||
return self._identifier
|
return self._identifier
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def operand(self) -> syntactical_analyzer.Expression:
|
def operand(self) -> sya.Expression:
|
||||||
return self._operand
|
return self._operand
|
||||||
|
|
||||||
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
@ -360,6 +360,9 @@ class Symbol:
|
||||||
self._definition = definition
|
self._definition = definition
|
||||||
self._references = []
|
self._references = []
|
||||||
|
|
||||||
|
def __hash__(self) -> int:
|
||||||
|
return id(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str: return self._name
|
def name(self) -> str: return self._name
|
||||||
|
|
||||||
|
@ -392,6 +395,9 @@ class SymbolTable:
|
||||||
raise KeyError
|
raise KeyError
|
||||||
self.set(value)
|
self.set(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def symbols(self) -> list[Symbol]: return self._symbols[:]
|
||||||
|
|
||||||
def get(self, key: str, symbol_type: SymbolType | None = None) -> Symbol:
|
def get(self, key: str, symbol_type: SymbolType | None = None) -> Symbol:
|
||||||
for symbol in self._symbols:
|
for symbol in self._symbols:
|
||||||
if symbol.name == key and symbol_type is None:
|
if symbol.name == key and symbol_type is None:
|
||||||
|
@ -474,6 +480,9 @@ class CodeBlock:
|
||||||
def __init__(self, code: list[Statement]):
|
def __init__(self, code: list[Statement]):
|
||||||
self._code = code[:]
|
self._code = code[:]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def code(self) -> list[Statement]: return self._code[:]
|
||||||
|
|
||||||
def tree_str(
|
def tree_str(
|
||||||
self,
|
self,
|
||||||
pre: str = "",
|
pre: str = "",
|
||||||
|
@ -489,19 +498,19 @@ class CodeBlock:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(
|
def _sa(
|
||||||
code: list[syntactical_analyzer.Statement],
|
code: list[sya.Statement],
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
members: list[syntactical_analyzer.LetStatement],
|
members: list[sya.LetStatement],
|
||||||
) -> "CodeBlock":
|
) -> "CodeBlock":
|
||||||
|
|
||||||
def add_ref_if(statement: syntactical_analyzer.Expression):
|
def add_ref_if(statement: sya.Expression):
|
||||||
if isinstance(statement, HasOperands):
|
if isinstance(statement, HasOperands):
|
||||||
for key in OperandKeys:
|
for key in OperandKeys:
|
||||||
if (
|
if (
|
||||||
hasattr(statement, key) and
|
hasattr(statement, key) and
|
||||||
isinstance(
|
isinstance(
|
||||||
getattr(statement, key),
|
getattr(statement, key),
|
||||||
syntactical_analyzer.Identifier,
|
sya.Identifier,
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
@ -515,7 +524,7 @@ class CodeBlock:
|
||||||
hasattr(statement, key) and
|
hasattr(statement, key) and
|
||||||
isinstance(
|
isinstance(
|
||||||
getattr(statement, key),
|
getattr(statement, key),
|
||||||
syntactical_analyzer.FunctionCall,
|
sya.FunctionCall,
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
@ -539,20 +548,20 @@ class CodeBlock:
|
||||||
elif (
|
elif (
|
||||||
isinstance(
|
isinstance(
|
||||||
statement,
|
statement,
|
||||||
syntactical_analyzer.BinaryExpression,
|
sya.BinaryExpression,
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
statement.operator ==
|
statement.operator ==
|
||||||
syntactical_analyzer.BinaryOperatorEnum.Assignment
|
sya.BinaryOperatorEnum.Assignment
|
||||||
) and
|
) and
|
||||||
hasattr(statement, key) and
|
hasattr(statement, key) and
|
||||||
isinstance(
|
isinstance(
|
||||||
getattr(statement, key),
|
getattr(statement, key),
|
||||||
syntactical_analyzer.BinaryExpression,
|
sya.BinaryExpression,
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
add_ref_if(getattr(statement, key))
|
add_ref_if(getattr(statement, key))
|
||||||
elif isinstance(statement, syntactical_analyzer.FunctionCall):
|
elif isinstance(statement, sya.FunctionCall):
|
||||||
try:
|
try:
|
||||||
symbol = symbol_table.get(
|
symbol = symbol_table.get(
|
||||||
statement.identifier.content, SymbolType.function)
|
statement.identifier.content, SymbolType.function)
|
||||||
|
@ -568,7 +577,7 @@ class CodeBlock:
|
||||||
raise UndeclaredVariable(arg.value) # type: ignore
|
raise UndeclaredVariable(arg.value) # type: ignore
|
||||||
else:
|
else:
|
||||||
symbol.add_reference(arg.value) # type: ignore
|
symbol.add_reference(arg.value) # type: ignore
|
||||||
elif isinstance(statement, syntactical_analyzer.Identifier):
|
elif isinstance(statement, sya.Identifier):
|
||||||
try:
|
try:
|
||||||
symbol = symbol_table.get(statement.content)
|
symbol = symbol_table.get(statement.content)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -579,7 +588,7 @@ class CodeBlock:
|
||||||
code_out: list[Statement] = []
|
code_out: list[Statement] = []
|
||||||
for root_statement in code:
|
for root_statement in code:
|
||||||
for statement in _flatten_statement(root_statement):
|
for statement in _flatten_statement(root_statement):
|
||||||
if isinstance(statement, syntactical_analyzer.LetStatement):
|
if isinstance(statement, sya.LetStatement):
|
||||||
try:
|
try:
|
||||||
symbol_table.add(Symbol(
|
symbol_table.add(Symbol(
|
||||||
statement.identifier.content,
|
statement.identifier.content,
|
||||||
|
@ -608,16 +617,16 @@ class CodeBlock:
|
||||||
elif isinstance(statement, AddRefTypes):
|
elif isinstance(statement, AddRefTypes):
|
||||||
add_ref_if(statement) # type: ignore
|
add_ref_if(statement) # type: ignore
|
||||||
code_out.append(statement) # type: ignore
|
code_out.append(statement) # type: ignore
|
||||||
elif isinstance(statement, syntactical_analyzer.IfBlock):
|
elif isinstance(statement, sya.IfBlock):
|
||||||
code_out.append(
|
code_out.append(
|
||||||
IfBlock._sa(statement, symbol_table, members))
|
IfBlock._sa(statement, symbol_table, members))
|
||||||
elif isinstance(statement, syntactical_analyzer.DoBlock):
|
elif isinstance(statement, sya.DoBlock):
|
||||||
code_out.append(
|
code_out.append(
|
||||||
DoBlock._sa(statement, symbol_table, members))
|
DoBlock._sa(statement, symbol_table, members))
|
||||||
elif isinstance(statement, syntactical_analyzer.WhileBlock):
|
elif isinstance(statement, sya.WhileBlock):
|
||||||
code_out.append(
|
code_out.append(
|
||||||
WhileBlock._sa(statement, symbol_table, members))
|
WhileBlock._sa(statement, symbol_table, members))
|
||||||
elif isinstance(statement, syntactical_analyzer.ForBlock):
|
elif isinstance(statement, sya.ForBlock):
|
||||||
code_out.append(
|
code_out.append(
|
||||||
ForBlock._sa(statement, symbol_table, members))
|
ForBlock._sa(statement, symbol_table, members))
|
||||||
else:
|
else:
|
||||||
|
@ -647,9 +656,9 @@ class ElseBlock:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(
|
def _sa(
|
||||||
else_block: syntactical_analyzer.ElseBlock,
|
else_block: sya.ElseBlock,
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
members: list[syntactical_analyzer.LetStatement],
|
members: list[sya.LetStatement],
|
||||||
) -> "ElseBlock":
|
) -> "ElseBlock":
|
||||||
|
|
||||||
code = CodeBlock._sa(else_block.code, symbol_table, members)
|
code = CodeBlock._sa(else_block.code, symbol_table, members)
|
||||||
|
@ -660,7 +669,7 @@ class ElseBlock:
|
||||||
class ForPreDef:
|
class ForPreDef:
|
||||||
|
|
||||||
_identifier: Identifier
|
_identifier: Identifier
|
||||||
_type: syntactical_analyzer.DataType
|
_type: sya.DataType
|
||||||
_pointer: bool
|
_pointer: bool
|
||||||
_assignment: CodeBlock | None
|
_assignment: CodeBlock | None
|
||||||
_file_info: FileInfo
|
_file_info: FileInfo
|
||||||
|
@ -668,7 +677,7 @@ class ForPreDef:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
type: syntactical_analyzer.DataType,
|
type: sya.DataType,
|
||||||
pointer: bool,
|
pointer: bool,
|
||||||
assignment: CodeBlock | None,
|
assignment: CodeBlock | None,
|
||||||
file_info: FileInfo,
|
file_info: FileInfo,
|
||||||
|
@ -743,12 +752,12 @@ class ForBlock:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(
|
def _sa(
|
||||||
for_block: syntactical_analyzer.ForBlock,
|
for_block: sya.ForBlock,
|
||||||
parent_table: SymbolTable,
|
parent_table: SymbolTable,
|
||||||
members: list[syntactical_analyzer.LetStatement],
|
members: list[sya.LetStatement],
|
||||||
) -> "ForBlock":
|
) -> "ForBlock":
|
||||||
symbol_table = ForSymbolTable(parent_table)
|
symbol_table = ForSymbolTable(parent_table)
|
||||||
if isinstance(for_block.pre_statement, syntactical_analyzer.ForPreDef):
|
if isinstance(for_block.pre_statement, sya.ForPreDef):
|
||||||
assignment = CodeBlock._sa(for_block.code, symbol_table, members)
|
assignment = CodeBlock._sa(for_block.code, symbol_table, members)
|
||||||
pre_statement = ForPreDef(
|
pre_statement = ForPreDef(
|
||||||
for_block.pre_statement.identifier,
|
for_block.pre_statement.identifier,
|
||||||
|
@ -827,9 +836,9 @@ class WhileBlock:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(
|
def _sa(
|
||||||
while_block: syntactical_analyzer.WhileBlock,
|
while_block: sya.WhileBlock,
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
members: list[syntactical_analyzer.LetStatement],
|
members: list[sya.LetStatement],
|
||||||
) -> "WhileBlock":
|
) -> "WhileBlock":
|
||||||
condition = CodeBlock._sa(
|
condition = CodeBlock._sa(
|
||||||
[while_block.condition], symbol_table, members)
|
[while_block.condition], symbol_table, members)
|
||||||
|
@ -897,9 +906,9 @@ class DoBlock:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(
|
def _sa(
|
||||||
do_block: syntactical_analyzer.DoBlock,
|
do_block: sya.DoBlock,
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
members: list[syntactical_analyzer.LetStatement],
|
members: list[sya.LetStatement],
|
||||||
) -> "DoBlock":
|
) -> "DoBlock":
|
||||||
condition = CodeBlock._sa([do_block.condition], symbol_table, members)
|
condition = CodeBlock._sa([do_block.condition], symbol_table, members)
|
||||||
first_code = CodeBlock._sa(do_block.first_code, symbol_table, members)
|
first_code = CodeBlock._sa(do_block.first_code, symbol_table, members)
|
||||||
|
@ -957,9 +966,9 @@ class IfBlock:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(
|
def _sa(
|
||||||
if_block: syntactical_analyzer.IfBlock,
|
if_block: sya.IfBlock,
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
members: list[syntactical_analyzer.LetStatement],
|
members: list[sya.LetStatement],
|
||||||
) -> "IfBlock":
|
) -> "IfBlock":
|
||||||
condition = CodeBlock._sa([if_block.condition], symbol_table, members)
|
condition = CodeBlock._sa([if_block.condition], symbol_table, members)
|
||||||
code = CodeBlock._sa(if_block.code, symbol_table, members)
|
code = CodeBlock._sa(if_block.code, symbol_table, members)
|
||||||
|
@ -977,48 +986,48 @@ class IfBlock:
|
||||||
|
|
||||||
class FunctionReturnDefinition:
|
class FunctionReturnDefinition:
|
||||||
|
|
||||||
_identifier: syntactical_analyzer.Identifier
|
_identifier: sya.Identifier
|
||||||
_return_type_pointer: bool
|
_return_type_pointer: bool
|
||||||
_return_type: syntactical_analyzer.DataType | None
|
_return_type: sya.DataType | None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
identifier: syntactical_analyzer.Identifier,
|
identifier: sya.Identifier,
|
||||||
return_type_pointer: bool,
|
return_type_pointer: bool,
|
||||||
return_type: syntactical_analyzer.DataType | None,
|
return_type: sya.DataType | None,
|
||||||
):
|
):
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
self._return_type_pointer = return_type_pointer
|
self._return_type_pointer = return_type_pointer
|
||||||
self._return_type = return_type
|
self._return_type = return_type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def identifier(self) -> syntactical_analyzer.Identifier:
|
def identifier(self) -> sya.Identifier:
|
||||||
return self._identifier
|
return self._identifier
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def return_type_pointer(self) -> bool: return self._return_type_pointer
|
def return_type_pointer(self) -> bool: return self._return_type_pointer
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def return_type(self) -> syntactical_analyzer.DataType | None:
|
def return_type(self) -> sya.DataType | None:
|
||||||
return self._return_type
|
return self._return_type
|
||||||
|
|
||||||
|
|
||||||
class FunctionBlock:
|
class FunctionBlock:
|
||||||
|
|
||||||
_identifier: syntactical_analyzer.Identifier
|
_identifier: sya.Identifier
|
||||||
_params: list[syntactical_analyzer.FunctionParameter]
|
_params: list[sya.FunctionParameter]
|
||||||
_return_type: FunctionReturnDefinition
|
_return_type: FunctionReturnDefinition
|
||||||
_members: list[syntactical_analyzer.LetStatement]
|
_members: list[sya.LetStatement]
|
||||||
_code: CodeBlock
|
_code: CodeBlock
|
||||||
_file_info: FileInfo
|
_file_info: FileInfo
|
||||||
_symbol_table: SymbolTable
|
_symbol_table: SymbolTable
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
identifier: syntactical_analyzer.Identifier,
|
identifier: sya.Identifier,
|
||||||
params: list[syntactical_analyzer.FunctionParameter],
|
params: list[sya.FunctionParameter],
|
||||||
return_type: FunctionReturnDefinition,
|
return_type: FunctionReturnDefinition,
|
||||||
members: list[syntactical_analyzer.LetStatement],
|
members: list[sya.LetStatement],
|
||||||
code: CodeBlock,
|
code: CodeBlock,
|
||||||
file_info: FileInfo,
|
file_info: FileInfo,
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
|
@ -1032,18 +1041,18 @@ class FunctionBlock:
|
||||||
self._symbol_table = symbol_table
|
self._symbol_table = symbol_table
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def identifier(self) -> syntactical_analyzer.Identifier:
|
def identifier(self) -> sya.Identifier:
|
||||||
return self._identifier
|
return self._identifier
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def params(self) -> list[syntactical_analyzer.FunctionParameter]:
|
def params(self) -> list[sya.FunctionParameter]:
|
||||||
return self._params[:]
|
return self._params[:]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def return_type(self) -> FunctionReturnDefinition: return self._return_type
|
def return_type(self) -> FunctionReturnDefinition: return self._return_type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def members(self) -> list[syntactical_analyzer.LetStatement]:
|
def members(self) -> list[sya.LetStatement]:
|
||||||
return self._members[:]
|
return self._members[:]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -1052,6 +1061,9 @@ class FunctionBlock:
|
||||||
@property
|
@property
|
||||||
def file_info(self) -> FileInfo: return self._file_info
|
def file_info(self) -> FileInfo: return self._file_info
|
||||||
|
|
||||||
|
@property
|
||||||
|
def symbol_table(self) -> SymbolTable: return self._symbol_table
|
||||||
|
|
||||||
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
s: str = f"{pre} Function: {self._identifier}\n"
|
s: str = f"{pre} Function: {self._identifier}\n"
|
||||||
if (
|
if (
|
||||||
|
@ -1096,11 +1108,11 @@ class FunctionBlock:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(
|
def _sa(
|
||||||
func: syntactical_analyzer.FunctionBlock,
|
func: sya.FunctionBlock,
|
||||||
parent_table: SymbolTable,
|
parent_table: SymbolTable,
|
||||||
) -> "FunctionBlock":
|
) -> "FunctionBlock":
|
||||||
symbol_table = SymbolTable(parent_table)
|
symbol_table = SymbolTable(parent_table)
|
||||||
members: list[syntactical_analyzer.LetStatement] = []
|
members: list[sya.LetStatement] = []
|
||||||
|
|
||||||
function_return = FunctionReturnDefinition(
|
function_return = FunctionReturnDefinition(
|
||||||
func.identifier, func.return_type_pointer, func.return_type)
|
func.identifier, func.return_type_pointer, func.return_type)
|
||||||
|
@ -1137,10 +1149,10 @@ class FunctionBlock:
|
||||||
class File:
|
class File:
|
||||||
|
|
||||||
_children: list[
|
_children: list[
|
||||||
syntactical_analyzer.Directive |
|
sya.Directive |
|
||||||
syntactical_analyzer.StructBlock |
|
sya.StructBlock |
|
||||||
FunctionBlock |
|
FunctionBlock |
|
||||||
syntactical_analyzer.EnumBlock
|
sya.EnumBlock
|
||||||
]
|
]
|
||||||
_file_info: FileInfo
|
_file_info: FileInfo
|
||||||
_symbol_table: SymbolTable
|
_symbol_table: SymbolTable
|
||||||
|
@ -1148,10 +1160,10 @@ class File:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
children: list[
|
children: list[
|
||||||
syntactical_analyzer.Directive |
|
sya.Directive |
|
||||||
syntactical_analyzer.StructBlock |
|
sya.StructBlock |
|
||||||
FunctionBlock |
|
FunctionBlock |
|
||||||
syntactical_analyzer.EnumBlock
|
sya.EnumBlock
|
||||||
],
|
],
|
||||||
file_info: FileInfo,
|
file_info: FileInfo,
|
||||||
symbol_table: SymbolTable,
|
symbol_table: SymbolTable,
|
||||||
|
@ -1160,9 +1172,20 @@ class File:
|
||||||
self._file_info = file_info
|
self._file_info = file_info
|
||||||
self._symbol_table = symbol_table
|
self._symbol_table = symbol_table
|
||||||
|
|
||||||
|
@property
|
||||||
|
def children(self) -> list[
|
||||||
|
sya.Directive |
|
||||||
|
sya.StructBlock |
|
||||||
|
FunctionBlock |
|
||||||
|
sya.EnumBlock
|
||||||
|
]: return self._children[:]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def file_info(self) -> FileInfo: return self._file_info
|
def file_info(self) -> FileInfo: return self._file_info
|
||||||
|
|
||||||
|
@property
|
||||||
|
def symbol_table(self) -> SymbolTable: return self._symbol_table
|
||||||
|
|
||||||
def tree_str(self) -> str:
|
def tree_str(self) -> str:
|
||||||
s: str = " File\n"
|
s: str = " File\n"
|
||||||
if self._children:
|
if self._children:
|
||||||
|
@ -1175,29 +1198,29 @@ class File:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sa(syntax_tree: syntactical_analyzer.File) -> "File":
|
def _sa(syntax_tree: sya.File) -> "File":
|
||||||
symbol_table = SymbolTable()
|
symbol_table = SymbolTable()
|
||||||
children: list[
|
children: list[
|
||||||
syntactical_analyzer.Directive |
|
sya.Directive |
|
||||||
syntactical_analyzer.StructBlock |
|
sya.StructBlock |
|
||||||
FunctionBlock |
|
FunctionBlock |
|
||||||
syntactical_analyzer.EnumBlock
|
sya.EnumBlock
|
||||||
] = []
|
] = []
|
||||||
for child in syntax_tree.children:
|
for child in syntax_tree.children:
|
||||||
symbol: Symbol | None = None
|
symbol: Symbol | None = None
|
||||||
if isinstance(child, syntactical_analyzer.StructBlock):
|
if isinstance(child, sya.StructBlock):
|
||||||
symbol = Symbol(
|
symbol = Symbol(
|
||||||
child.identifier.content,
|
child.identifier.content,
|
||||||
SymbolType.struct,
|
SymbolType.struct,
|
||||||
child,
|
child,
|
||||||
)
|
)
|
||||||
elif isinstance(child, syntactical_analyzer.FunctionBlock):
|
elif isinstance(child, sya.FunctionBlock):
|
||||||
symbol = Symbol(
|
symbol = Symbol(
|
||||||
child.identifier.content,
|
child.identifier.content,
|
||||||
SymbolType.function,
|
SymbolType.function,
|
||||||
child, # type: ignore
|
child, # type: ignore
|
||||||
)
|
)
|
||||||
elif isinstance(child, syntactical_analyzer.EnumBlock):
|
elif isinstance(child, sya.EnumBlock):
|
||||||
symbol = Symbol(
|
symbol = Symbol(
|
||||||
child.identifier.content,
|
child.identifier.content,
|
||||||
SymbolType.enum,
|
SymbolType.enum,
|
||||||
|
@ -1206,30 +1229,26 @@ class File:
|
||||||
if symbol is not None:
|
if symbol is not None:
|
||||||
symbol_table.add(symbol)
|
symbol_table.add(symbol)
|
||||||
for child in syntax_tree.children:
|
for child in syntax_tree.children:
|
||||||
new_child: (
|
new_child: sya.StructBlock | FunctionBlock | sya.EnumBlock
|
||||||
syntactical_analyzer.StructBlock |
|
if isinstance(child, sya.FunctionBlock):
|
||||||
FunctionBlock |
|
|
||||||
syntactical_analyzer.EnumBlock
|
|
||||||
)
|
|
||||||
if isinstance(child, syntactical_analyzer.FunctionBlock):
|
|
||||||
new_child = FunctionBlock._sa(child, symbol_table)
|
new_child = FunctionBlock._sa(child, symbol_table)
|
||||||
symbol_table.get(
|
symbol_table.get(
|
||||||
child.identifier.content
|
child.identifier.content
|
||||||
)._definition = new_child # type: ignore
|
)._definition = new_child # type: ignore
|
||||||
# TODO: analyze structs
|
# TODO: analyze structs
|
||||||
elif isinstance(child, syntactical_analyzer.StructBlock):
|
elif isinstance(child, sya.StructBlock):
|
||||||
new_child = child
|
new_child = child
|
||||||
elif isinstance(child, syntactical_analyzer.EnumBlock):
|
elif isinstance(child, sya.EnumBlock):
|
||||||
new_child = _sa_enum(child)
|
new_child = _sa_enum(child)
|
||||||
elif isinstance(child, syntactical_analyzer.Directive):
|
elif isinstance(child, sya.Directive):
|
||||||
continue
|
continue
|
||||||
children.append(new_child)
|
children.append(new_child)
|
||||||
file = File(children, syntax_tree._file_info, symbol_table)
|
file = File(children, syntax_tree._file_info, symbol_table)
|
||||||
return file
|
return file
|
||||||
|
|
||||||
def _sa_enum(block: syntactical_analyzer.EnumBlock
|
|
||||||
) -> syntactical_analyzer.EnumBlock:
|
def _sa_enum(block: sya.EnumBlock) -> sya.EnumBlock:
|
||||||
members: list[syntactical_analyzer.EnumMember] = []
|
members: list[sya.EnumMember] = []
|
||||||
used_numbers: set[int] = set()
|
used_numbers: set[int] = set()
|
||||||
for member in block.members:
|
for member in block.members:
|
||||||
if member.value is not None:
|
if member.value is not None:
|
||||||
|
@ -1239,7 +1258,7 @@ def _sa_enum(block: syntactical_analyzer.EnumBlock
|
||||||
while i in used_numbers:
|
while i in used_numbers:
|
||||||
i += 1
|
i += 1
|
||||||
if member.value is not None:
|
if member.value is not None:
|
||||||
members.append(syntactical_analyzer.EnumMember(
|
members.append(sya.EnumMember(
|
||||||
member.identifier,
|
member.identifier,
|
||||||
member.value,
|
member.value,
|
||||||
member.file_info
|
member.file_info
|
||||||
|
@ -1247,13 +1266,13 @@ def _sa_enum(block: syntactical_analyzer.EnumBlock
|
||||||
i = member.value.value + 1
|
i = member.value.value + 1
|
||||||
else:
|
else:
|
||||||
used_numbers.add(i)
|
used_numbers.add(i)
|
||||||
members.append(syntactical_analyzer.EnumMember(
|
members.append(sya.EnumMember(
|
||||||
member.identifier,
|
member.identifier,
|
||||||
syntactical_analyzer.NumberLiteral(str(i), member.file_info),
|
sya.NumberLiteral(str(i), member.file_info),
|
||||||
member.file_info
|
member.file_info
|
||||||
))
|
))
|
||||||
i += 1
|
i += 1
|
||||||
return syntactical_analyzer.EnumBlock(
|
return sya.EnumBlock(
|
||||||
block.identifier,
|
block.identifier,
|
||||||
sorted(
|
sorted(
|
||||||
sorted(members, key=lambda o: o.identifier.content),
|
sorted(members, key=lambda o: o.identifier.content),
|
||||||
|
@ -1263,12 +1282,12 @@ def _sa_enum(block: syntactical_analyzer.EnumBlock
|
||||||
)
|
)
|
||||||
|
|
||||||
def _compound_identifier(
|
def _compound_identifier(
|
||||||
statement: syntactical_analyzer.BinaryExpression,
|
statement: sya.BinaryExpression,
|
||||||
operator: syntactical_analyzer.Operator,
|
operator: sya.Operator,
|
||||||
) -> CompoundIdentifier:
|
) -> CompoundIdentifier:
|
||||||
if (
|
if (
|
||||||
statement.operator.content ==
|
statement.operator.content ==
|
||||||
syntactical_analyzer.BinaryOperatorEnum.MemberOf
|
sya.BinaryOperatorEnum.MemberOf
|
||||||
): return CompoundIdentifier(
|
): return CompoundIdentifier(
|
||||||
_assert_identifier(statement.operand1, statement.operator, True),
|
_assert_identifier(statement.operand1, statement.operator, True),
|
||||||
_assert_identifier(statement.operand2, statement.operator, True),
|
_assert_identifier(statement.operand2, statement.operator, True),
|
||||||
|
@ -1277,19 +1296,19 @@ def _compound_identifier(
|
||||||
else: raise InvalidOperand(operator, statement)
|
else: raise InvalidOperand(operator, statement)
|
||||||
|
|
||||||
def _augment_identifier(
|
def _augment_identifier(
|
||||||
statement: syntactical_analyzer.UnaryExpression,
|
statement: sya.UnaryExpression,
|
||||||
operator: syntactical_analyzer.Operator,
|
operator: sya.Operator,
|
||||||
) -> AddressOfIdentifier | DereferenceIdentifier:
|
) -> AddressOfIdentifier | DereferenceIdentifier:
|
||||||
if (
|
if (
|
||||||
statement.operator.content ==
|
statement.operator.content ==
|
||||||
syntactical_analyzer.PrefixUnaryOperatorEnum.AddressOf
|
sya.PrefixUnaryOperatorEnum.AddressOf
|
||||||
): return AddressOfIdentifier(
|
): return AddressOfIdentifier(
|
||||||
_assert_identifier(statement.operand, statement.operator, True),
|
_assert_identifier(statement.operand, statement.operator, True),
|
||||||
statement.file_info,
|
statement.file_info,
|
||||||
)
|
)
|
||||||
elif (
|
elif (
|
||||||
statement.operator.content ==
|
statement.operator.content ==
|
||||||
syntactical_analyzer.PrefixUnaryOperatorEnum.Dereference
|
sya.PrefixUnaryOperatorEnum.Dereference
|
||||||
): return DereferenceIdentifier(
|
): return DereferenceIdentifier(
|
||||||
_assert_identifier(statement.operand, statement.operator, True),
|
_assert_identifier(statement.operand, statement.operator, True),
|
||||||
statement.file_info,
|
statement.file_info,
|
||||||
|
@ -1297,25 +1316,25 @@ def _augment_identifier(
|
||||||
else: raise InvalidOperand(operator, statement)
|
else: raise InvalidOperand(operator, statement)
|
||||||
|
|
||||||
def _assert_identifier(
|
def _assert_identifier(
|
||||||
statement: syntactical_analyzer.Statement,
|
statement: sya.Statement,
|
||||||
operator: syntactical_analyzer.Operator,
|
operator: sya.Operator,
|
||||||
harsh: bool = False
|
harsh: bool = False
|
||||||
) -> Identifier:
|
) -> Identifier:
|
||||||
if isinstance(statement, syntactical_analyzer.Identifier):
|
if isinstance(statement, sya.Identifier):
|
||||||
return statement
|
return statement
|
||||||
elif isinstance(statement, syntactical_analyzer.UnaryExpression):
|
elif isinstance(statement, sya.UnaryExpression):
|
||||||
if (
|
if (
|
||||||
isinstance(statement.operand, syntactical_analyzer.BinaryExpression)
|
isinstance(statement.operand, sya.BinaryExpression)
|
||||||
and not harsh
|
and not harsh
|
||||||
):
|
):
|
||||||
return statement # type: ignore
|
return statement # type: ignore
|
||||||
return _augment_identifier(statement, operator)
|
return _augment_identifier(statement, operator)
|
||||||
elif isinstance(statement, syntactical_analyzer.BinaryExpression):
|
elif isinstance(statement, sya.BinaryExpression):
|
||||||
return _compound_identifier(statement, operator)
|
return _compound_identifier(statement, operator)
|
||||||
else: raise InvalidOperand(operator, statement)
|
else: raise InvalidOperand(operator, statement)
|
||||||
|
|
||||||
def _create_internal_definition(
|
def _create_internal_definition(
|
||||||
statement: syntactical_analyzer.Expression,
|
statement: sya.Expression,
|
||||||
) -> list[IntermediateStatement]:
|
) -> list[IntermediateStatement]:
|
||||||
flattened = _flatten_statement(statement)
|
flattened = _flatten_statement(statement)
|
||||||
internal_definition = InternalDefinition(
|
internal_definition = InternalDefinition(
|
||||||
|
@ -1324,12 +1343,12 @@ def _create_internal_definition(
|
||||||
internal_definition, internal_definition.identifier]
|
internal_definition, internal_definition.identifier]
|
||||||
|
|
||||||
def _flatten_statement(
|
def _flatten_statement(
|
||||||
statement: syntactical_analyzer.Statement,
|
statement: sya.Statement,
|
||||||
) -> list[IntermediateStatement]:
|
) -> list[IntermediateStatement]:
|
||||||
|
|
||||||
if isinstance(statement, syntactical_analyzer.UnaryExpression):
|
if isinstance(statement, sya.UnaryExpression):
|
||||||
if statement.operator.content in IncrementOperators:
|
if statement.operator.content in IncrementOperators:
|
||||||
return [syntactical_analyzer.UnaryExpression(
|
return [sya.UnaryExpression(
|
||||||
statement.operator,
|
statement.operator,
|
||||||
_assert_identifier( # type: ignore
|
_assert_identifier( # type: ignore
|
||||||
statement.operand, statement.operator),
|
statement.operand, statement.operator),
|
||||||
|
@ -1342,17 +1361,17 @@ def _flatten_statement(
|
||||||
else:
|
else:
|
||||||
flattened = _create_internal_definition(statement.operand)
|
flattened = _create_internal_definition(statement.operand)
|
||||||
return flattened[:-1] + [
|
return flattened[:-1] + [
|
||||||
syntactical_analyzer.UnaryExpression(
|
sya.UnaryExpression(
|
||||||
statement.operator,
|
statement.operator,
|
||||||
flattened[-1], # type: ignore
|
flattened[-1], # type: ignore
|
||||||
statement.file_info,
|
statement.file_info,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
elif isinstance(statement, syntactical_analyzer.BinaryExpression):
|
elif isinstance(statement, sya.BinaryExpression):
|
||||||
if (
|
if (
|
||||||
statement.operator.content ==
|
statement.operator.content ==
|
||||||
syntactical_analyzer.BinaryOperatorEnum.MemberOf
|
sya.BinaryOperatorEnum.MemberOf
|
||||||
): return [CompoundIdentifier(
|
): return [CompoundIdentifier(
|
||||||
_assert_identifier(statement.operand1, statement.operator),
|
_assert_identifier(statement.operand1, statement.operator),
|
||||||
_assert_identifier(statement.operand2, statement.operator),
|
_assert_identifier(statement.operand2, statement.operator),
|
||||||
|
@ -1360,10 +1379,10 @@ def _flatten_statement(
|
||||||
)]
|
)]
|
||||||
elif (
|
elif (
|
||||||
statement.operator.content ==
|
statement.operator.content ==
|
||||||
syntactical_analyzer.BinaryOperatorEnum.Assignment
|
sya.BinaryOperatorEnum.Assignment
|
||||||
):
|
):
|
||||||
flattened = _flatten_statement(statement.operand2)
|
flattened = _flatten_statement(statement.operand2)
|
||||||
return flattened[:-1] + [syntactical_analyzer.BinaryExpression(
|
return flattened[:-1] + [sya.BinaryExpression(
|
||||||
statement.operator,
|
statement.operator,
|
||||||
_assert_identifier( # type: ignore
|
_assert_identifier( # type: ignore
|
||||||
statement.operand1,
|
statement.operand1,
|
||||||
|
@ -1374,7 +1393,7 @@ def _flatten_statement(
|
||||||
)]
|
)]
|
||||||
elif statement.operator.content in AssignmentOperators:
|
elif statement.operator.content in AssignmentOperators:
|
||||||
if isinstance(statement.operand2, BaseValues):
|
if isinstance(statement.operand2, BaseValues):
|
||||||
return [syntactical_analyzer.BinaryExpression(
|
return [sya.BinaryExpression(
|
||||||
statement.operator,
|
statement.operator,
|
||||||
_assert_identifier( # type: ignore
|
_assert_identifier( # type: ignore
|
||||||
statement.operand1,
|
statement.operand1,
|
||||||
|
@ -1385,7 +1404,7 @@ def _flatten_statement(
|
||||||
)]
|
)]
|
||||||
else:
|
else:
|
||||||
flattened = _create_internal_definition(statement.operand2)
|
flattened = _create_internal_definition(statement.operand2)
|
||||||
return flattened[:-1] + [syntactical_analyzer.BinaryExpression(
|
return flattened[:-1] + [sya.BinaryExpression(
|
||||||
statement.operator,
|
statement.operator,
|
||||||
_assert_identifier( # type: ignore
|
_assert_identifier( # type: ignore
|
||||||
statement.operand1,
|
statement.operand1,
|
||||||
|
@ -1402,7 +1421,7 @@ def _flatten_statement(
|
||||||
flattened2 = [statement.operand2]
|
flattened2 = [statement.operand2]
|
||||||
else: flattened2 = _create_internal_definition(statement.operand2)
|
else: flattened2 = _create_internal_definition(statement.operand2)
|
||||||
return flattened1[:-1] + flattened2[:-1] + [
|
return flattened1[:-1] + flattened2[:-1] + [
|
||||||
syntactical_analyzer.BinaryExpression(
|
sya.BinaryExpression(
|
||||||
statement.operator,
|
statement.operator,
|
||||||
flattened1[-1], # type: ignore
|
flattened1[-1], # type: ignore
|
||||||
flattened2[-1], # type: ignore
|
flattened2[-1], # type: ignore
|
||||||
|
@ -1410,7 +1429,7 @@ def _flatten_statement(
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
elif isinstance(statement, syntactical_analyzer.TernaryExpression):
|
elif isinstance(statement, sya.TernaryExpression):
|
||||||
if isinstance(statement.operand1, BaseValues):
|
if isinstance(statement.operand1, BaseValues):
|
||||||
flattened1 = [statement.operand1]
|
flattened1 = [statement.operand1]
|
||||||
else: flattened1 = _create_internal_definition(statement.operand1)
|
else: flattened1 = _create_internal_definition(statement.operand1)
|
||||||
|
@ -1421,7 +1440,7 @@ def _flatten_statement(
|
||||||
flattened3 = [statement.operand3]
|
flattened3 = [statement.operand3]
|
||||||
else: flattened3 = _create_internal_definition(statement.operand3)
|
else: flattened3 = _create_internal_definition(statement.operand3)
|
||||||
return flattened1[:-1] + flattened2[:-1] + flattened3[:-1] + [
|
return flattened1[:-1] + flattened2[:-1] + flattened3[:-1] + [
|
||||||
syntactical_analyzer.TernaryExpression(
|
sya.TernaryExpression(
|
||||||
statement.operator,
|
statement.operator,
|
||||||
flattened1[-1], # type: ignore
|
flattened1[-1], # type: ignore
|
||||||
flattened2[-1], # type: ignore
|
flattened2[-1], # type: ignore
|
||||||
|
@ -1432,5 +1451,5 @@ def _flatten_statement(
|
||||||
|
|
||||||
else: return [statement]
|
else: return [statement]
|
||||||
|
|
||||||
def semantical_analyzer(syntax_tree: syntactical_analyzer.File) -> File:
|
def semantical_analyzer(syntax_tree: sya.File) -> File:
|
||||||
return File._sa(syntax_tree)
|
return File._sa(syntax_tree)
|
||||||
|
|
|
@ -177,6 +177,13 @@ class BuiltInConst:
|
||||||
@property
|
@property
|
||||||
def file_info(self) -> FileInfo: return self._file_info
|
def file_info(self) -> FileInfo: return self._file_info
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> int:
|
||||||
|
match (self._content):
|
||||||
|
case BuiltInConstEnum.ConstTrue: return 1
|
||||||
|
case BuiltInConstEnum.ConstFalse: return 0
|
||||||
|
case BuiltInConstEnum.ConstNone: return 0
|
||||||
|
|
||||||
def __str__(self) -> str: return self._content.value
|
def __str__(self) -> str: return self._content.value
|
||||||
|
|
||||||
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
@ -547,7 +554,7 @@ class NumberLiteral:
|
||||||
def content(self) -> str: return self._content
|
def content(self) -> str: return self._content
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> int: return int(self._content)
|
def value(self) -> int: return int(self._content, base=0)
|
||||||
|
|
||||||
def __str__(self) -> str: return self._content
|
def __str__(self) -> str: return self._content
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue