#![doc = include_str!("readme.md")]
use core::range::Range;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct PythonRoot {
pub program: Program,
#[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
pub span: Range<usize>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Program {
pub statements: Vec<Statement>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum Statement {
FunctionDef {
decorators: Vec<Expression>,
name: String,
parameters: Vec<Parameter>,
return_type: Option<Type>,
body: Vec<Statement>,
},
AsyncFunctionDef {
decorators: Vec<Expression>,
name: String,
parameters: Vec<Parameter>,
return_type: Option<Type>,
body: Vec<Statement>,
},
ClassDef {
decorators: Vec<Expression>,
name: String,
bases: Vec<Expression>,
body: Vec<Statement>,
},
Assignment {
target: Expression,
value: Expression,
},
AugmentedAssignment {
target: Expression,
operator: AugmentedOperator,
value: Expression,
},
Expression(Expression),
Return(Option<Expression>),
If {
test: Expression,
body: Vec<Statement>,
orelse: Vec<Statement>,
},
For {
target: Expression,
iter: Expression,
body: Vec<Statement>,
orelse: Vec<Statement>,
},
AsyncFor {
target: Expression,
iter: Expression,
body: Vec<Statement>,
orelse: Vec<Statement>,
},
While {
test: Expression,
body: Vec<Statement>,
orelse: Vec<Statement>,
},
Break,
Continue,
Pass,
Import {
names: Vec<ImportName>,
},
ImportFrom {
module: Option<String>,
names: Vec<ImportName>,
},
Global {
names: Vec<String>,
},
Nonlocal {
names: Vec<String>,
},
Try {
body: Vec<Statement>,
handlers: Vec<ExceptHandler>,
orelse: Vec<Statement>,
finalbody: Vec<Statement>,
},
Raise {
exc: Option<Expression>,
cause: Option<Expression>,
},
With {
items: Vec<WithItem>,
body: Vec<Statement>,
},
AsyncWith {
items: Vec<WithItem>,
body: Vec<Statement>,
},
Assert {
test: Expression,
msg: Option<Expression>,
},
Match {
subject: Expression,
cases: Vec<MatchCase>,
},
Delete {
targets: Vec<Expression>,
},
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct MatchCase {
pub pattern: Pattern,
pub guard: Option<Expression>,
pub body: Vec<Statement>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum Pattern {
Value(Expression),
Wildcard,
As {
pattern: Option<Box<Pattern>>,
name: String,
},
Sequence(Vec<Pattern>),
Mapping {
keys: Vec<Expression>,
patterns: Vec<Pattern>,
},
Class {
cls: Expression,
patterns: Vec<Pattern>,
keywords: Vec<String>,
keyword_patterns: Vec<Pattern>,
},
Or(Vec<Pattern>),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
Literal(Literal),
Name(String),
BinaryOp {
left: Box<Expression>,
operator: BinaryOperator,
right: Box<Expression>,
},
UnaryOp {
operator: UnaryOperator,
operand: Box<Expression>,
},
BoolOp {
operator: BoolOperator,
values: Vec<Expression>,
},
Compare {
left: Box<Expression>,
ops: Vec<CompareOperator>,
comparators: Vec<Expression>,
},
Call {
func: Box<Expression>,
args: Vec<Expression>,
keywords: Vec<Keyword>,
},
Attribute {
value: Box<Expression>,
attr: String,
},
Subscript {
value: Box<Expression>,
slice: Box<Expression>,
},
List {
elts: Vec<Expression>,
},
Tuple {
elts: Vec<Expression>,
},
Slice {
lower: Option<Box<Expression>>,
upper: Option<Box<Expression>>,
step: Option<Box<Expression>>,
},
Dict {
keys: Vec<Option<Expression>>,
values: Vec<Expression>,
},
Set {
elts: Vec<Expression>,
},
ListComp {
elt: Box<Expression>,
generators: Vec<Comprehension>,
},
DictComp {
key: Box<Expression>,
value: Box<Expression>,
generators: Vec<Comprehension>,
},
SetComp {
elt: Box<Expression>,
generators: Vec<Comprehension>,
},
GeneratorExp {
elt: Box<Expression>,
generators: Vec<Comprehension>,
},
Lambda {
args: Vec<Parameter>,
body: Box<Expression>,
},
IfExp {
test: Box<Expression>,
body: Box<Expression>,
orelse: Box<Expression>,
},
JoinedStr {
values: Vec<Expression>,
},
FormattedValue {
value: Box<Expression>,
conversion: usize,
format_spec: Option<Box<Expression>>,
},
Yield(Option<Box<Expression>>),
YieldFrom(Box<Expression>),
Await(Box<Expression>),
Starred {
value: Box<Expression>,
is_double: bool,
},
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
Integer(i64),
Float(f64),
String(String),
Bytes(Vec<u8>),
Boolean(bool),
None,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum AugmentedOperator {
Add,
Sub,
Mult,
Div,
FloorDiv,
Mod,
Pow,
LShift,
RShift,
BitOr,
BitXor,
BitAnd,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum BinaryOperator {
Add,
Sub,
Mult,
Div,
FloorDiv,
Mod,
Pow,
LShift,
RShift,
BitOr,
BitXor,
BitAnd,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum UnaryOperator {
Invert,
Not,
UAdd,
USub,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum BoolOperator {
And,
Or,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum CompareOperator {
Eq,
NotEq,
Lt,
LtE,
Gt,
GtE,
Is,
IsNot,
In,
NotIn,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Parameter {
pub name: String,
pub annotation: Option<Type>,
pub default: Option<Expression>,
pub is_vararg: bool,
pub is_kwarg: bool,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum Type {
Name(String),
Generic {
name: String,
args: Vec<Type>,
},
Union(Vec<Type>),
Optional(Box<Type>),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Keyword {
pub arg: Option<String>,
pub value: Expression,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Comprehension {
pub target: Expression,
pub iter: Expression,
pub ifs: Vec<Expression>,
pub is_async: bool,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct ImportName {
pub name: String,
pub asname: Option<String>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct ExceptHandler {
pub type_: Option<Expression>,
pub name: Option<String>,
pub body: Vec<Statement>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct WithItem {
pub context_expr: Expression,
pub optional_vars: Option<Expression>,
}
impl Program {
pub fn new() -> Self {
Self { statements: Vec::new() }
}
pub fn add_statement(&mut self, statement: Statement) {
self.statements.push(statement)
}
}
impl Default for Program {
fn default() -> Self {
Self::new()
}
}
impl Expression {
pub fn name(name: impl Into<String>) -> Self {
Self::Name(name.into())
}
pub fn string(value: impl Into<String>) -> Self {
Self::Literal(Literal::String(value.into()))
}
pub fn integer(value: i64) -> Self {
Self::Literal(Literal::Integer(value))
}
pub fn float(value: f64) -> Self {
Self::Literal(Literal::Float(value))
}
pub fn boolean(value: bool) -> Self {
Self::Literal(Literal::Boolean(value))
}
pub fn none() -> Self {
Self::Literal(Literal::None)
}
}
impl Statement {
pub fn function_def(name: impl Into<String>, parameters: Vec<Parameter>, return_type: Option<Type>, body: Vec<Statement>) -> Self {
Self::FunctionDef { decorators: Vec::new(), name: name.into(), parameters, return_type, body }
}
pub fn assignment(target: Expression, value: Expression) -> Self {
Self::Assignment { target, value }
}
pub fn expression(expr: Expression) -> Self {
Self::Expression(expr)
}
pub fn return_stmt(value: Option<Expression>) -> Self {
Self::Return(value)
}
}