use depyler_annotations::TranspilationAnnotations;
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
pub type Symbol = String;
#[cfg(test)]
#[macro_export]
macro_rules! params {
() => {
smallvec::smallvec![]
};
($($param:expr),* $(,)?) => {
smallvec::smallvec![$($param),*]
};
}
#[cfg(test)]
#[macro_export]
macro_rules! param {
($name:expr, $ty:expr) => {
$crate::hir::HirParam::new($name.to_string(), $ty)
};
}
#[cfg(test)]
#[macro_export]
macro_rules! param_with_default {
($name:expr, $ty:expr, $default:expr) => {
$crate::hir::HirParam::with_default($name.to_string(), $ty, $default)
};
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirModule {
pub functions: Vec<HirFunction>,
pub imports: Vec<Import>,
pub type_aliases: Vec<TypeAlias>,
pub protocols: Vec<Protocol>,
pub classes: Vec<HirClass>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirProgram {
pub functions: Vec<HirFunction>,
pub classes: Vec<HirClass>,
pub imports: Vec<Import>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Import {
pub module: String,
pub items: Vec<ImportItem>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ImportItem {
Named(String),
Aliased { name: String, alias: String },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TypeAlias {
pub name: String,
pub target_type: Type,
pub is_newtype: bool, }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Protocol {
pub name: String,
pub type_params: Vec<String>, pub methods: Vec<ProtocolMethod>,
pub is_runtime_checkable: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ProtocolMethod {
pub name: String,
pub params: SmallVec<[HirParam; 4]>,
pub ret_type: Type,
pub is_optional: bool,
pub has_default: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirClass {
pub name: String,
pub base_classes: Vec<String>, pub methods: Vec<HirMethod>,
pub fields: Vec<HirField>,
pub is_dataclass: bool,
pub docstring: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirMethod {
pub name: String,
pub params: SmallVec<[HirParam; 4]>,
pub ret_type: Type,
pub body: Vec<HirStmt>,
pub is_static: bool,
pub is_classmethod: bool,
pub is_property: bool,
pub is_async: bool,
pub docstring: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirField {
pub name: String,
pub field_type: Type,
pub default_value: Option<HirExpr>,
pub is_class_var: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirParam {
pub name: Symbol,
pub ty: Type,
pub default: Option<HirExpr>,
}
impl HirParam {
pub fn new(name: Symbol, ty: Type) -> Self {
Self {
name,
ty,
default: None,
}
}
pub fn with_default(name: Symbol, ty: Type, default: HirExpr) -> Self {
Self {
name,
ty,
default: Some(default),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirFunction {
pub name: Symbol,
pub params: SmallVec<[HirParam; 4]>, pub ret_type: Type,
pub body: Vec<HirStmt>,
pub properties: FunctionProperties,
pub annotations: TranspilationAnnotations,
pub docstring: Option<String>,
}
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionProperties {
pub is_pure: bool,
pub max_stack_depth: Option<usize>,
pub always_terminates: bool,
pub panic_free: bool,
pub can_fail: bool,
pub error_types: Vec<String>,
pub is_async: bool,
pub is_generator: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AssignTarget {
Symbol(Symbol),
Index {
base: Box<HirExpr>,
index: Box<HirExpr>,
},
Attribute { value: Box<HirExpr>, attr: Symbol },
Tuple(Vec<AssignTarget>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum HirStmt {
Assign {
target: AssignTarget,
value: HirExpr,
type_annotation: Option<Type>,
},
Return(Option<HirExpr>),
If {
condition: HirExpr,
then_body: Vec<HirStmt>,
else_body: Option<Vec<HirStmt>>,
},
While {
condition: HirExpr,
body: Vec<HirStmt>,
},
For {
target: AssignTarget,
iter: HirExpr,
body: Vec<HirStmt>,
},
Expr(HirExpr),
Raise {
exception: Option<HirExpr>,
cause: Option<HirExpr>,
},
Break {
label: Option<Symbol>,
},
Continue {
label: Option<Symbol>,
},
With {
context: HirExpr,
target: Option<Symbol>,
body: Vec<HirStmt>,
},
Try {
body: Vec<HirStmt>,
handlers: Vec<ExceptHandler>,
orelse: Option<Vec<HirStmt>>,
finalbody: Option<Vec<HirStmt>>,
},
Assert {
test: HirExpr,
msg: Option<HirExpr>,
},
Pass,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExceptHandler {
pub exception_type: Option<String>,
pub name: Option<Symbol>,
pub body: Vec<HirStmt>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum HirExpr {
Literal(Literal),
Var(Symbol),
Binary {
op: BinOp,
left: Box<HirExpr>,
right: Box<HirExpr>,
},
Unary {
op: UnaryOp,
operand: Box<HirExpr>,
},
Call {
func: Symbol,
args: Vec<HirExpr>,
},
MethodCall {
object: Box<HirExpr>,
method: Symbol,
args: Vec<HirExpr>,
},
Index {
base: Box<HirExpr>,
index: Box<HirExpr>,
},
Slice {
base: Box<HirExpr>,
start: Option<Box<HirExpr>>,
stop: Option<Box<HirExpr>>,
step: Option<Box<HirExpr>>,
},
Attribute {
value: Box<HirExpr>,
attr: Symbol,
},
List(Vec<HirExpr>),
Dict(Vec<(HirExpr, HirExpr)>),
Tuple(Vec<HirExpr>),
Set(Vec<HirExpr>),
FrozenSet(Vec<HirExpr>),
Borrow {
expr: Box<HirExpr>,
mutable: bool,
},
ListComp {
element: Box<HirExpr>,
target: Symbol,
iter: Box<HirExpr>,
condition: Option<Box<HirExpr>>,
},
SetComp {
element: Box<HirExpr>,
target: Symbol,
iter: Box<HirExpr>,
condition: Option<Box<HirExpr>>,
},
DictComp {
key: Box<HirExpr>,
value: Box<HirExpr>,
target: Symbol,
iter: Box<HirExpr>,
condition: Option<Box<HirExpr>>,
},
Lambda {
params: Vec<Symbol>,
body: Box<HirExpr>,
},
Await {
value: Box<HirExpr>,
},
FString {
parts: Vec<FStringPart>,
},
Yield {
value: Option<Box<HirExpr>>,
},
IfExpr {
test: Box<HirExpr>,
body: Box<HirExpr>,
orelse: Box<HirExpr>,
},
SortByKey {
iterable: Box<HirExpr>,
key_params: Vec<Symbol>,
key_body: Box<HirExpr>,
reverse: bool,
},
GeneratorExp {
element: Box<HirExpr>,
generators: Vec<HirComprehension>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HirComprehension {
pub target: Symbol,
pub iter: Box<HirExpr>,
pub conditions: Vec<HirExpr>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum FStringPart {
Literal(String),
Expr(Box<HirExpr>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Int(i64),
Float(f64),
String(String),
Bool(bool),
None,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
FloorDiv,
Mod,
Pow,
Eq,
NotEq,
Lt,
LtEq,
Gt,
GtEq,
And,
Or,
BitAnd,
BitOr,
BitXor,
LShift,
RShift,
In,
NotIn,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOp {
Not,
Neg,
Pos,
BitNot,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ConstGeneric {
Literal(usize),
Parameter(String),
Expression(String),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Type {
Unknown,
Int,
Float,
String,
Bool,
None,
List(Box<Type>),
Dict(Box<Type>, Box<Type>),
Tuple(Vec<Type>),
Set(Box<Type>),
Optional(Box<Type>),
Function {
params: Vec<Type>,
ret: Box<Type>,
},
Custom(String),
TypeVar(String),
Generic {
base: String,
params: Vec<Type>,
},
Union(Vec<Type>),
Array {
element_type: Box<Type>,
size: ConstGeneric,
},
}
impl Type {
pub fn is_numeric(&self) -> bool {
matches!(self, Type::Int | Type::Float)
}
pub fn is_container(&self) -> bool {
matches!(
self,
Type::List(_) | Type::Dict(_, _) | Type::Tuple(_) | Type::Set(_) | Type::Array { .. }
)
}
}