python-plus-plus/ppp_ast.py

522 lines
10 KiB
Python

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Dict, List, Optional, Tuple
### Types ###
class TypeExpression(ABC):
@abstractmethod
def represent(self) -> str: ...
@dataclass
class TupleTypeExpr(TypeExpression):
types: List[TypeExpression]
def represent(self) -> str:
return f"({', '.join([type.represent() for type in self.types])})"
@dataclass
class ListTypeExpr(TypeExpression):
type: TypeExpression
def represent(self) -> str:
return self.type.represent()+"[]"
@dataclass
class ArrayTypeExpr(TypeExpression):
type: TypeExpression
number: int
def represent(self) -> str:
return self.type.represent()+f"[{self.number}]"
@dataclass
class TypeName(TypeExpression):
name: str
def represent(self) -> str:
return self.name
@dataclass
class TypeSpecification(TypeExpression):
type: TypeExpression
types: List[TypeExpression]
def represent(self) -> str:
return f'{self.type.represent()}<{', '.join([type.represent() for type in self.types])}>'
@dataclass
class FunctionTypeExpr(TypeExpression):
arguments: List[TypeExpression]
return_type: TypeExpression
def represent(self) -> str:
assert False, ("Unimplemented")
### Statements ###
class Statement:
pass
@dataclass
class Statements(Statement):
statements: List[Statement]
### Enums + Struct ###
@dataclass
class EnumEntry:
name: str
types: List[TypeExpression]
@dataclass
class EnumDefinition(Statement):
name: str
entries: List[EnumEntry]
@dataclass
class TypeDeclaration:
name: str
type: TypeExpression
def represent(self) -> str:
return f"{self.name}: {self.type.represent()}"
@dataclass
class StructDefinition(Statement):
name: str
entries: List[TypeDeclaration]
### Function ###
@dataclass
class FunctionDefinition(Statement):
name: str
arguments: list[TypeDeclaration]
return_type: Optional[TypeExpression]
body: Statement
### Expressions ###
class Expression(ABC):
@abstractmethod
def precedence(self) -> int: ...
@abstractmethod
def represent(self) -> str: ...
def wrap(self, other: 'Expression') -> str:
if self.precedence() > other.precedence(): return '('+other.represent()+')'
return other.represent()
@dataclass
class FunctionCall(Expression):
function: Expression
arguments: List[Expression]
def represent(self) -> str:
return self.wrap(self.function)+"("+', '.join([argument.represent() for argument in self.arguments])+")"
def precedence(self) -> int: return 13
@dataclass
class Variable(Expression):
name: str
def represent(self) -> str:
return self.name
def precedence(self) -> int: return 13
@dataclass
class ArrayAccess(Expression):
array: Expression
index: Expression
def represent(self) -> str:
return self.wrap(self.array)+"["+self.index.represent()+"]"
def precedence(self) -> int: return 13
@dataclass
class Array(Expression):
element_type: TypeExpression
array: List[Expression]
def represent(self) -> str:
return f"[:{self.element_type.represent()}{''.join([', '+element.represent() for element in self.array])}]"
def precedence(self) -> int: return 13
@dataclass
class FieldAccess(Expression):
expression: Expression
field: str
def represent(self) -> str:
return self.wrap(self.expression)+"."+self.field
def precedence(self) -> int: return 13
@dataclass
class Number(Expression):
number: int
def represent(self) -> str:
return str(self.number)
def precedence(self) -> int: return 13
@dataclass
class String(Expression):
string: str
def represent(self) -> str:
return repr(self.string)
def precedence(self) -> int: return 13
@dataclass
class TupleExpr(Expression):
elements: List[Expression]
def represent(self) -> str:
return f"({', '.join([element.represent() for element in self.elements])})"
def precedence(self) -> int: return 13
@dataclass
class StructInstantiation(Expression):
struct: Expression
arguments: List[Tuple[str, Expression]]
def represent(self) -> str:
assert False, ("Unimplemented")
def precedence(self) -> int: return 13
@dataclass
class LoopComprehension(Expression):
element_type: TypeExpression
body: Expression
variable: str # TODO: Pattern matching
array: Expression
def represent(self) -> str:
return f"[:{self.element_type.represent()}, {self.body.represent()} for {self.variable} in {self.array.represent()}]"
def precedence(self) -> int: return 13
@dataclass
class Lambda(Expression):
parameters: List[TypeDeclaration]
expression: Expression
def represent(self) -> str:
return f"lambda {', '.join([parameter.represent() for parameter in self.parameters])} => {self.expression.represent()}"
def precedence(self) -> int: return 0
@dataclass
class Ternary(Expression):
condition: Expression
if_true: Expression
if_false: Expression
def represent(self) -> str:
return self.wrap(self.if_true)+" if "+self.wrap(self.condition)+" else "+self.wrap(self.if_false)
def precedence(self) -> int: return 1
@dataclass
class Or(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" or "+self.wrap(self.rhs)
def precedence(self) -> int: return 2
@dataclass
class And(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" and "+self.wrap(self.rhs)
def precedence(self) -> int: return 3
@dataclass
class Bor(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" | "+self.wrap(self.rhs)
def precedence(self) -> int: return 4
@dataclass
class Bxor(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" ^ "+self.wrap(self.rhs)
def precedence(self) -> int: return 5
@dataclass
class Band(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" & "+self.wrap(self.rhs)
def precedence(self) -> int: return 6
@dataclass
class Equal(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" == "+self.wrap(self.rhs)
def precedence(self) -> int: return 7
@dataclass
class NotEqual(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" != "+self.wrap(self.rhs)
def precedence(self) -> int: return 7
@dataclass
class LessThan(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" < "+self.wrap(self.rhs)
def precedence(self) -> int: return 8
@dataclass
class GreaterThan(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" > "+self.wrap(self.rhs)
def precedence(self) -> int: return 8
@dataclass
class LessThanOrEqual(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" <= "+self.wrap(self.rhs)
def precedence(self) -> int: return 8
@dataclass
class GreaterThanOrEqual(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" >= "+self.wrap(self.rhs)
def precedence(self) -> int: return 8
@dataclass
class ShiftLeft(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" << "+self.wrap(self.rhs)
def precedence(self) -> int: return 9
@dataclass
class ShiftRight(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" >> "+self.wrap(self.rhs)
def precedence(self) -> int: return 9
@dataclass
class Addition(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" + "+self.wrap(self.rhs)
def precedence(self) -> int: return 10
@dataclass
class Subtract(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" - "+self.wrap(self.rhs)
def precedence(self) -> int: return 10
@dataclass
class Multiplication(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" * "+self.wrap(self.rhs)
def precedence(self) -> int: return 11
@dataclass
class Division(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" / "+self.wrap(self.rhs)
def precedence(self) -> int: return 11
@dataclass
class Modulo(Expression):
lhs: Expression
rhs: Expression
def represent(self) -> str:
return self.wrap(self.lhs)+" % "+self.wrap(self.rhs)
def precedence(self) -> int: return 11
@dataclass
class Bnot(Expression):
expression: Expression
def represent(self) -> str:
return "~"+self.wrap(self.expression)
def precedence(self) -> int: return 12
@dataclass
class Not(Expression):
expression: Expression
def represent(self) -> str:
return "!"+self.wrap(self.expression)
def precedence(self) -> int: return 12
@dataclass
class UnaryPlus(Expression):
expression: Expression
def represent(self) -> str:
return "+"+self.wrap(self.expression)
def precedence(self) -> int: return 12
@dataclass
class UnaryMinus(Expression):
expression: Expression
def represent(self) -> str:
return "-"+self.wrap(self.expression)
def precedence(self) -> int: return 12
@dataclass
class ExpressionStatement(Statement):
expression: Expression
### Assignment + Declaration ###
@dataclass
class Assignment(Statement):
lhs: Expression
rhs: Expression
type: Optional[TypeExpression] = None
@dataclass
class TypeDeclarationStatement(Statement):
type_declaration: TypeDeclaration
### Control flow ###
@dataclass
class IfStatement(Statement):
condition: Expression
body: Statement
else_body: Optional[Statement]
@dataclass
class WhileStatement(Statement):
condition: Expression
body: Statement
@dataclass
class DoWhileStatement(Statement):
body: Statement
condition: Optional[Expression]
@dataclass
class BreakStatement(Statement):
pass
@dataclass
class ContinueStatement(Statement):
pass
@dataclass
class ReturnStatement(Statement):
expression: Expression
@dataclass
class MatchStatement(Statement):
value: Expression
cases: List[Tuple[Expression, Statement]]
@dataclass
class AssertStatement(Statement):
condition: Expression
message: Optional[Expression]
@dataclass
class ForLoop(Statement):
variable: str # TODO allow for pattern matching
array: Expression
body: Statement
@dataclass
class Import(Statement):
file: str
@dataclass
class TypeDefinition(Statement):
name: str
expression: TypeExpression
@dataclass
class DeferStatement(Statement):
statement: Statement