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
use crate::language::InternSymbol;
use crate::parser::primary::{Primary, AccessItem, Atom};
use crate::parser::operator::BinaryOp;
use crate::parser::expr::{Expr, ExprMeta};
#[derive(Debug, Clone)]
pub enum LValue {
Identifier(InternSymbol),
Attribute(Box<AttributeTarget>),
Index(Box<IndexTarget>),
Tuple(Box<[LValue]>),
}
#[derive(Debug, Clone)]
pub struct AttributeTarget {
pub receiver: Primary,
pub name: InternSymbol,
}
#[derive(Debug, Clone)]
pub struct IndexTarget {
pub receiver: Primary,
pub index: ExprMeta,
}
#[derive(Debug, Clone)]
pub struct Assignment {
pub lhs: LValue,
pub op: Option<BinaryOp>,
pub rhs: Expr,
pub nonlocal: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeclType {
Immutable,
Mutable,
}
#[derive(Debug, Clone)]
pub struct Declaration {
pub decl: DeclType,
pub lhs: LValue,
pub init: Expr,
}
impl TryFrom<Atom> for LValue {
type Error = ();
fn try_from(atom: Atom) -> Result<Self, Self::Error> {
match atom {
Atom::Identifier(name) => Ok(LValue::Identifier(name)),
Atom::Group(expr) => (*expr).try_into(),
_ => Err(())
}
}
}
impl TryFrom<Primary> for LValue {
type Error = ();
fn try_from(primary: Primary) -> Result<Self, Self::Error> {
let (atom, mut path) = primary.take();
let tail = path.pop();
let receiver = Primary::new(atom, path);
let lvalue = match tail {
Some(AccessItem::Attribute(name))
=> LValue::Attribute(Box::new(AttributeTarget { receiver, name })),
Some(AccessItem::Index(index))
=> LValue::Index(Box::new(IndexTarget { receiver, index })),
_ => return Err(()),
};
Ok(lvalue)
}
}
impl TryFrom<Expr> for LValue {
type Error = ();
fn try_from(expr: Expr) -> Result<Self, Self::Error> {
match expr {
Expr::Atom(atom) => atom.try_into(),
Expr::Primary(primary) => primary.try_into(),
Expr::Tuple(expr_list) => {
let mut lvalue_list = Vec::<LValue>::new();
for expr in expr_list.into_vec().into_iter() {
let lvalue = expr.take_variant().try_into()?;
lvalue_list.push(lvalue);
}
Ok(Self::Tuple(lvalue_list.into_boxed_slice()))
},
_ => Err(()),
}
}
}