// Starlark AST node types.
// All nodes carry a Position for error reporting.
///|
/// Represents a literal value in the Starlark AST.
///
/// Variants:
///
/// - `LitInt` : An integer literal.
/// - `LitFloat` : A floating-point literal.
/// - `LitString` : A string literal.
/// - `LitBytes` : A bytes literal.
pub(all) enum LiteralVal {
LitInt(BigInt)
LitFloat(Double)
LitString(String)
LitBytes(Bytes)
}
///|
/// Represents a unary operator in the Starlark AST.
///
/// Variants:
///
/// - `OpPlus` : Unary `+`.
/// - `OpMinus` : Unary `-`.
/// - `OpBitNot` : Bitwise complement `~`.
/// - `OpNot` : Logical negation `not`.
pub(all) enum UnaryOp {
OpPlus
OpMinus
OpBitNot
OpNot
}
///|
/// Represents a binary operator in the Starlark AST.
///
/// Covers arithmetic, bitwise, comparison, membership, and logical operators.
pub(all) enum BinaryOp {
OpAdd
OpSub
OpMul
OpDiv
OpFloorDiv
OpMod
OpBitAnd
OpBitOr
OpBitXor
OpLShift
OpRShift
OpEq
OpNe
OpLt
OpLe
OpGt
OpGe
OpIn
OpNotIn
OpAnd
OpOr
}
///|
/// Represents an augmented-assignment operator in the Starlark AST.
///
/// Each variant corresponds to one of the `+=`, `-=`, `*=`, `/=`, `//=`,
/// `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=` forms.
pub(all) enum AugOp {
AugAdd
AugSub
AugMul
AugDiv
AugFloorDiv
AugMod
AugBitAnd
AugBitOr
AugBitXor
AugLShift
AugRShift
}
// Param and Expr are mutually recursive.
///|
/// Represents a single parameter in a function definition.
///
/// Variants:
///
/// - `ParamIdent` : A plain positional parameter `name`.
/// - `ParamDefault` : A parameter with a default value `name = expr`.
/// - `ParamStarBare` : A bare `*` separator (no name).
/// - `ParamStarIdent` : A `*name` variadic positional parameter.
/// - `ParamKwIdent` : A `**name` variadic keyword parameter.
///
/// Each variant carries the source `Position` of the parameter token.
pub(all) enum Param {
ParamIdent(String, @errors.Position)
ParamDefault(String, Expr, @errors.Position)
ParamStarBare(@errors.Position)
ParamStarIdent(String, @errors.Position)
ParamKwIdent(String, @errors.Position)
}
///|
/// Represents a single argument at a call site.
///
/// Variants:
///
/// - `ArgPos` : A positional argument `expr`.
/// - `ArgKw` : A keyword argument `name = expr`.
/// - `ArgStarArgs` : A `*expr` unpacked positional argument.
/// - `ArgKwArgs` : A `**expr` unpacked keyword argument.
///
/// `ArgKw`, `ArgStarArgs`, and `ArgKwArgs` carry the source `Position` of
/// the argument token.
pub(all) enum Arg {
ArgPos(Expr)
ArgKw(String, Expr, @errors.Position)
ArgStarArgs(@errors.Position, Expr)
ArgKwArgs(@errors.Position, Expr)
}
///|
/// Represents a single clause in a comprehension expression.
///
/// Variants:
///
/// - `ClauseFor` : A `for lhs in rhs` iteration clause.
/// - `ClauseIf` : A filtering `if cond` clause.
///
/// Each variant carries the source `Position` of the clause keyword.
pub(all) enum CompClause {
ClauseFor(Expr, Expr, @errors.Position)
ClauseIf(Expr, @errors.Position)
}
///|
/// Represents an expression node in the Starlark AST.
///
/// Every variant carries a source `Position` as its last field for error
/// reporting. Variants:
///
/// - `EIdent` : An identifier reference.
/// - `ELiteral` : A literal value.
/// - `EUnary` : A unary operation.
/// - `EBinary` : A binary operation.
/// - `ECond` : A conditional expression `t if cond else f`.
/// - `EIndex` : A subscript expression `obj[key]`.
/// - `ESlice` : A slice expression `obj[lo:hi:step]`; absent bounds are `None`.
/// - `EDot` : An attribute access `obj.attr`.
/// - `ECall` : A function call `fn(args...)`.
/// - `EList` : A list display `[...]`.
/// - `ETuple` : A tuple display `(...)`.
/// - `EDict` : A dict display `{k: v, ...}`.
/// - `ESet` : A set display `{...}`.
/// - `ELambda` : A lambda expression `lambda params: body`.
/// - `EListComp` : A list comprehension `[expr for ...]`.
/// - `ESetComp` : A set comprehension `{expr for ...}`.
/// - `EDictComp` : A dict comprehension `{k: v for ...}`.
pub(all) enum Expr {
EIdent(String, @errors.Position)
ELiteral(LiteralVal, @errors.Position)
EUnary(UnaryOp, Expr, @errors.Position)
EBinary(Expr, BinaryOp, Expr, @errors.Position)
ECond(Expr, Expr, Expr, @errors.Position)
EIndex(Expr, Expr, @errors.Position)
ESlice(Expr, Expr?, Expr?, Expr?, @errors.Position)
EDot(Expr, String, @errors.Position)
ECall(Expr, Array[Arg], @errors.Position)
EList(Array[Expr], @errors.Position)
ETuple(Array[Expr], @errors.Position)
EDict(Array[(Expr, Expr, @errors.Position)], @errors.Position)
ESet(Array[Expr], @errors.Position)
ELambda(Array[Param], Expr, @errors.Position)
EListComp(Expr, Array[CompClause], @errors.Position)
ESetComp(Expr, Array[CompClause], @errors.Position)
EDictComp(Expr, Expr, Array[CompClause], @errors.Position, @errors.Position)
}
///|
/// Represents a statement node in the Starlark AST.
///
/// Every variant (except `SExpr`) carries a source `Position` as its last
/// field for error reporting. Variants:
///
/// - `SExpr` : An expression used as a statement.
/// - `SAssign` : A simple assignment `lhs = rhs`.
/// - `SAugAssign` : An augmented assignment `lhs op= rhs`.
/// - `SIf` : An `if / else` block; the else branch may be empty.
/// - `SFor` : A `for` loop.
/// - `SWhile` : A `while` loop.
/// - `SDef` : A function definition `def name(params): body`.
/// - `SReturn` : A `return` statement; the expression is optional.
/// - `SBreak` : A `break` statement.
/// - `SContinue` : A `continue` statement.
/// - `SPass` : A `pass` statement.
/// - `SLoad` : A `load` statement; each binding is `(local, orig, pos)`.
pub(all) enum Stmt {
SExpr(Expr)
SAssign(Expr, Expr, @errors.Position)
SAugAssign(Expr, AugOp, Expr, @errors.Position)
SIf(Expr, Array[Stmt], Array[Stmt], @errors.Position)
SFor(Expr, Expr, Array[Stmt], @errors.Position)
SWhile(Expr, Array[Stmt], @errors.Position)
SDef(String, @errors.Position, Array[Param], Array[Stmt], @errors.Position)
SReturn(Expr?, @errors.Position)
SBreak(@errors.Position)
SContinue(@errors.Position)
SPass(@errors.Position)
SLoad(String, Array[(String, String, @errors.Position)], @errors.Position)
}
///|
/// A parsed Starlark source file: its filename and top-level statement list.
pub struct File {
priv path : String
priv stmts : Array[Stmt]
}
///|
/// Constructs a `File` with the given source path and top-level statement list.
///
/// Parameters:
///
/// - `path` : The source file path recorded in the AST.
/// - `stmts` : The top-level statements parsed from the file.
///
/// Returns a new `File` AST node.
pub fn File::new(path : String, stmts : Array[Stmt]) -> File {
{ path, stmts }
}
///|
/// Returns the source file path.
///
/// Parameters:
///
/// - `self` : The file node to inspect.
///
/// Returns the path string recorded in this `File`.
pub fn File::path(self : File) -> String {
self.path
}
///|
/// Returns the top-level statement list.
///
/// Parameters:
///
/// - `self` : The file node to inspect.
///
/// Returns the array of top-level `Stmt` nodes in this file.
pub fn File::stmts(self : File) -> Array[Stmt] {
self.stmts
}
///|
/// Returns the source position of an expression node.
///
/// Parameters:
///
/// - `e` : The expression node to inspect.
///
/// Returns the `Position` stored in the expression's position slot.
pub fn expr_pos(e : Expr) -> @errors.Position {
match e {
EIdent(_, p) => p
ELiteral(_, p) => p
EUnary(_, _, p) => p
EBinary(_, _, _, p) => p
ECond(_, _, _, p) => p
EIndex(_, _, p) => p
ESlice(_, _, _, _, p) => p
EDot(_, _, p) => p
ECall(_, _, p) => p
EList(_, p) => p
ETuple(_, p) => p
EDict(_, p) => p
ESet(_, p) => p
ELambda(_, _, p) => p
EListComp(_, _, p) => p
ESetComp(_, _, p) => p
EDictComp(_, _, _, _, p) => p
}
}
///|
/// Returns the position of the leftmost token in an expression.
///
/// Unlike `expr_pos`, which returns the position stored in the node's own
/// slot (operator, bracket, etc.), `start` walks into sub-expressions to
/// find the leftmost token of the whole expression. Used to anchor error
/// messages at the beginning of a compound LHS (e.g. `foobar` in
/// `foobar() = 2`). See the "Error-position anchoring policy" section in
/// `README.mbt.md` for the full set of anchoring rules.
///
/// Parameters:
///
/// - `e` : The expression node to inspect.
///
/// Returns the `Position` of the leftmost token.
pub fn start(e : Expr) -> @errors.Position {
match e {
EBinary(lhs, _, _, _) => start(lhs)
ECall(callee, _, _) => start(callee)
ESlice(x, _, _, _, _) => start(x)
EIndex(x, _, _) => start(x)
EDot(obj, _, _) => start(obj)
_ => expr_pos(e)
}
}
///|
/// Returns the source position of a statement node.
///
/// Parameters:
///
/// - `s` : The statement node to inspect.
///
/// Returns the `Position` stored in the statement's position slot.
pub fn stmt_pos(s : Stmt) -> @errors.Position {
match s {
SExpr(e) => expr_pos(e)
SAssign(_, _, p) => p
SAugAssign(_, _, _, p) => p
SIf(_, _, _, p) => p
SFor(_, _, _, p) => p
SWhile(_, _, p) => p
SDef(_, _, _, _, p) => p
SReturn(_, p) => p
SBreak(p) => p
SContinue(p) => p
SPass(p) => p
SLoad(_, _, p) => p
}
}