luna_lib/luna_impl/
interpreter.rs

1use super::{
2    position::{Located, Position},
3    std::{
4        globals, BOOL_MODULE, CHAR_MODULE, FLOAT_MODULE, INT_MODULE, STRING_MODULE, VECTOR_MODULE,
5    },
6};
7use crate::lang::{
8    code::{Address, BinaryOperation, ByteCode, Location, Register, Source, UnaryOperation},
9    value::{Function, FunctionKind, Object, Value, META_CALL, META_GET, META_SET},
10};
11use std::{cell::RefCell, collections::HashMap, error::Error, fmt::Display, rc::Rc};
12
13pub const CALL_STACK_CAP: usize = 0xffff;
14
15#[derive(Debug, Clone)]
16pub struct Interpreter {
17    pub call_frames: Vec<CallFrame>,
18    pub globals: Rc<RefCell<HashMap<String, Rc<RefCell<Value>>>>>,
19    pub global_path: Option<String>,
20}
21#[derive(Debug, Clone)]
22pub struct CallFrame {
23    pub function: Rc<Function>,
24    pub stack: Vec<Rc<RefCell<Value>>>,
25    pub idx: Address,
26    pub dst: Option<Location>,
27    pub globals: Rc<RefCell<HashMap<String, Rc<RefCell<Value>>>>>,
28}
29#[derive(Debug, Clone, PartialEq)]
30pub enum RunTimeError {
31    CannotCall(String),
32    CannotIter(String),
33    CannotFieldInto {
34        head: String,
35        field: String,
36    },
37    CannotField(String),
38    CannotSetFieldWith {
39        head: String,
40        field: String,
41    },
42    CannotSetField(String),
43    InvalidSetIndex(usize),
44    InvalidBinary {
45        op: BinaryOperation,
46        left: String,
47        right: String,
48    },
49    InvalidUnary {
50        op: UnaryOperation,
51        right: String,
52    },
53    Custom(String),
54}
55
56impl Default for Interpreter {
57    fn default() -> Self {
58        Self {
59            call_frames: Vec::with_capacity(CALL_STACK_CAP),
60            globals: Rc::new(RefCell::new(globals())),
61            global_path: None,
62        }
63    }
64}
65impl Interpreter {
66    #[inline(always)]
67    pub fn with_global_path(mut self, path: Option<String>) -> Self {
68        self.global_path = path;
69        self
70    }
71}
72impl Interpreter {
73    #[inline(always)]
74    pub fn path(&self) -> Option<String> {
75        self.call_frames
76            .last()?
77            .function
78            .closure
79            .borrow()
80            .path
81            .clone()
82    }
83    #[inline(always)]
84    pub fn call(&mut self, function: &Rc<Function>, args: Vec<Value>, dst: Option<Location>) {
85        let mut stack = Vec::with_capacity(function.closure.borrow().registers as usize + 1);
86        let args_len = args.len();
87        stack.extend(args.into_iter().map(|v| Rc::new(RefCell::new(v))));
88        stack.extend(
89            (args_len..function.closure.borrow().registers as usize + 1)
90                .map(|_| Rc::new(RefCell::new(Value::default()))),
91        );
92        self.call_frames.push(CallFrame {
93            function: Rc::clone(function),
94            stack,
95            idx: 0,
96            dst,
97            globals: Rc::clone(&self.globals),
98        });
99    }
100    #[inline(always)]
101    pub fn return_call(&mut self, src: Option<Source>) -> Option<Value> {
102        let top_frame = self.call_frames.pop().expect("no frame on stack");
103        if let Some(prev_frame) = self.call_frames.last_mut() {
104            if let Some(dst) = top_frame.dst {
105                let value = top_frame
106                    .source(&src.unwrap_or_default())
107                    .expect("source not found");
108                let dst = prev_frame.location(&dst).expect("location not found");
109                *dst.borrow_mut() = value;
110            }
111        }
112        if let Some(src) = src {
113            return Some(top_frame.source(&src).expect("source not found"));
114        }
115        None
116    }
117    #[inline(always)]
118    pub fn call_kind(
119        &mut self,
120        kind: FunctionKind,
121        args: Vec<Value>,
122        dst: Option<Location>,
123        pos: Position,
124    ) -> Result<(), Located<RunTimeError>> {
125        match kind {
126            FunctionKind::Function(function) => {
127                self.call(&function, args, dst);
128                Ok(())
129            }
130            FunctionKind::UserFunction(func) => {
131                let dst = dst.map(|dst| {
132                    self.call_frames
133                        .last_mut()
134                        .expect("no call frame")
135                        .location(&dst)
136                        .expect("dst not found")
137                });
138                let value = func(self, args)
139                    .map_err(|err| Located::new(RunTimeError::Custom(err.to_string()), pos))?;
140                if let Some(dst) = dst {
141                    *dst.borrow_mut() = value;
142                }
143                Ok(())
144            }
145        }
146    }
147    pub fn step(&mut self) -> Result<Option<Value>, Located<RunTimeError>> {
148        let idx = self.call_frames.last_mut().expect("no call frame").idx;
149        let Located {
150            value: bytecode,
151            pos,
152        } = self
153            .call_frames
154            .last_mut()
155            .expect("no call frame")
156            .function
157            .closure
158            .borrow()
159            .code
160            .get(idx as usize)
161            .cloned()
162            .expect("idx out of range");
163        self.call_frames.last_mut().expect("no call frame").idx += 1;
164        match bytecode {
165            ByteCode::None => {}
166            ByteCode::Jump { addr } => {
167                self.call_frames.last_mut().expect("no call frame").idx = addr;
168            }
169            ByteCode::JumpIf {
170                negative: false,
171                cond,
172                addr,
173            } => {
174                if self
175                    .call_frames
176                    .last_mut()
177                    .expect("no call frame")
178                    .source(&cond)
179                    .expect("cond not found")
180                    .into()
181                {
182                    self.call_frames.last_mut().expect("no call frame").idx = addr;
183                }
184            }
185            ByteCode::JumpIf {
186                negative: true,
187                cond,
188                addr,
189            } => {
190                if !bool::from(
191                    self.call_frames
192                        .last_mut()
193                        .expect("no call frame")
194                        .source(&cond)
195                        .expect("cond not found"),
196                ) {
197                    self.call_frames.last_mut().expect("no call frame").idx = addr;
198                }
199            }
200            ByteCode::JumpNull { negative: false, cond, addr } => {
201                if self
202                    .call_frames
203                    .last_mut()
204                    .expect("no call frame")
205                    .source(&cond)
206                    .expect("cond not found")
207                    == Value::default()
208                {
209                    self.call_frames.last_mut().expect("no call frame").idx = addr;
210                }
211            }
212            ByteCode::JumpNull { negative: true, cond, addr } => {
213                if self
214                    .call_frames
215                    .last_mut()
216                    .expect("no call frame")
217                    .source(&cond)
218                    .expect("cond not found")
219                    != Value::default()
220                {
221                    self.call_frames.last_mut().expect("no call frame").idx = addr;
222                }
223            }
224            ByteCode::CallSingle { dst, func, arg } => {
225                let func = self
226                    .call_frames
227                    .last_mut()
228                    .expect("no call frame")
229                    .source(&func)
230                    .expect("func not found");
231                let mut args = vec![self
232                    .call_frames
233                    .last_mut()
234                    .expect("no call frame")
235                    .source(&arg)
236                    .expect("func not found")];
237                match func {
238                    Value::Function(kind) => self.call_kind(kind, args, dst, pos)?,
239                    Value::Object(object) => {
240                        args.insert(0, Value::Object(Rc::clone(&object)));
241                        let object = object.borrow();
242                        if let Some(Value::Function(kind)) = object.get_meta(META_CALL) {
243                            self.call_kind(kind, args, dst, pos)?;
244                        }
245                    }
246                    value => {
247                        return Err(Located::new(
248                            RunTimeError::CannotCall(value.dynamic_typ()),
249                            pos,
250                        ))
251                    }
252                };
253            }
254            ByteCode::CallZero { dst, func } => {
255                let func = self
256                    .call_frames
257                    .last_mut()
258                    .expect("no call frame")
259                    .source(&func)
260                    .expect("func not found");
261                let mut args = Vec::with_capacity(1);
262                match func {
263                    Value::Function(kind) => self.call_kind(kind, args, dst, pos)?,
264                    Value::Object(object) => {
265                        args.insert(0, Value::Object(Rc::clone(&object)));
266                        let object = object.borrow();
267                        if let Some(Value::Function(kind)) = object.get_meta(META_CALL) {
268                            self.call_kind(kind, args, dst, pos)?;
269                        }
270                    }
271                    value => {
272                        return Err(Located::new(
273                            RunTimeError::CannotCall(value.dynamic_typ()),
274                            pos,
275                        ))
276                    }
277                };
278            }
279            ByteCode::Call {
280                dst,
281                func,
282                offset,
283                amount,
284            } => {
285                let func = self
286                    .call_frames
287                    .last_mut()
288                    .expect("no call frame")
289                    .source(&func)
290                    .expect("func not found");
291                let mut args = Vec::with_capacity(amount as usize);
292                for register in offset..offset + amount as Register {
293                    args.push(
294                        self.call_frames
295                            .last_mut()
296                            .expect("no call frame")
297                            .register(register)
298                            .expect("register out of range")
299                            .borrow()
300                            .clone(),
301                    )
302                }
303                match func {
304                    Value::Function(kind) => self.call_kind(kind, args, dst, pos)?,
305                    Value::Object(object) => {
306                        args.insert(0, Value::Object(Rc::clone(&object)));
307                        let object = object.borrow();
308                        if let Some(Value::Function(kind)) = object.get_meta(META_CALL) {
309                            self.call_kind(kind, args, dst, pos)?;
310                        }
311                    }
312                    value => {
313                        return Err(Located::new(
314                            RunTimeError::CannotCall(value.dynamic_typ()),
315                            pos,
316                        ))
317                    }
318                };
319            }
320            ByteCode::Return { src } => return Ok(self.return_call(src)),
321            ByteCode::Move { dst, src } => {
322                let dst = self
323                    .call_frames
324                    .last_mut()
325                    .expect("no call frame")
326                    .location(&dst)
327                    .expect("location not found");
328                let value = self
329                    .call_frames
330                    .last_mut()
331                    .expect("no call frame")
332                    .source(&src)
333                    .expect("source not found");
334                *dst.borrow_mut() = value;
335            }
336            ByteCode::Field { dst, head, field } => {
337                let dst_value = self
338                    .call_frames
339                    .last_mut()
340                    .expect("no call frame")
341                    .location(&dst)
342                    .expect("location not found");
343                let head = self
344                    .call_frames
345                    .last_mut()
346                    .expect("no call frame")
347                    .source(&head)
348                    .expect("source not found");
349                let field = self
350                    .call_frames
351                    .last_mut()
352                    .expect("no call frame")
353                    .source(&field)
354                    .expect("source not found");
355                *dst_value.borrow_mut() = match &head {
356                    Value::Object(object) => {
357                        if let Some(Value::Function(kind)) = object.borrow().get_meta(META_GET) {
358                            self.call_kind(
359                                kind,
360                                vec![head.clone(), field],
361                                Some(dst),
362                                pos.clone(),
363                            )?;
364                            return Ok(None);
365                        }
366                        match field {
367                            Value::String(key) => object.borrow_mut().fields.get(&key).cloned(),
368                            field => {
369                                return Err(Located::new(
370                                    RunTimeError::CannotFieldInto {
371                                        head: Value::Object(Default::default()).dynamic_typ(),
372                                        field: field.dynamic_typ(),
373                                    },
374                                    pos,
375                                ))
376                            }
377                        }
378                    }
379                    Value::UserObject(object) => match field {
380                        Value::String(key) => object.borrow_mut().get(&key),
381                        field => {
382                            return Err(Located::new(
383                                RunTimeError::CannotFieldInto {
384                                    head: Value::Object(Default::default()).dynamic_typ(),
385                                    field: field.dynamic_typ(),
386                                },
387                                pos,
388                            ))
389                        }
390                    },
391                    Value::Vector(vector) => match field {
392                        Value::Int(index) => {
393                            let vector = vector.borrow_mut();
394                            let length = vector.len();
395                            let index = if index < 0 {
396                                let index = length as i64 + index;
397                                if index < 0 {
398                                    length
399                                } else {
400                                    index as usize
401                                }
402                            } else {
403                                index.unsigned_abs() as usize
404                            };
405                            vector.get(index).cloned()
406                        }
407                        Value::String(key) => {
408                            if let Value::Object(object) = self
409                                .globals
410                                .borrow()
411                                .get(VECTOR_MODULE)
412                                .cloned()
413                                .unwrap_or_default()
414                                .borrow()
415                                .clone()
416                            {
417                                let object = object.borrow();
418                                object.fields.get(&key).cloned()
419                            } else {
420                                Some(Value::default())
421                            }
422                        }
423                        field => {
424                            return Err(Located::new(
425                                RunTimeError::CannotFieldInto {
426                                    head: Value::Vector(Default::default()).dynamic_typ(),
427                                    field: field.dynamic_typ(),
428                                },
429                                pos,
430                            ))
431                        }
432                    },
433                    Value::String(string) => match field {
434                        Value::Int(index) => {
435                            let length = string.len();
436                            let index = if index < 0 {
437                                let index = length as i64 + index;
438                                if index < 0 {
439                                    length
440                                } else {
441                                    index as usize
442                                }
443                            } else {
444                                index.unsigned_abs() as usize
445                            };
446                            string
447                                .get(index..=index)
448                                .and_then(|s| s.chars().next())
449                                .map(Value::Char)
450                        }
451                        Value::String(key) => {
452                            if let Value::Object(object) = self
453                                .globals
454                                .borrow()
455                                .get(STRING_MODULE)
456                                .cloned()
457                                .unwrap_or_default()
458                                .borrow()
459                                .clone()
460                            {
461                                let object = object.borrow();
462                                object.fields.get(&key).cloned()
463                            } else {
464                                Some(Value::default())
465                            }
466                        }
467                        field => {
468                            return Err(Located::new(
469                                RunTimeError::CannotFieldInto {
470                                    head: Value::String(Default::default()).dynamic_typ(),
471                                    field: field.dynamic_typ(),
472                                },
473                                pos,
474                            ))
475                        }
476                    },
477                    Value::Int(_) => match field {
478                        Value::String(key) => {
479                            if let Value::Object(object) = self
480                                .globals
481                                .borrow()
482                                .get(INT_MODULE)
483                                .cloned()
484                                .unwrap_or_default()
485                                .borrow()
486                                .clone()
487                            {
488                                let object = object.borrow();
489                                object.fields.get(&key).cloned()
490                            } else {
491                                Some(Value::default())
492                            }
493                        }
494                        field => {
495                            return Err(Located::new(
496                                RunTimeError::CannotFieldInto {
497                                    head: Value::String(Default::default()).dynamic_typ(),
498                                    field: field.dynamic_typ(),
499                                },
500                                pos,
501                            ))
502                        }
503                    },
504                    Value::Float(_) => match field {
505                        Value::String(key) => {
506                            if let Value::Object(object) = self
507                                .globals
508                                .borrow()
509                                .get(FLOAT_MODULE)
510                                .cloned()
511                                .unwrap_or_default()
512                                .borrow()
513                                .clone()
514                            {
515                                let object = object.borrow();
516                                object.fields.get(&key).cloned()
517                            } else {
518                                Some(Value::default())
519                            }
520                        }
521                        field => {
522                            return Err(Located::new(
523                                RunTimeError::CannotFieldInto {
524                                    head: Value::String(Default::default()).dynamic_typ(),
525                                    field: field.dynamic_typ(),
526                                },
527                                pos,
528                            ))
529                        }
530                    },
531                    Value::Bool(_) => match field {
532                        Value::String(key) => {
533                            if let Value::Object(object) = self
534                                .globals
535                                .borrow()
536                                .get(BOOL_MODULE)
537                                .cloned()
538                                .unwrap_or_default()
539                                .borrow()
540                                .clone()
541                            {
542                                let object = object.borrow();
543                                object.fields.get(&key).cloned()
544                            } else {
545                                Some(Value::default())
546                            }
547                        }
548                        field => {
549                            return Err(Located::new(
550                                RunTimeError::CannotFieldInto {
551                                    head: Value::String(Default::default()).dynamic_typ(),
552                                    field: field.dynamic_typ(),
553                                },
554                                pos,
555                            ))
556                        }
557                    },
558                    Value::Char(_) => match field {
559                        Value::String(key) => {
560                            if let Value::Object(object) = self
561                                .globals
562                                .borrow()
563                                .get(CHAR_MODULE)
564                                .cloned()
565                                .unwrap_or_default()
566                                .borrow()
567                                .clone()
568                            {
569                                let object = object.borrow();
570                                object.fields.get(&key).cloned()
571                            } else {
572                                Some(Value::default())
573                            }
574                        }
575                        field => {
576                            return Err(Located::new(
577                                RunTimeError::CannotFieldInto {
578                                    head: Value::String(Default::default()).dynamic_typ(),
579                                    field: field.dynamic_typ(),
580                                },
581                                pos,
582                            ))
583                        }
584                    },
585                    head => {
586                        return Err(Located::new(
587                            RunTimeError::CannotField(head.dynamic_typ()),
588                            pos,
589                        ))
590                    }
591                }
592                .unwrap_or_default();
593            }
594            ByteCode::SetField { head, field, src } => {
595                let value = self
596                    .call_frames
597                    .last_mut()
598                    .expect("no call frame")
599                    .source(&src)
600                    .expect("source not found");
601                let head = self
602                    .call_frames
603                    .last_mut()
604                    .expect("no call frame")
605                    .source(&head)
606                    .expect("source not found");
607                let field = self
608                    .call_frames
609                    .last_mut()
610                    .expect("no call frame")
611                    .source(&field)
612                    .expect("source not found");
613                match &head {
614                    Value::Object(object) => {
615                        if let Some(Value::Function(kind)) = object.borrow().get_meta(META_SET) {
616                            self.call_kind(
617                                kind,
618                                vec![head.clone(), field, value],
619                                None,
620                                pos.clone(),
621                            )?;
622                            return Ok(None);
623                        }
624                        let mut object = object.borrow_mut();
625                        let old_value = match field {
626                            Value::String(key) => {
627                                if let Some(value) = object.fields.get_mut(&key) {
628                                    value
629                                } else {
630                                    object.fields.insert(key.clone(), Value::default());
631                                    object.fields.get_mut(&key).unwrap()
632                                }
633                            }
634                            field => {
635                                return Err(Located::new(
636                                    RunTimeError::CannotSetFieldWith {
637                                        head: Value::Object(Default::default()).dynamic_typ(),
638                                        field: field.dynamic_typ(),
639                                    },
640                                    pos,
641                                ))
642                            }
643                        };
644                        *old_value = value;
645                    }
646                    Value::Vector(vector) => {
647                        let mut vector = vector.borrow_mut();
648                        match field {
649                            Value::Int(index) => {
650                                let length = vector.len();
651                                let index = if index < 0 {
652                                    let index = length as i64 + index;
653                                    if index < 0 {
654                                        length
655                                    } else {
656                                        index as usize
657                                    }
658                                } else {
659                                    index.unsigned_abs() as usize
660                                };
661                                if let Some(old_value) = vector.get_mut(index) {
662                                    *old_value = value;
663                                } else {
664                                    return Err(Located::new(
665                                        RunTimeError::InvalidSetIndex(index),
666                                        pos,
667                                    ));
668                                }
669                            }
670                            field => {
671                                return Err(Located::new(
672                                    RunTimeError::CannotSetFieldWith {
673                                        head: Value::Vector(Default::default()).dynamic_typ(),
674                                        field: field.dynamic_typ(),
675                                    },
676                                    pos,
677                                ))
678                            }
679                        }
680                    }
681                    head => {
682                        return Err(Located::new(
683                            RunTimeError::CannotSetField(head.dynamic_typ()),
684                            pos,
685                        ))
686                    }
687                }
688            }
689            ByteCode::Vector { dst, start, amount } => {
690                let dst = self
691                    .call_frames
692                    .last_mut()
693                    .expect("no call frame")
694                    .location(&dst)
695                    .expect("location not found");
696                let mut values = vec![];
697                for register in start..start + amount {
698                    values.push(
699                        self.call_frames
700                            .last_mut()
701                            .expect("no call frame")
702                            .register(register)
703                            .expect("register not found")
704                            .borrow()
705                            .clone(),
706                    );
707                }
708                *dst.borrow_mut() = Value::Vector(Rc::new(RefCell::new(values)));
709            }
710            ByteCode::Object { dst, start, amount } => {
711                let dst = self
712                    .call_frames
713                    .last_mut()
714                    .expect("no call frame")
715                    .location(&dst)
716                    .expect("location not found");
717                let mut object = Object::default();
718                for register in (start..start + amount * 2).step_by(2) {
719                    let Value::String(field) = self
720                        .call_frames
721                        .last_mut()
722                        .expect("no call frame")
723                        .register(register)
724                        .expect("register not found")
725                        .borrow()
726                        .clone()
727                    else {
728                        panic!("expected object field to be a string")
729                    };
730                    let value = self
731                        .call_frames
732                        .last_mut()
733                        .expect("no call frame")
734                        .register(register + 1)
735                        .expect("register not found")
736                        .borrow()
737                        .clone();
738                    object.fields.insert(field, value);
739                }
740                *dst.borrow_mut() = Value::Object(Rc::new(RefCell::new(object)));
741            }
742            ByteCode::Function { dst, addr } => {
743                let dst = self
744                    .call_frames
745                    .last_mut()
746                    .expect("no call frame")
747                    .location(&dst)
748                    .expect("location not found");
749                let closure = Rc::clone(
750                    self.call_frames
751                        .last_mut()
752                        .expect("no call frame on stack")
753                        .function
754                        .closure
755                        .borrow()
756                        .closures
757                        .get(addr as usize)
758                        .expect("closure not found"),
759                );
760                let mut upvalues = Vec::with_capacity(closure.borrow().upvalues.len());
761                for upvalue in closure.borrow().upvalues.iter() {
762                    upvalues.push(if upvalue.depth == 0 {
763                        self.call_frames
764                            .last_mut()
765                            .expect("no call frame")
766                            .register(upvalue.register)
767                            .expect("register not found")
768                    } else if let Some(value) = self
769                        .call_frames
770                        .get(self.call_frames.len() - 1 - upvalue.depth as usize)
771                        .map(|frame| {
772                            frame
773                                .register(upvalue.register)
774                                .expect("register not found")
775                        })
776                    {
777                        value
778                    } else {
779                        Rc::default()
780                    });
781                }
782                *dst.borrow_mut() = Value::Function(FunctionKind::Function(Rc::new(Function {
783                    upvalues,
784                    closure,
785                })));
786            }
787            ByteCode::Binary {
788                op,
789                dst,
790                left,
791                right,
792            } => {
793                let dst_value = self
794                    .call_frames
795                    .last_mut()
796                    .expect("no call frame")
797                    .location(&dst)
798                    .expect("location not found");
799                let left = self
800                    .call_frames
801                    .last_mut()
802                    .expect("no call frame")
803                    .source(&left)
804                    .expect("source not found");
805                let right = self
806                    .call_frames
807                    .last_mut()
808                    .expect("no call frame")
809                    .source(&right)
810                    .expect("source not found");
811                if let Value::Object(object) = &left {
812                    if let Some(Value::Function(kind)) = {
813                        let object = object.borrow();
814                        object.get_meta(&format!("__{}", op))
815                    } {
816                        self.call_kind(kind, vec![left, right], Some(dst), pos)?;
817                        return Ok(None);
818                    }
819                }
820                *dst_value.borrow_mut() = match op {
821                    BinaryOperation::Add => match (left, right) {
822                        (Value::Int(left), Value::Int(right)) => Value::Int(left + right),
823                        (Value::Float(left), Value::Float(right)) => Value::Float(left + right),
824                        (Value::Int(left), Value::Float(right)) => {
825                            Value::Float(left as f64 + right)
826                        }
827                        (Value::Float(left), Value::Int(right)) => {
828                            Value::Float(left + right as f64)
829                        }
830                        (Value::String(left), Value::String(right)) => Value::String(left + &right),
831                        (Value::String(mut left), Value::Char(right)) => {
832                            left.push(right);
833                            Value::String(left)
834                        }
835                        (left, right) => {
836                            return Err(Located::new(
837                                RunTimeError::InvalidBinary {
838                                    op,
839                                    left: left.dynamic_typ(),
840                                    right: right.dynamic_typ(),
841                                },
842                                pos,
843                            ))
844                        }
845                    },
846                    BinaryOperation::Sub => match (left, right) {
847                        (Value::Int(left), Value::Int(right)) => Value::Int(left - right),
848                        (Value::Float(left), Value::Float(right)) => Value::Float(left - right),
849                        (Value::Int(left), Value::Float(right)) => {
850                            Value::Float(left as f64 - right)
851                        }
852                        (Value::Float(left), Value::Int(right)) => {
853                            Value::Float(left - right as f64)
854                        }
855                        (left, right) => {
856                            return Err(Located::new(
857                                RunTimeError::InvalidBinary {
858                                    op,
859                                    left: left.dynamic_typ(),
860                                    right: right.dynamic_typ(),
861                                },
862                                pos,
863                            ))
864                        }
865                    },
866                    BinaryOperation::Mul => match (left, right) {
867                        (Value::Int(left), Value::Int(right)) => Value::Int(left * right),
868                        (Value::Float(left), Value::Float(right)) => Value::Float(left * right),
869                        (Value::Int(left), Value::Float(right)) => {
870                            Value::Float(left as f64 * right)
871                        }
872                        (Value::Float(left), Value::Int(right)) => {
873                            Value::Float(left * right as f64)
874                        }
875                        (left, right) => {
876                            return Err(Located::new(
877                                RunTimeError::InvalidBinary {
878                                    op,
879                                    left: left.dynamic_typ(),
880                                    right: right.dynamic_typ(),
881                                },
882                                pos,
883                            ))
884                        }
885                    },
886                    BinaryOperation::Div => match (left, right) {
887                        (Value::Int(left), Value::Int(right)) => {
888                            Value::Float(left as f64 / right as f64)
889                        }
890                        (Value::Float(left), Value::Float(right)) => Value::Float(left / right),
891                        (Value::Int(left), Value::Float(right)) => {
892                            Value::Float(left as f64 / right)
893                        }
894                        (Value::Float(left), Value::Int(right)) => {
895                            Value::Float(left / right as f64)
896                        }
897                        (left, right) => {
898                            return Err(Located::new(
899                                RunTimeError::InvalidBinary {
900                                    op,
901                                    left: left.dynamic_typ(),
902                                    right: right.dynamic_typ(),
903                                },
904                                pos,
905                            ))
906                        }
907                    },
908                    BinaryOperation::Pow => match (left, right) {
909                        (Value::Int(left), Value::Int(right)) => {
910                            Value::Float((left as f64).powf(right as f64))
911                        }
912                        (Value::Float(left), Value::Float(right)) => Value::Float(left.powf(right)),
913                        (Value::Int(left), Value::Float(right)) => {
914                            Value::Float((left as f64).powf(right))
915                        }
916                        (Value::Float(left), Value::Int(right)) => {
917                            Value::Float(left.powf(right as f64))
918                        }
919                        (left, right) => {
920                            return Err(Located::new(
921                                RunTimeError::InvalidBinary {
922                                    op,
923                                    left: left.dynamic_typ(),
924                                    right: right.dynamic_typ(),
925                                },
926                                pos,
927                            ))
928                        }
929                    },
930                    BinaryOperation::Mod => match (left, right) {
931                        (Value::Int(left), Value::Int(right)) => Value::Int(left % right),
932                        (Value::Float(left), Value::Float(right)) => Value::Float(left % right),
933                        (Value::Int(left), Value::Float(right)) => {
934                            Value::Float(left as f64 % right)
935                        }
936                        (Value::Float(left), Value::Int(right)) => {
937                            Value::Float(left % right as f64)
938                        }
939                        (left, right) => {
940                            return Err(Located::new(
941                                RunTimeError::InvalidBinary {
942                                    op,
943                                    left: left.dynamic_typ(),
944                                    right: right.dynamic_typ(),
945                                },
946                                pos,
947                            ))
948                        }
949                    },
950                    BinaryOperation::EQ => Value::Bool(left == right),
951                    BinaryOperation::NE => Value::Bool(left != right),
952                    BinaryOperation::LT => match (left, right) {
953                        (Value::Int(left), Value::Int(right)) => Value::Bool(left < right),
954                        (Value::Float(left), Value::Float(right)) => Value::Bool(left < right),
955                        (Value::Int(left), Value::Float(right)) => {
956                            Value::Bool((left as f64) < right)
957                        }
958                        (Value::Float(left), Value::Int(right)) => Value::Bool(left < right as f64),
959                        (left, right) => {
960                            return Err(Located::new(
961                                RunTimeError::InvalidBinary {
962                                    op,
963                                    left: left.dynamic_typ(),
964                                    right: right.dynamic_typ(),
965                                },
966                                pos,
967                            ))
968                        }
969                    },
970                    BinaryOperation::GT => match (left, right) {
971                        (Value::Int(left), Value::Int(right)) => Value::Bool(left > right),
972                        (Value::Float(left), Value::Float(right)) => Value::Bool(left > right),
973                        (Value::Int(left), Value::Float(right)) => Value::Bool(left as f64 > right),
974                        (Value::Float(left), Value::Int(right)) => Value::Bool(left > right as f64),
975                        (left, right) => {
976                            return Err(Located::new(
977                                RunTimeError::InvalidBinary {
978                                    op,
979                                    left: left.dynamic_typ(),
980                                    right: right.dynamic_typ(),
981                                },
982                                pos,
983                            ))
984                        }
985                    },
986                    BinaryOperation::LE => match (left, right) {
987                        (Value::Int(left), Value::Int(right)) => Value::Bool(left <= right),
988                        (Value::Float(left), Value::Float(right)) => Value::Bool(left <= right),
989                        (Value::Int(left), Value::Float(right)) => {
990                            Value::Bool(left as f64 <= right)
991                        }
992                        (Value::Float(left), Value::Int(right)) => {
993                            Value::Bool(left <= right as f64)
994                        }
995                        (left, right) => {
996                            return Err(Located::new(
997                                RunTimeError::InvalidBinary {
998                                    op,
999                                    left: left.dynamic_typ(),
1000                                    right: right.dynamic_typ(),
1001                                },
1002                                pos,
1003                            ))
1004                        }
1005                    },
1006                    BinaryOperation::GE => match (left, right) {
1007                        (Value::Int(left), Value::Int(right)) => Value::Bool(left >= right),
1008                        (Value::Float(left), Value::Float(right)) => Value::Bool(left >= right),
1009                        (Value::Int(left), Value::Float(right)) => {
1010                            Value::Bool(left as f64 >= right)
1011                        }
1012                        (Value::Float(left), Value::Int(right)) => {
1013                            Value::Bool(left >= right as f64)
1014                        }
1015                        (left, right) => {
1016                            return Err(Located::new(
1017                                RunTimeError::InvalidBinary {
1018                                    op,
1019                                    left: left.dynamic_typ(),
1020                                    right: right.dynamic_typ(),
1021                                },
1022                                pos,
1023                            ))
1024                        }
1025                    },
1026                    BinaryOperation::And => Value::Bool(left.into() && right.into()),
1027                    BinaryOperation::Or => Value::Bool(left.into() || right.into()),
1028                };
1029            }
1030            ByteCode::Unary { op, dst, src } => {
1031                let dst_value = self
1032                    .call_frames
1033                    .last_mut()
1034                    .expect("no call frame")
1035                    .location(&dst)
1036                    .expect("location not found");
1037                let src = self
1038                    .call_frames
1039                    .last_mut()
1040                    .expect("no call frame")
1041                    .source(&src)
1042                    .expect("source not found");
1043                if let Value::Object(object) = &src {
1044                    if let Some(Value::Function(kind)) = {
1045                        let object = object.borrow();
1046                        object.get_meta(&format!("__{}", op))
1047                    } {
1048                        self.call_kind(kind, vec![src], Some(dst), pos)?;
1049                        return Ok(None);
1050                    }
1051                }
1052                *dst_value.borrow_mut() = match op {
1053                    UnaryOperation::Neg => match src {
1054                        Value::Int(v) => Value::Int(-v),
1055                        Value::Float(v) => Value::Float(-v),
1056                        src => {
1057                            return Err(Located::new(
1058                                RunTimeError::InvalidUnary {
1059                                    op,
1060                                    right: src.dynamic_typ(),
1061                                },
1062                                pos,
1063                            ))
1064                        }
1065                    },
1066                    UnaryOperation::Not => Value::Bool(!bool::from(src)),
1067                };
1068            }
1069        }
1070        Ok(None)
1071    }
1072    pub fn run(&mut self) -> Result<Option<Value>, Located<RunTimeError>> {
1073        let level = self.call_frames.len();
1074        loop {
1075            let value = self.step()?;
1076            if self.call_frames.len() < level || self.call_frames.is_empty() {
1077                return Ok(value);
1078            }
1079        }
1080    }
1081}
1082impl CallFrame {
1083    #[inline(always)]
1084    pub fn path(&self) -> Option<String> {
1085        self.function.closure.borrow().path.clone()
1086    }
1087    #[inline(always)]
1088    pub fn register(&self, register: Register) -> Option<Rc<RefCell<Value>>> {
1089        self.stack.get(register as usize).cloned()
1090    }
1091    #[inline(always)]
1092    pub fn source(&self, source: &Source) -> Option<Value> {
1093        match source {
1094            Source::Register(register) => {
1095                self.register(*register).map(|value| value.borrow().clone())
1096            }
1097            Source::Upvalue(addr) => self
1098                .function
1099                .upvalues
1100                .get(*addr as usize)
1101                .map(|value| value.borrow().clone()),
1102            Source::Global(addr) => {
1103                if let Value::String(ident) = self
1104                    .function
1105                    .closure
1106                    .borrow()
1107                    .consts
1108                    .get(*addr as usize)
1109                    .expect("constant not found")
1110                {
1111                    Some(
1112                        self.globals
1113                            .borrow()
1114                            .get(ident)
1115                            .map(|value| value.borrow().clone())
1116                            .unwrap_or_default(),
1117                    )
1118                } else {
1119                    panic!("expected a string for the global")
1120                }
1121            }
1122            Source::Constant(addr) => self
1123                .function
1124                .closure
1125                .borrow()
1126                .consts
1127                .get(*addr as usize)
1128                .cloned(),
1129            Source::Null => Some(Value::default()),
1130            Source::Bool(v) => Some(Value::Bool(*v)),
1131            Source::Char(v) => Some(Value::Char(*v)),
1132        }
1133    }
1134    #[inline(always)]
1135    pub fn location(&mut self, location: &Location) -> Option<Rc<RefCell<Value>>> {
1136        match location {
1137            Location::Register(register) => self.register(*register),
1138            Location::Upvalue(addr) => self.function.upvalues.get(*addr as usize).map(Rc::clone),
1139            Location::Global(addr) => {
1140                if let Value::String(ident) = self
1141                    .function
1142                    .closure
1143                    .borrow()
1144                    .consts
1145                    .get(*addr as usize)
1146                    .expect("constant not found")
1147                {
1148                    let mut globals = self.globals.borrow_mut();
1149                    if let Some(value) = globals.get(ident).cloned() {
1150                        Some(value)
1151                    } else {
1152                        globals.insert(ident.clone(), Rc::new(RefCell::new(Value::default())));
1153                        globals.get(ident).cloned()
1154                    }
1155                } else {
1156                    panic!("expected a string for the global")
1157                }
1158            }
1159        }
1160    }
1161}
1162impl Display for RunTimeError {
1163    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1164        match self {
1165            RunTimeError::CannotCall(typ) => write!(f, "can not call {typ}"),
1166            RunTimeError::CannotIter(typ) => write!(f, "can not iterate over {typ}"),
1167            RunTimeError::CannotFieldInto { head, field } => {
1168                write!(f, "can not field into {head} with {field}")
1169            }
1170            RunTimeError::CannotField(typ) => write!(f, "can not field into {typ}"),
1171            RunTimeError::CannotSetFieldWith { head, field } => {
1172                write!(f, "can not set field of {head} with {field}")
1173            }
1174            RunTimeError::CannotSetField(head) => write!(f, "can not set field of {head}"),
1175            RunTimeError::InvalidSetIndex(index) => {
1176                write!(f, "invalid set index {index:?} (out of range)")
1177            }
1178            RunTimeError::InvalidBinary { op, left, right } => write!(
1179                f,
1180                "attempt to perform binary operation {:?} on {left} with {right}",
1181                format!("{:?}", op).to_lowercase()
1182            ),
1183            RunTimeError::InvalidUnary { op, right } => write!(
1184                f,
1185                "attempt to perform unary operation {:?} on {right}",
1186                format!("{:?}", op).to_lowercase()
1187            ),
1188            RunTimeError::Custom(msg) => write!(f, "{msg}"),
1189        }
1190    }
1191}
1192impl Error for RunTimeError {}