tests(parser): update snapshot with new syntax

This commit is contained in:
2026-05-21 15:04:32 +02:00
parent 5224e79d9f
commit 2f6e137f1a
3 changed files with 2487 additions and 862 deletions

View File

@@ -1,14 +1,24 @@
from typing import Optional, Sequence
from core.ast.midas import ( from core.ast.midas import (
ConstraintExpr, BinaryExpr,
ConstraintStmt, ComplexTypeStmt,
Expr, Expr,
ExtendStmt,
GetExpr,
GroupingExpr,
LiteralExpr, LiteralExpr,
LogicalExpr,
OpStmt, OpStmt,
PredicateStmt,
PropertyStmt, PropertyStmt,
SimpleTypeExpr,
SimpleTypeStmt,
Stmt, Stmt,
TypeBodyExpr, TemplateExpr,
TypeExpr, TypeExpr,
TypeStmt, UnaryExpr,
VariableExpr,
WildcardExpr, WildcardExpr,
) )
@@ -19,42 +29,29 @@ class AstJsonSerializer(Stmt.Visitor[dict], Expr.Visitor[dict]):
def serialize(self, stmts: list[Stmt]) -> list[dict]: def serialize(self, stmts: list[Stmt]) -> list[dict]:
return [stmt.accept(self) for stmt in stmts] return [stmt.accept(self) for stmt in stmts]
def visit_type_stmt(self, stmt: TypeStmt) -> dict: def _serialize_optional(self, element: Optional[Stmt | Expr]) -> Optional[dict]:
if element is None:
return None
return element.accept(self)
def _serialize_list(self, elements: Sequence[Stmt | Expr]) -> list[dict]:
return [element.accept(self) for element in elements]
def visit_simple_type_stmt(self, stmt: SimpleTypeStmt) -> dict:
return { return {
"_type": "TypeStmt", "_type": "SimpleTypeStmt",
"template": self._serialize_optional(stmt.template),
"name": stmt.name.lexeme, "name": stmt.name.lexeme,
"bases": [base.accept(self) for base in stmt.bases], "base": stmt.base.accept(self),
"body": stmt.body.accept(self) if stmt.body is not None else None, "constraint": self._serialize_optional(stmt.constraint),
} }
def visit_type_expr(self, expr: TypeExpr) -> dict: def visit_complex_type_stmt(self, stmt: ComplexTypeStmt) -> dict:
return { return {
"_type": "TypeExpr", "_type": "ComplexTypeStmt",
"name": expr.name.lexeme, "name": stmt.name.lexeme,
"constraints": [constraint.accept(self) for constraint in expr.constraints], "template": self._serialize_optional(stmt.template),
} "properties": self._serialize_list(stmt.properties),
def visit_constraint_expr(self, expr: ConstraintExpr) -> dict:
return {
"_type": "ConstraintExpr",
"left": expr.left.accept(self),
"op": expr.op.lexeme,
"right": expr.right.accept(self),
}
def visit_wildcard_expr(self, expr: WildcardExpr) -> dict:
return {"_type": "WildcardExpr"}
def visit_literal_expr(self, expr: LiteralExpr) -> dict:
return {
"_type": "LiteralExpr",
"value": expr.value,
}
def visit_type_body_expr(self, expr: TypeBodyExpr) -> dict:
return {
"_type": "TypeBodyExpr",
"properties": [prop.accept(self) for prop in expr.properties],
} }
def visit_property_stmt(self, stmt: PropertyStmt) -> dict: def visit_property_stmt(self, stmt: PropertyStmt) -> dict:
@@ -62,20 +59,101 @@ class AstJsonSerializer(Stmt.Visitor[dict], Expr.Visitor[dict]):
"_type": "PropertyStmt", "_type": "PropertyStmt",
"name": stmt.name.lexeme, "name": stmt.name.lexeme,
"type": stmt.type.accept(self), "type": stmt.type.accept(self),
"constraint": self._serialize_optional(stmt.constraint),
}
def visit_extend_stmt(self, stmt: ExtendStmt) -> dict:
return {
"_type": "ExtendStmt",
"type": stmt.type.accept(self),
"operations": self._serialize_list(stmt.operations),
} }
def visit_op_stmt(self, stmt: OpStmt) -> dict: def visit_op_stmt(self, stmt: OpStmt) -> dict:
return { return {
"_type": "OpStmt", "_type": "OpStmt",
"left": stmt.left.accept(self), "name": stmt.name.lexeme,
"op": stmt.op.lexeme, "operand": stmt.operand.accept(self),
"right": stmt.right.accept(self),
"result": stmt.result.accept(self), "result": stmt.result.accept(self),
} }
def visit_constraint_stmt(self, stmt: ConstraintStmt) -> dict: def visit_predicate_stmt(self, stmt: PredicateStmt) -> dict:
return { return {
"_type": "ConstraintStmt", "_type": "PredicateStmt",
"name": stmt.name.lexeme, "name": stmt.name.lexeme,
"constraint": stmt.constraint.accept(self), "subject": stmt.subject.lexeme,
"type": stmt.type.accept(self),
"condition": stmt.condition.accept(self),
}
def visit_simple_type_expr(self, expr: SimpleTypeExpr) -> dict:
return {
"_type": "SimpleTypeExpr",
"name": expr.name.lexeme,
"optional": expr.optional,
}
def visit_logical_expr(self, expr: LogicalExpr) -> dict:
return {
"_type": "LogicalExpr",
"left": expr.left.accept(self),
"operator": expr.operator.lexeme,
"right": expr.right.accept(self),
}
def visit_binary_expr(self, expr: BinaryExpr) -> dict:
return {
"_type": "BinaryExpr",
"left": expr.left.accept(self),
"operator": expr.operator.lexeme,
"right": expr.right.accept(self),
}
def visit_unary_expr(self, expr: UnaryExpr) -> dict:
return {
"_type": "UnaryExpr",
"operator": expr.operator.lexeme,
"right": expr.right.accept(self),
}
def visit_get_expr(self, expr: GetExpr) -> dict:
return {
"_type": "GetExpr",
"expr": expr.expr.accept(self),
"name": expr.name.lexeme,
}
def visit_variable_expr(self, expr: VariableExpr) -> dict:
return {
"_type": "VariableExpr",
"name": expr.name.lexeme,
}
def visit_grouping_expr(self, expr: GroupingExpr) -> dict:
return {
"_type": "GroupingExpr",
"expr": expr.expr.accept(self),
}
def visit_literal_expr(self, expr: LiteralExpr) -> dict:
return {
"_type": "LiteralExpr",
"value": expr.value,
}
def visit_wildcard_expr(self, expr: WildcardExpr) -> dict:
return {"_type": "WildcardExpr"}
def visit_template_expr(self, expr: TemplateExpr) -> dict:
return {
"_type": "TemplateExpr",
"type": expr.type.accept(self),
}
def visit_type_expr(self, expr: TypeExpr) -> dict:
return {
"_type": "TypeExpr",
"name": expr.name.lexeme,
"template": self._serialize_optional(expr.template),
"optional": expr.optional,
} }

View File

@@ -1,24 +1,57 @@
// Simple custom type derived from floats // Simple custom type derived from float
type Latitude<float> type Custom(float)
type Longitude<float>
// Simple custom types with constraints
type Latitude(float) where (-90 <= _ <= 90)
type Longitude(float) where (-180 <= _ <= 180)
// Generic custom type (a Difference of T is derived from T, e.g. a difference of floats is a float
type Difference[T](T)
// Complex custom type, containing two values accessible through properties // Complex custom type, containing two values accessible through properties
type GeoLocation<Latitude, Longitude> { type GeoLocation {
lat: Latitude lat: Latitude
lon: Longitude lon: Longitude
} }
type LatitudeDiff<float> // Define operations on our custom type
type LongitudeDiff<float> extend GeoLocation {
// This type is compatible with the `-` operation with another GeoLocation
// i.e. you can subtract a GeoLocation from another GeoLocation, resulting
// in a Difference of GeoLocations
op __sub__(GeoLocation) -> Difference[GeoLocation]
}
// For complex generics, you need to specify how the genericity the properties
// are handled
type Difference[GeoLocation] {
lat: Difference[Latitude]
lon: Difference[Longitude]
}
// Simple operation defined on our custom types // Simple operation defined on our custom types
op <Latitude> - <Latitude> = <LatitudeDiff> extend Latitude {
op <Longitude> - <Longitude> = <LongitudeDiff> op __sub__(Latitude) -> Difference[Latitude]
}
// Simple custom type with a constraint extend Longitude {
type Age<int + (0 <= _) + (_ < 150)> op __sub__(Longitude) -> Difference[Longitude]
}
// Predefined custom constraints that can be referenced in other definitions // Predefined custom predicates that can be referenced in other definitions
constraint Positive = _ >= 0 predicate Positive(v: float) = v >= 0
constraint StrictlyPositive = _ > 0 predicate StrictlyPositive(v: float) = v > 0
//constraint Even = _ % 2 == 0 predicate Equatorial(loc: GeoLocation) = (-10 <= loc.lat <= 10)
predicate Arctic(loc: GeoLocation) = (loc.lat >= 66)
type Person {
name: str
// Property with an inline constraint
age: int? where (0 <= _ < 150)
// Property referencing a predicate
height: float where StrictlyPositive
home: GeoLocation
}

File diff suppressed because it is too large Load Diff