1use serde::{Deserialize, Serialize};
2
3use crate::annotations::Annotation;
4use crate::compilation::CompiledRynaExpr;
5use crate::parser::Location;
6use crate::types::{Type, INT, BOOL, STR, T_0, FLOAT};
7use crate::{object::*, ARR_OF};
8use crate::context::RynaContext;
9
10pub type UnaryFunctionFn = fn(&Vec<Type>, &Type, Object) -> Result<Object, String>;
17pub type BinaryFunctionFn = fn(&Vec<Type>, &Type, Object, Object, &RynaContext) -> Result<Object, String>;
18pub type NaryFunctionFn = fn((&mut Vec<Object>, &mut usize, &mut Vec<(i32, usize, i32)>, &mut i32), &Vec<Type>, &Type) -> Result<(), String>;
19
20pub type OptUnaryFunctionFn = Option<UnaryFunctionFn>;
21pub type OptBinaryFunctionFn = Option<BinaryFunctionFn>;
22pub type OptNaryFunctionFn = Option<NaryFunctionFn>;
23
24#[derive(Clone, Serialize, Deserialize)]
25#[serde(bound = "")]
26pub struct Operation<T> {
27 pub location: Location,
28 pub annotations: Vec<Annotation>,
29 pub templates: usize,
30 pub args: Type,
31 pub ret: Type,
32
33 #[serde(skip)]
34 pub operation: Option<T>
35}
36
37pub type UnaryOperations = Vec<Operation<UnaryFunctionFn>>;
38pub type BinaryOperations = Vec<Operation<BinaryFunctionFn>>;
39pub type NaryOperations = Vec<Operation<NaryFunctionFn>>;
40
41const EMPTY_UN_FUNC: UnaryFunctionFn = |_, _, _| Ok(Object::empty());
42const EMPTY_BIN_FUNC: BinaryFunctionFn = |_, _, _, _, _| Ok(Object::empty());
43const EMPTY_NARY_FUNC: NaryFunctionFn = |_, _, _| Ok(());
44
45#[derive(Clone, Serialize, Deserialize)]
46pub enum Operator {
47 Unary {
48 id: usize,
49 representation: String,
50 prefix: bool,
51 precedence: usize,
52 operations: UnaryOperations
53 },
54
55 Binary {
56 id: usize,
57 right_associative: bool,
58 representation: String,
59 precedence: usize,
60 operations: BinaryOperations
61 },
62
63 Nary {
64 id: usize,
65 open_rep: String, close_rep: String,
67 precedence: usize,
68 operations: NaryOperations
69 }
70}
71
72impl Operator {
73 pub fn get_id(&self) -> usize {
74 match self {
75 Operator::Unary { id, .. } => *id,
76 Operator::Binary { id, .. } => *id,
77 Operator::Nary { id, .. } => *id
78 }
79 }
80
81 pub fn get_precedence(&self) -> usize {
82 match self {
83 Operator::Unary { precedence: p, .. } => *p,
84 Operator::Binary { precedence: p, .. } => *p,
85 Operator::Nary { precedence: p, .. } => *p
86 }
87 }
88
89 pub fn get_repr(&self) -> String {
90 match self {
91 Operator::Unary { representation: r, .. } => r.into(),
92 Operator::Binary { representation: r, .. } => r.into(),
93 Operator::Nary { open_rep: o, close_rep: c, .. } => format!("{o}{c}")
94 }
95 }
96
97 pub fn is_right_associative(&self) -> bool {
98 match self {
99 Operator::Binary { right_associative, .. } => *right_associative,
100 _ => unreachable!()
101 }
102 }
103}
104
105macro_rules! define_unary_native_op {
112 ($ctx: ident, $id: expr, $inner_type: expr, $return_type: expr) => {
113 $ctx.define_native_unary_operation($id, 0, $inner_type, $return_type, EMPTY_UN_FUNC).unwrap();
114 };
115}
116
117macro_rules! define_unary_native_op_combinations {
118 ($ctx: ident, $id: expr, $inner_type: expr, $return_type: expr) => {
119 let base_ref = Type::Ref(Box::new($inner_type.clone()));
120 let base_mut = Type::MutRef(Box::new($inner_type.clone()));
121
122 define_unary_native_op!($ctx, $id, $inner_type, $return_type);
123 define_unary_native_op!($ctx, $id, base_ref.clone(), $return_type);
124 define_unary_native_op!($ctx, $id, base_mut.clone(), $return_type);
125 };
126}
127
128pub const NEG_UNOP_ID: usize = 0;
129pub const NOT_UNOP_ID: usize = 1;
130pub const DEREF_UNOP_ID: usize = 2;
131
132pub fn standard_unary_operations(ctx: &mut RynaContext) {
133 ctx.define_unary_operator("-".into(), true, 300).unwrap();
134
135 define_unary_native_op_combinations!(ctx, 0, INT, INT);
136 define_unary_native_op_combinations!(ctx, 0, FLOAT, FLOAT);
137
138 ctx.define_unary_operator("!".into(), true, 250).unwrap();
139
140 define_unary_native_op_combinations!(ctx, 1, BOOL, BOOL);
141 define_unary_native_op_combinations!(ctx, 1, INT, INT);
142
143 ctx.define_unary_operator("*".into(), true, 155).unwrap();
144
145 ctx.define_native_unary_operation(2, 1, T_0.to_mut(), T_0, EMPTY_UN_FUNC).unwrap();
146 ctx.define_native_unary_operation(2, 1, T_0.to_ref(), T_0, EMPTY_UN_FUNC).unwrap();
147}
148
149macro_rules! define_binary_native_op {
150 ($ctx: ident, $id: expr, $l_type: expr, $r_type: expr, $return_type: expr) => {
151 $ctx.define_native_binary_operation($id, 0, $l_type, $r_type, $return_type, EMPTY_BIN_FUNC).unwrap();
152 };
153}
154
155macro_rules! define_binary_native_op_combinations_distinct {
156 ($ctx: ident, $id: expr, $base_type_1: expr, $base_type_2: expr, $return_type: expr) => {
157 let base_ref_1 = Type::Ref(Box::new($base_type_1.clone()));
158 let base_mut_1 = Type::MutRef(Box::new($base_type_1.clone()));
159 let base_ref_2 = Type::Ref(Box::new($base_type_2.clone()));
160 let base_mut_2 = Type::MutRef(Box::new($base_type_2.clone()));
161
162 define_binary_native_op!($ctx, $id, $base_type_1, $base_type_2, $return_type);
163 define_binary_native_op!($ctx, $id, base_ref_1.clone(), $base_type_2, $return_type);
164 define_binary_native_op!($ctx, $id, $base_type_1, base_ref_2.clone(), $return_type);
165 define_binary_native_op!($ctx, $id, base_mut_1.clone(), $base_type_2, $return_type);
166 define_binary_native_op!($ctx, $id, $base_type_1, base_mut_2.clone(), $return_type);
167 define_binary_native_op!($ctx, $id, base_ref_1.clone(), base_ref_2.clone(), $return_type);
168 define_binary_native_op!($ctx, $id, base_ref_1.clone(), base_mut_2.clone(), $return_type);
169 define_binary_native_op!($ctx, $id, base_mut_1.clone(), base_mut_2.clone(), $return_type);
170 define_binary_native_op!($ctx, $id, base_mut_1.clone(), base_ref_2.clone(), $return_type);
171 };
172}
173
174macro_rules! define_binary_native_op_combinations {
175 ($ctx: ident, $id: expr, $base_type: expr, $return_type: expr) => {
176 define_binary_native_op_combinations_distinct!($ctx, $id, $base_type, $base_type, $return_type);
177 };
178}
179
180pub const ADD_BINOP_ID: usize = 0;
182pub const SUB_BINOP_ID: usize = 1;
183pub const MUL_BINOP_ID: usize = 2;
184pub const DIV_BINOP_ID: usize = 3;
185pub const MOD_BINOP_ID: usize = 4;
186
187pub const DOT_BINOP_ID: usize = 5;
188
189pub const LT_BINOP_ID: usize = 6;
190pub const GT_BINOP_ID: usize = 7;
191pub const LTEQ_BINOP_ID: usize = 8;
192pub const GTEQ_BINOP_ID: usize = 9;
193pub const EQ_BINOP_ID: usize = 10;
194pub const NEQ_BINOP_ID: usize = 11;
195
196pub const OR_BINOP_ID: usize = 12;
197pub const AND_BINOP_ID: usize = 13;
198pub const XOR_BINOP_ID: usize = 19;
199
200pub const SHR_BINOP_ID: usize = 15;
201pub const SHL_BINOP_ID: usize = 16;
202pub const ANDB_BINOP_ID: usize = 17;
203pub const ORB_BINOP_ID: usize = 18;
204
205pub const ASSIGN_BINOP_ID: usize = 14;
206
207pub const LT_BINOP_PREC: usize = 900;
208
209pub const DEFINE_BINOP_ID: usize = 20;
210
211pub const IDX_NARYOP_ID: usize = 1;
212
213pub fn standard_binary_operations(ctx: &mut RynaContext) {
214
215 ctx.define_binary_operator("+".into(), false, 650).unwrap();
222
223 define_binary_native_op_combinations!(ctx, 0, INT, INT);
224 define_binary_native_op_combinations!(ctx, 0, FLOAT, FLOAT);
225 define_binary_native_op_combinations_distinct!(ctx, 0, INT, FLOAT, FLOAT);
226 define_binary_native_op_combinations_distinct!(ctx, 0, FLOAT, INT, FLOAT);
227
228 define_binary_native_op_combinations!(ctx, 0, STR, STR);
229
230 ctx.define_binary_operator("-".into(), true, 700).unwrap();
231
232 define_binary_native_op_combinations!(ctx, 1, INT, INT);
233 define_binary_native_op_combinations!(ctx, 1, FLOAT, FLOAT);
234 define_binary_native_op_combinations_distinct!(ctx, 1, INT, FLOAT, FLOAT);
235 define_binary_native_op_combinations_distinct!(ctx, 1, FLOAT, INT, FLOAT);
236
237 ctx.define_binary_operator("*".into(), false, 500).unwrap();
238
239 define_binary_native_op_combinations!(ctx, 2, INT, INT);
240 define_binary_native_op_combinations!(ctx, 2, FLOAT, FLOAT);
241 define_binary_native_op_combinations_distinct!(ctx, 2, INT, FLOAT, FLOAT);
242 define_binary_native_op_combinations_distinct!(ctx, 2, FLOAT, INT, FLOAT);
243
244 ctx.define_binary_operator("/".into(), false, 550).unwrap();
245
246 define_binary_native_op_combinations!(ctx, 3, INT, INT);
247 define_binary_native_op_combinations!(ctx, 3, FLOAT, FLOAT);
248 define_binary_native_op_combinations_distinct!(ctx, 3, INT, FLOAT, FLOAT);
249 define_binary_native_op_combinations_distinct!(ctx, 3, FLOAT, INT, FLOAT);
250
251 ctx.define_binary_operator("%".into(), false, 600).unwrap();
252
253 define_binary_native_op_combinations!(ctx, 4, INT, INT);
254 define_binary_native_op_combinations!(ctx, 4, FLOAT, FLOAT);
255 define_binary_native_op_combinations_distinct!(ctx, 4, INT, FLOAT, FLOAT);
256 define_binary_native_op_combinations_distinct!(ctx, 4, FLOAT, INT, FLOAT);
257
258 ctx.define_binary_operator(".".into(), true, 100).unwrap();
265
266 ctx.define_binary_operator("<".into(), false, 900).unwrap();
273
274 define_binary_native_op_combinations!(ctx, 6, INT, BOOL);
275 define_binary_native_op_combinations!(ctx, 6, FLOAT, BOOL);
276 define_binary_native_op_combinations_distinct!(ctx, 6, INT, FLOAT, BOOL);
277 define_binary_native_op_combinations_distinct!(ctx, 6, FLOAT, INT, BOOL);
278
279 ctx.define_binary_operator(">".into(), false, 950).unwrap();
280
281 define_binary_native_op_combinations!(ctx, 7, INT, BOOL);
282 define_binary_native_op_combinations!(ctx, 7, FLOAT, BOOL);
283 define_binary_native_op_combinations_distinct!(ctx, 7, INT, FLOAT, BOOL);
284 define_binary_native_op_combinations_distinct!(ctx, 7, FLOAT, INT, BOOL);
285
286 ctx.define_binary_operator("<=".into(), false, 1000).unwrap();
287
288 define_binary_native_op_combinations!(ctx, 8, INT, BOOL);
289 define_binary_native_op_combinations!(ctx, 8, FLOAT, BOOL);
290 define_binary_native_op_combinations_distinct!(ctx, 8, INT, FLOAT, BOOL);
291 define_binary_native_op_combinations_distinct!(ctx, 8, FLOAT, INT, BOOL);
292
293 ctx.define_binary_operator(">=".into(), false, 1050).unwrap();
294
295 define_binary_native_op_combinations!(ctx, 9, INT, BOOL);
296 define_binary_native_op_combinations!(ctx, 9, FLOAT, BOOL);
297 define_binary_native_op_combinations_distinct!(ctx, 9, INT, FLOAT, BOOL);
298 define_binary_native_op_combinations_distinct!(ctx, 9, FLOAT, INT, BOOL);
299
300 ctx.define_binary_operator("==".into(), false, 1100).unwrap();
301
302 define_binary_native_op_combinations!(ctx, 10, INT, BOOL);
303 define_binary_native_op_combinations!(ctx, 10, FLOAT, BOOL);
304 define_binary_native_op_combinations!(ctx, 10, STR, BOOL);
305 define_binary_native_op_combinations!(ctx, 10, BOOL, BOOL);
306
307 ctx.define_binary_operator("!=".into(), false, 1150).unwrap();
308
309 define_binary_native_op_combinations!(ctx, 11, INT, BOOL);
310 define_binary_native_op_combinations!(ctx, 11, FLOAT, BOOL);
311 define_binary_native_op_combinations!(ctx, 11, STR, BOOL);
312 define_binary_native_op_combinations!(ctx, 11, BOOL, BOOL);
313
314 ctx.define_binary_operator("||".into(), false, 1500).unwrap();
321
322 define_binary_native_op_combinations!(ctx, 12, BOOL, BOOL);
323
324 ctx.define_binary_operator("&&".into(), false, 1550).unwrap();
325
326 define_binary_native_op_combinations!(ctx, 13, BOOL, BOOL);
327
328 ctx.define_binary_operator(":=".into(), false, 100000).unwrap();
329
330 ctx.define_native_binary_operation(
331 14, 1,
332 T_0.to_mut(), T_0, Type::Empty,
333 |_, _, a, b, ctx| {
334 a.assign(b, ctx)?;
335 Ok(Object::empty())
336 }
337 ).unwrap();
338
339 ctx.define_binary_operator(">>".into(), false, 350).unwrap();
340
341 define_binary_native_op_combinations!(ctx, 15, INT, INT);
342
343 ctx.define_binary_operator("<<".into(), false, 360).unwrap();
344
345 define_binary_native_op_combinations!(ctx, 16, INT, INT);
346
347 ctx.define_binary_operator("&".into(), false, 370).unwrap();
348
349 define_binary_native_op_combinations!(ctx, 17, INT, INT);
350
351 ctx.define_binary_operator("|".into(), false, 380).unwrap();
352
353 define_binary_native_op_combinations!(ctx, 18, INT, INT);
354
355 ctx.define_binary_operator("^".into(), false, 390).unwrap();
356
357 define_binary_native_op_combinations!(ctx, 19, BOOL, BOOL);
358 define_binary_native_op_combinations!(ctx, 19, INT, INT);
359
360 ctx.define_binary_operator("=".into(), false, 200000).unwrap();
361}
362
363pub const CALL_OP: usize = 0;
364
365pub fn standard_nary_operations(ctx: &mut RynaContext) {
366 ctx.define_nary_operator("(".into(), ")".into(), 50).unwrap();
367
368 for n in 0..30 {
369 let args = (0..n).map(|i| Type::TemplateParam(i, vec!())).collect::<Vec<_>>();
370
371 let f_type = Type::Function(
372 Box::new(Type::And(args.clone())),
373 Box::new(Type::TemplateParam(n, vec!()))
374 );
375
376 let res = ctx.define_native_nary_operation(
377 0, n + 1,
378 Type::MutRef(Box::new(f_type.clone())),
379 args.as_slice(),
380 Type::TemplateParam(n, vec!()),
381 EMPTY_NARY_FUNC
382 ).unwrap();
383
384 ctx.cache.opcodes.nary.insert((0, res), (CompiledRynaExpr::LambdaCallRef, 0));
385
386 let res = ctx.define_native_nary_operation(
387 0, n + 1,
388 Type::Ref(Box::new(f_type.clone())),
389 args.as_slice(),
390 Type::TemplateParam(n, vec!()),
391 EMPTY_NARY_FUNC
392 ).unwrap();
393
394 ctx.cache.opcodes.nary.insert((0, res), (CompiledRynaExpr::LambdaCallRef, 0));
395
396 let res = ctx.define_native_nary_operation(
397 0, n + 1,
398 f_type,
399 args.as_slice(),
400 Type::TemplateParam(n, vec!()),
401 EMPTY_NARY_FUNC
402 ).unwrap();
403
404 ctx.cache.opcodes.nary.insert((0, res), (CompiledRynaExpr::LambdaCall, 0));
405 }
406
407 ctx.define_nary_operator("[".into(), "]".into(), 75).unwrap();
408
409 let res = ctx.define_native_nary_operation(1, 1, ARR_OF!(T_0), &[INT], T_0, EMPTY_NARY_FUNC).unwrap();
411 ctx.cache.opcodes.nary.insert((1, res), (CompiledRynaExpr::IdxMove, 0));
412
413 let res = ctx.define_native_nary_operation(1, 1, ARR_OF!(T_0).to_mut(), &[INT], T_0.to_mut(), EMPTY_NARY_FUNC).unwrap();
414 ctx.cache.opcodes.nary.insert((1, res), (CompiledRynaExpr::IdxMut, 0));
415
416 let res = ctx.define_native_nary_operation(1, 1, ARR_OF!(T_0).to_ref(), &[INT], T_0.to_ref(), EMPTY_NARY_FUNC).unwrap();
417 ctx.cache.opcodes.nary.insert((1, res), (CompiledRynaExpr::IdxRef, 0));
418}