1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
use std::convert::TryFrom;
use std::fmt::{Display, Formatter};

use crate::ASTTy;
use crate::check::context::function;
use crate::generate::result::UnimplementedErr;
use crate::parse::ast::node_op::NodeOp;

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum Core {
    Import { from: Option<Box<Core>>, import: Vec<Core>, alias: Vec<Core> },
    ClassDef { name: Box<Core>, parent_names: Vec<Core>, body: Box<Core> },
    FunctionCall { function: Box<Core>, args: Vec<Core> },
    PropertyCall { object: Box<Core>, property: Box<Core> },
    Id { lit: String },
    Type { lit: String, generics: Vec<Core> },
    ExpressionType { expr: Box<Core>, ty: Box<Core> },
    Assign { left: Box<Core>, right: Box<Core>, op: CoreOp },
    VarDef { var: Box<Core>, ty: Option<Box<Core>>, expr: Option<Box<Core>> },
    FunDefOp { op: CoreFunOp, arg: Vec<Core>, ty: Option<Box<Core>>, body: Box<Core> },
    FunDef { dec: Vec<String>, id: String, arg: Vec<Core>, ty: Option<Box<Core>>, body: Box<Core> },
    FunArg { vararg: bool, var: Box<Core>, ty: Option<Box<Core>>, default: Option<Box<Core>> },
    AnonFun { args: Vec<Core>, body: Box<Core> },
    Block { statements: Vec<Core> },
    Float { float: String },
    Int { int: String },
    ENum { num: String, exp: String },
    DocStr { string: String },
    Str { string: String },
    FStr { string: String },
    Bool { boolean: bool },
    Tuple { elements: Vec<Core> },
    TupleLiteral { elements: Vec<Core> },
    DictComprehension { from: Box<Core>, to: Box<Core>, col: Box<Core>, conds: Vec<Core> },
    Comprehension { expr: Box<Core>, col: Box<Core>, conds: Vec<Core> },
    Dictionary { elements: Vec<(Core, Core)> },
    Set { elements: Vec<Core> },
    List { elements: Vec<Core> },
    Index { item: Box<Core>, range: Box<Core> },
    Ge { left: Box<Core>, right: Box<Core> },
    Geq { left: Box<Core>, right: Box<Core> },
    Le { left: Box<Core>, right: Box<Core> },
    Leq { left: Box<Core>, right: Box<Core> },
    Not { expr: Box<Core> },
    Is { left: Box<Core>, right: Box<Core> },
    IsN { left: Box<Core>, right: Box<Core> },
    Eq { left: Box<Core>, right: Box<Core> },
    Neq { left: Box<Core>, right: Box<Core> },
    IsA { left: Box<Core>, right: Box<Core> },
    And { left: Box<Core>, right: Box<Core> },
    Or { left: Box<Core>, right: Box<Core> },
    Add { left: Box<Core>, right: Box<Core> },
    AddU { expr: Box<Core> },
    Sub { left: Box<Core>, right: Box<Core> },
    SubU { expr: Box<Core> },
    Mul { left: Box<Core>, right: Box<Core> },
    Mod { left: Box<Core>, right: Box<Core> },
    Pow { left: Box<Core>, right: Box<Core> },
    Div { left: Box<Core>, right: Box<Core> },
    FDiv { left: Box<Core>, right: Box<Core> },
    Sqrt { expr: Box<Core> },
    BAnd { left: Box<Core>, right: Box<Core> },
    BOr { left: Box<Core>, right: Box<Core> },
    BXOr { left: Box<Core>, right: Box<Core> },
    BOneCmpl { expr: Box<Core> },
    BLShift { left: Box<Core>, right: Box<Core> },
    BRShift { left: Box<Core>, right: Box<Core> },
    For { expr: Box<Core>, col: Box<Core>, body: Box<Core> },
    If { cond: Box<Core>, then: Box<Core> },
    IfElse { cond: Box<Core>, then: Box<Core>, el: Box<Core> },
    Match { expr: Box<Core>, cases: Vec<Core> },
    Case { expr: Box<Core>, body: Box<Core> },
    Ternary { cond: Box<Core>, then: Box<Core>, el: Box<Core> },
    KeyValue { key: Box<Core>, value: Box<Core> },
    While { cond: Box<Core>, body: Box<Core> },
    In { left: Box<Core>, right: Box<Core> },
    Break,
    Continue,
    Return { expr: Box<Core> },
    UnderScore,
    Pass,
    None,
    Empty,
    TryExcept { setup: Option<Box<Core>>, attempt: Box<Core>, except: Vec<Core> },
    ExceptId { id: Box<Core>, class: Box<Core>, body: Box<Core> },
    Except { class: Box<Core>, body: Box<Core> },
    Raise { error: Box<Core> },
    With { resource: Box<Core>, expr: Box<Core> },
    WithAs { resource: Box<Core>, alias: Box<Core>, expr: Box<Core> },
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum CoreOp {
    Assign,
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    PowAssign,
    BLShiftAssign,
    BRShiftAssign,
}

impl TryFrom<(&ASTTy, &NodeOp)> for CoreOp {
    type Error = UnimplementedErr;

    fn try_from((ast, op): (&ASTTy, &NodeOp)) -> Result<Self, Self::Error> {
        match &op {
            NodeOp::Add => Ok(CoreOp::AddAssign),
            NodeOp::Sub => Ok(CoreOp::SubAssign),
            NodeOp::Mul => Ok(CoreOp::MulAssign),
            NodeOp::Div => Ok(CoreOp::DivAssign),
            NodeOp::Pow => Ok(CoreOp::PowAssign),
            NodeOp::BLShift => Ok(CoreOp::BLShiftAssign),
            NodeOp::BRShift => Ok(CoreOp::BRShiftAssign),
            NodeOp::Assign => Ok(CoreOp::Assign),
            op => Err(UnimplementedErr::new(ast, &format!("Reassign with {op}")))
        }
    }
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum CoreFunOp {
    Ge,
    Geq,
    Le,
    Leq,
    Eq,
    Neq,
    Add,
    Sub,
    Mul,
    Div,
    Pow,
    Mod,
    FDiv,
}

impl CoreFunOp {
    pub fn from(lit: &str) -> Option<CoreFunOp> {
        Some(match lit {
            function::GE => CoreFunOp::Ge,
            function::GEQ => CoreFunOp::Geq,
            function::LE => CoreFunOp::Le,
            function::LEQ => CoreFunOp::Leq,
            function::EQ => CoreFunOp::Eq,
            function::NEQ => CoreFunOp::Neq,
            function::ADD => CoreFunOp::Add,
            function::SUB => CoreFunOp::Sub,
            function::POW => CoreFunOp::Pow,
            function::MUL => CoreFunOp::Mul,
            function::MOD => CoreFunOp::Mod,
            function::DIV => CoreFunOp::Div,
            function::FDIV => CoreFunOp::FDiv,
            _ => return None
        })
    }
}

impl Display for CoreOp {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match &self {
                CoreOp::Assign => "=",
                CoreOp::AddAssign => "+=",
                CoreOp::SubAssign => "-=",
                CoreOp::MulAssign => "*=",
                CoreOp::DivAssign => "/=",
                CoreOp::PowAssign => "**=",
                CoreOp::BLShiftAssign => "<<=",
                CoreOp::BRShiftAssign => ">>=",
            }
        )
    }
}

impl Display for CoreFunOp {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match &self {
                CoreFunOp::Ge => function::python::GE,
                CoreFunOp::Geq => function::python::GEQ,
                CoreFunOp::Le => function::python::LE,
                CoreFunOp::Leq => function::python::LEQ,
                CoreFunOp::Eq => function::python::EQ,
                CoreFunOp::Neq => function::python::NEQ,
                CoreFunOp::Add => function::python::ADD,
                CoreFunOp::Sub => function::python::SUB,
                CoreFunOp::Pow => function::python::POW,
                CoreFunOp::Mul => function::python::MUL,
                CoreFunOp::Mod => function::python::MOD,
                CoreFunOp::Div => function::python::DIV,
                CoreFunOp::FDiv => function::python::FDIV,
            }
        )
    }
}