luna_lib/luna_impl/
compiler.rs

1use super::{
2    position::{Located, Position},
3    std::FOR_FUNC,
4};
5use crate::lang::{
6    ast::*,
7    code::{
8        Address, BinaryOperation, ByteCode, Closure, Location, ObjectSize, Register, Source,
9        Upvalue, VectorSize,
10    },
11    value::Value,
12};
13use std::{
14    cell::RefCell,
15    collections::{HashMap, HashSet},
16    error::Error,
17    rc::Rc,
18};
19
20#[derive(Debug, Default)]
21pub struct Compiler {
22    pub frames: Vec<CompilerFrame>,
23    pub path: Option<String>,
24}
25#[derive(Debug, Default)]
26pub struct CompilerFrame {
27    pub closure: Rc<RefCell<Closure>>,
28    pub(crate) scopes: Vec<Scope>,
29    pub(crate) registers: Register,
30}
31#[derive(Debug, Clone, Default)]
32pub struct Scope {
33    pub(crate) locals: HashMap<String, Register>,
34    pub(crate) register_offset: Register,
35    pub(crate) breaks: HashSet<Address>,
36    pub(crate) continues: HashSet<Address>,
37}
38pub trait Compilable {
39    type Output;
40    fn compile(self, compiler: &mut Compiler) -> Result<Self::Output, Located<Box<dyn Error>>>;
41}
42
43pub const COMPILER_FRAME_EXPECT: &str = "no compiler frame on stack";
44pub const COMPILER_SCOPE_EXPECT: &str = "no scope on stack";
45macro_rules! compiler_frame {
46    ($compiler:ident) => {
47        $compiler.frame().expect(COMPILER_FRAME_EXPECT)
48    };
49}
50macro_rules! compiler_frame_mut {
51    ($compiler:ident) => {
52        $compiler.frame_mut().expect(COMPILER_FRAME_EXPECT)
53    };
54}
55impl Compiler {
56    pub fn new(path: Option<String>) -> Self {
57        Self {
58            frames: vec![CompilerFrame {
59                closure: Rc::new(RefCell::new(Closure {
60                    path: path.clone(),
61                    ..Default::default()
62                })),
63                scopes: vec![Scope::default()],
64                registers: 0,
65            }],
66            path,
67        }
68    }
69    pub fn push_frame(&mut self, frame: CompilerFrame) {
70        self.frames.push(frame);
71    }
72    pub fn pop_frame(&mut self) -> Option<CompilerFrame> {
73        self.frames.pop()
74    }
75    pub fn frame(&self) -> Option<&CompilerFrame> {
76        self.frames.last()
77    }
78    pub fn frame_mut(&mut self) -> Option<&mut CompilerFrame> {
79        self.frames.last_mut()
80    }
81    pub fn get_variable_location(&mut self, ident: &str) -> Option<Location> {
82        if let Some(register) = self.frame_mut().expect("no frame").get_local(ident) {
83            return Some(Location::Register(register));
84        }
85        for (depth, other_frame) in self.frames.iter_mut().rev().skip(1).enumerate() {
86            if let Some(register) = other_frame.get_local(ident) {
87                let frame = self.frame_mut().expect("no frame");
88                let addr = frame.closure.borrow().upvalues.len() as Address;
89                let upvalue = Upvalue {
90                    register,
91                    depth: depth as u8,
92                };
93                if let Some(addr) = frame
94                    .closure
95                    .borrow_mut()
96                    .upvalues
97                    .iter()
98                    .position(|upv| upv == &upvalue)
99                {
100                    return Some(Location::Upvalue(addr as Address));
101                }
102                frame.closure.borrow_mut().upvalues.push(upvalue);
103                return Some(Location::Upvalue(addr));
104            }
105        }
106        None
107    }
108}
109impl CompilerFrame {
110    pub fn write(&mut self, bytecode: ByteCode, pos: Position) -> Address {
111        let addr = self.closure.borrow().code.len() as Address;
112        self.closure
113            .borrow_mut()
114            .code
115            .push(Located::new(bytecode, pos));
116        addr
117    }
118    pub fn overwrite(&mut self, addr: Address, bytecode: ByteCode, pos: Option<Position>) {
119        let mut closure = self.closure.borrow_mut();
120        let old = closure.code.get_mut(addr as usize).expect("invalid addr");
121        *old = Located::new(bytecode, pos.unwrap_or(old.pos.clone()));
122    }
123    pub fn addr(&self) -> Address {
124        self.closure.borrow().code.len() as Address
125    }
126    pub fn new_const(&mut self, value: Value) -> Address {
127        let consts = &mut self.closure.borrow_mut().consts;
128        if let Some(pos) = consts.iter().position(|v| v == &value) {
129            return pos as Address;
130        }
131        let addr = consts.len();
132        consts.push(value);
133        addr as Address
134    }
135    pub fn new_closure(&mut self, value: Rc<RefCell<Closure>>) -> Address {
136        let closures = &mut self.closure.borrow_mut().closures;
137        let addr = closures.len();
138        closures.push(value);
139        addr as Address
140    }
141    pub fn new_register(&mut self) -> Register {
142        let addr = self.registers;
143        self.registers += 1;
144        if self.registers > self.closure.borrow().registers {
145            self.closure.borrow_mut().registers = self.registers;
146        }
147        addr
148    }
149    pub fn add_registers(&mut self, amount: Register) {
150        self.registers += amount;
151        if self.registers > self.closure.borrow().registers {
152            self.closure.borrow_mut().registers = self.registers;
153        }
154    }
155    pub fn push_scope(&mut self) {
156        let register_offset = self.registers;
157        self.scopes.push(Scope {
158            register_offset,
159            ..Default::default()
160        });
161    }
162    pub fn pop_scope(&mut self) -> Option<Scope> {
163        if let Some(scope) = self.scopes.pop() {
164            self.registers = scope.register_offset;
165            return Some(scope);
166        }
167        None
168    }
169    pub fn scope(&self) -> Option<&Scope> {
170        self.scopes.last()
171    }
172    pub fn scope_mut(&mut self) -> Option<&mut Scope> {
173        self.scopes.last_mut()
174    }
175    pub fn new_local(&mut self, ident: String) -> Register {
176        let register = self.new_register();
177        let scope = self.scope_mut().expect("no scope");
178        scope.set_local(ident, register);
179        register
180    }
181    pub fn get_local(&self, ident: &str) -> Option<Register> {
182        self.scopes
183            .iter()
184            .rev()
185            .find(|scope| scope.get_local(ident).is_some())
186            .and_then(|scope| scope.get_local(ident))
187    }
188}
189impl Scope {
190    pub fn set_local(&mut self, ident: String, register: Register) -> Option<Register> {
191        self.locals.insert(ident, register)
192    }
193    pub fn get_local(&self, ident: &str) -> Option<Register> {
194        self.locals.get(ident).cloned()
195    }
196}
197
198impl Compilable for Located<Chunk> {
199    type Output = Rc<RefCell<Closure>>;
200    fn compile(self, compiler: &mut Compiler) -> Result<Self::Output, Located<Box<dyn Error>>> {
201        let Located { value: chunk, pos } = self;
202        compiler.push_frame(CompilerFrame {
203            closure: Rc::new(RefCell::new(Closure {
204                path: compiler.path.clone(),
205                ..Default::default()
206            })),
207            scopes: vec![Scope::default()],
208            registers: 0,
209        });
210        for stat in chunk.0 {
211            stat.compile(compiler)?;
212        }
213        compiler_frame_mut!(compiler).write(ByteCode::Return { src: None }, pos);
214        Ok(compiler
215            .pop_frame()
216            .expect("no compiler frame on stack")
217            .closure)
218    }
219}
220impl Compilable for Located<Block> {
221    type Output = Option<Source>;
222    fn compile(self, compiler: &mut Compiler) -> Result<Self::Output, Located<Box<dyn Error>>> {
223        let Located {
224            value: block,
225            pos: _,
226        } = self;
227        for stat in block.0 {
228            stat.compile(compiler)?;
229        }
230        Ok(None)
231    }
232}
233impl Compilable for Located<Statement> {
234    type Output = Option<Source>;
235    fn compile(self, compiler: &mut Compiler) -> Result<Self::Output, Located<Box<dyn Error>>> {
236        let Located { value: stat, pos } = self;
237        match stat {
238            Statement::Block(block) => {
239                compiler_frame_mut!(compiler).push_scope();
240                Located::new(block, pos).compile(compiler)?;
241                let scope = compiler_frame_mut!(compiler)
242                    .pop_scope()
243                    .expect("no scope on stack");
244                if !scope.breaks.is_empty() {
245                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
246                        prev_scope.breaks.extend(scope.breaks);
247                    }
248                }
249                if !scope.continues.is_empty() {
250                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
251                        prev_scope.continues.extend(scope.continues);
252                    }
253                }
254                Ok(None)
255            }
256            Statement::LetBinding { params, mut exprs } => {
257                for Located { value: param, pos } in params.into_iter() {
258                    let src = if exprs.is_empty() {
259                        Source::default()
260                    } else {
261                        exprs.remove(0).compile(compiler)?
262                    };
263                    match param {
264                        Parameter::Ident(ident) => {
265                            let dst =
266                                Location::Register(compiler_frame_mut!(compiler).new_local(ident));
267                            compiler_frame_mut!(compiler).write(ByteCode::Move { dst, src }, pos);
268                        }
269                        Parameter::Object(fields) => {
270                            for Located { value: ident, pos } in fields.into_iter() {
271                                let field = Source::Constant(
272                                    compiler_frame_mut!(compiler)
273                                        .new_const(Value::String(ident.clone())),
274                                );
275                                let dst = Location::Register(
276                                    compiler_frame_mut!(compiler).new_local(ident),
277                                );
278                                compiler_frame_mut!(compiler).write(
279                                    ByteCode::Field {
280                                        dst,
281                                        head: src,
282                                        field,
283                                    },
284                                    pos,
285                                );
286                            }
287                        }
288                        Parameter::Vector(idents) => {
289                            for (idx, Located { value: ident, pos }) in
290                                idents.into_iter().enumerate()
291                            {
292                                let field = Source::Constant(
293                                    compiler_frame_mut!(compiler)
294                                        .new_const(Value::Int(idx as isize as i64)),
295                                );
296                                let dst = Location::Register(
297                                    compiler_frame_mut!(compiler).new_local(ident),
298                                );
299                                compiler_frame_mut!(compiler).write(
300                                    ByteCode::Field {
301                                        dst,
302                                        head: src,
303                                        field,
304                                    },
305                                    pos,
306                                );
307                            }
308                        }
309                    }
310                }
311                Ok(None)
312            }
313            Statement::LetElse {
314                param:
315                    Located {
316                        value: param,
317                        pos: _,
318                    },
319                expr,
320                else_case,
321            } => {
322                let cond = expr.compile(compiler)?;
323                match param {
324                    Parameter::Ident(ident) => {
325                        let dst =
326                            Location::Register(compiler_frame_mut!(compiler).new_local(ident));
327                        compiler_frame_mut!(compiler).write(ByteCode::Move { dst, src: cond }, pos.clone());
328                    }
329                    Parameter::Object(fields) => {
330                        for Located { value: ident, pos } in fields.into_iter() {
331                            let field = Source::Constant(
332                                compiler_frame_mut!(compiler)
333                                    .new_const(Value::String(ident.clone())),
334                            );
335                            let dst =
336                                Location::Register(compiler_frame_mut!(compiler).new_local(ident));
337                            compiler_frame_mut!(compiler).write(
338                                ByteCode::Field {
339                                    dst,
340                                    head: cond,
341                                    field,
342                                },
343                                pos,
344                            );
345                        }
346                    }
347                    Parameter::Vector(idents) => {
348                        for (idx, Located { value: ident, pos }) in idents.into_iter().enumerate() {
349                            let field = Source::Constant(
350                                compiler_frame_mut!(compiler)
351                                    .new_const(Value::Int(idx as isize as i64)),
352                            );
353                            let dst =
354                                Location::Register(compiler_frame_mut!(compiler).new_local(ident));
355                            compiler_frame_mut!(compiler).write(
356                                ByteCode::Field {
357                                    dst,
358                                    head: cond,
359                                    field,
360                                },
361                                pos,
362                            );
363                        }
364                    }
365                }
366                let check_addr =
367                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
368                compiler_frame_mut!(compiler).push_scope();
369                else_case.compile(compiler)?;
370                let scope = compiler_frame_mut!(compiler)
371                    .pop_scope()
372                    .expect(COMPILER_SCOPE_EXPECT);
373                if !scope.breaks.is_empty() {
374                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
375                        prev_scope.breaks.extend(scope.breaks);
376                    }
377                }
378                if !scope.continues.is_empty() {
379                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
380                        prev_scope.continues.extend(scope.continues);
381                    }
382                }
383                let exit_addr = compiler_frame_mut!(compiler).addr();
384                compiler_frame_mut!(compiler).overwrite(
385                    check_addr,
386                    ByteCode::JumpNull {
387                        negative: true,
388                        cond,
389                        addr: exit_addr + 1,
390                    },
391                    Some(pos.clone()),
392                );
393                Ok(None)
394            }
395            Statement::Assign { paths, mut exprs } => {
396                for Located {
397                    value: path,
398                    pos: path_pos,
399                } in paths.into_iter()
400                {
401                    let src = if exprs.is_empty() {
402                        Source::default()
403                    } else {
404                        exprs.remove(0).compile(compiler)?
405                    };
406                    match path {
407                        Path::Ident(ident) => {
408                            let dst = compiler.get_variable_location(&ident).unwrap_or_else(|| {
409                                let addr =
410                                    compiler_frame_mut!(compiler).new_const(Value::String(ident));
411                                Location::Global(addr)
412                            });
413                            compiler_frame_mut!(compiler)
414                                .write(ByteCode::Move { dst, src }, path_pos);
415                        }
416                        Path::Field {
417                            head,
418                            field:
419                                Located {
420                                    value: field,
421                                    pos: _,
422                                },
423                        } => {
424                            let head = head.compile(compiler)?;
425                            let field =
426                                compiler_frame_mut!(compiler).new_const(Value::String(field));
427                            compiler_frame_mut!(compiler).write(
428                                ByteCode::SetField {
429                                    head: head.into(),
430                                    field: Source::Constant(field),
431                                    src,
432                                },
433                                path_pos,
434                            );
435                        }
436                        Path::Index { head, index } => {
437                            let head = head.compile(compiler)?;
438                            let field = index.compile(compiler)?;
439                            compiler_frame_mut!(compiler).write(
440                                ByteCode::SetField {
441                                    head: head.into(),
442                                    field,
443                                    src,
444                                },
445                                path_pos,
446                            );
447                        }
448                    }
449                }
450                Ok(None)
451            }
452            Statement::AssignOperation {
453                op,
454                path:
455                    Located {
456                        value: path,
457                        pos: path_pos,
458                    },
459                expr,
460            } => {
461                let src = expr.compile(compiler)?;
462                match path {
463                    Path::Ident(ident) => {
464                        let dst = compiler.get_variable_location(&ident).unwrap_or_else(|| {
465                            let addr =
466                                compiler_frame_mut!(compiler).new_const(Value::String(ident));
467                            Location::Global(addr)
468                        });
469                        compiler_frame_mut!(compiler).write(
470                            ByteCode::Binary {
471                                op: op.into(),
472                                dst,
473                                left: dst.into(),
474                                right: src,
475                            },
476                            path_pos,
477                        );
478                    }
479                    Path::Field {
480                        head,
481                        field:
482                            Located {
483                                value: field,
484                                pos: _,
485                            },
486                    } => {
487                        let head = head.compile(compiler)?;
488                        let field = compiler_frame_mut!(compiler).new_const(Value::String(field));
489                        let dst = compiler_frame_mut!(compiler).new_register();
490                        compiler_frame_mut!(compiler).write(
491                            ByteCode::Field {
492                                dst: Location::Register(dst),
493                                head: head.into(),
494                                field: Source::Constant(field),
495                            },
496                            path_pos.clone(),
497                        );
498                        compiler_frame_mut!(compiler).write(
499                            ByteCode::Binary {
500                                op: op.into(),
501                                dst: Location::Register(dst),
502                                left: Source::Register(dst),
503                                right: src,
504                            },
505                            path_pos.clone(),
506                        );
507                        compiler_frame_mut!(compiler).write(
508                            ByteCode::SetField {
509                                head: head.into(),
510                                field: Source::Constant(field),
511                                src: Source::Register(dst),
512                            },
513                            path_pos,
514                        );
515                    }
516                    Path::Index { head, index } => {
517                        let head = head.compile(compiler)?;
518                        let field = index.compile(compiler)?;
519                        let dst = compiler_frame_mut!(compiler).new_register();
520                        compiler_frame_mut!(compiler).write(
521                            ByteCode::Field {
522                                dst: Location::Register(dst),
523                                head: head.into(),
524                                field,
525                            },
526                            path_pos.clone(),
527                        );
528                        compiler_frame_mut!(compiler).write(
529                            ByteCode::Binary {
530                                op: op.into(),
531                                dst: Location::Register(dst),
532                                left: Source::Register(dst),
533                                right: src,
534                            },
535                            path_pos.clone(),
536                        );
537                        compiler_frame_mut!(compiler).write(
538                            ByteCode::SetField {
539                                head: head.into(),
540                                field,
541                                src: Source::Register(dst),
542                            },
543                            path_pos,
544                        );
545                    }
546                }
547                Ok(None)
548            }
549            Statement::Call { path, mut args } => {
550                let path_location = path.compile(compiler)?;
551                let amount = args.len() as u8;
552                match amount {
553                    0 => {
554                        compiler_frame_mut!(compiler).write(
555                            ByteCode::CallZero {
556                                dst: None,
557                                func: path_location.into(),
558                            },
559                            pos,
560                        );
561                    }
562                    1 => {
563                        let arg = args.remove(0).compile(compiler)?;
564                        compiler_frame_mut!(compiler).write(
565                            ByteCode::CallSingle {
566                                dst: None,
567                                func: path_location.into(),
568                                arg,
569                            },
570                            pos,
571                        );
572                    }
573                    amount => {
574                        let offset = compiler_frame_mut!(compiler).registers;
575                        compiler_frame_mut!(compiler).add_registers(amount as Register);
576                        for (register, arg) in
577                            (offset..offset + amount as Register).zip(args.into_iter())
578                        {
579                            let pos = arg.pos.clone();
580                            let src = arg.compile(compiler)?;
581                            compiler_frame_mut!(compiler).write(
582                                ByteCode::Move {
583                                    dst: Location::Register(register),
584                                    src,
585                                },
586                                pos,
587                            );
588                        }
589                        compiler_frame_mut!(compiler).registers = offset;
590                        compiler_frame_mut!(compiler).write(
591                            ByteCode::Call {
592                                dst: None,
593                                func: path_location.into(),
594                                offset,
595                                amount,
596                            },
597                            pos,
598                        );
599                    }
600                }
601                Ok(None)
602            }
603            Statement::SelfCall {
604                head,
605                field:
606                    Located {
607                        value: field,
608                        pos: field_pos,
609                    },
610                args,
611            } => {
612                let head_pos = head.pos.clone();
613                let head_location = head.compile(compiler)?;
614                let func = {
615                    let head: Source = head_location.into();
616                    let dst = compiler_frame_mut!(compiler).new_register();
617                    let field_addr = compiler_frame_mut!(compiler).new_const(Value::String(field));
618                    compiler_frame_mut!(compiler).write(
619                        ByteCode::Field {
620                            dst: Location::Register(dst),
621                            head,
622                            field: Source::Constant(field_addr),
623                        },
624                        field_pos,
625                    );
626                    Source::Register(dst)
627                };
628                let amount = args.len() as u8 + 1;
629                match amount {
630                    1 => {
631                        let offset = compiler_frame_mut!(compiler).registers;
632                        let arg = head_location.into();
633                        compiler_frame_mut!(compiler).registers = offset;
634                        compiler_frame_mut!(compiler).write(
635                            ByteCode::CallSingle {
636                                dst: None,
637                                func,
638                                arg,
639                            },
640                            pos,
641                        );
642                    }
643                    amount => {
644                        let offset = compiler_frame_mut!(compiler).registers;
645                        let head_register = compiler_frame_mut!(compiler).new_register();
646                        compiler_frame_mut!(compiler).write(
647                            ByteCode::Move {
648                                dst: Location::Register(head_register),
649                                src: head_location.into(),
650                            },
651                            head_pos,
652                        );
653                        compiler_frame_mut!(compiler).registers += amount as Register;
654                        for (register, arg) in
655                            (offset + 1..offset + amount as Register).zip(args.into_iter())
656                        {
657                            let pos = arg.pos.clone();
658                            let src = arg.compile(compiler)?;
659                            compiler_frame_mut!(compiler).write(
660                                ByteCode::Move {
661                                    dst: Location::Register(register),
662                                    src,
663                                },
664                                pos,
665                            );
666                        }
667                        compiler_frame_mut!(compiler).registers = offset;
668                        compiler_frame_mut!(compiler).write(
669                            ByteCode::Call {
670                                dst: None,
671                                func,
672                                offset,
673                                amount,
674                            },
675                            pos,
676                        );
677                    }
678                }
679                Ok(None)
680            }
681            Statement::Fn {
682                path:
683                    Located {
684                        value: path,
685                        pos: path_pos,
686                    },
687                params,
688                var_args: _,
689                body,
690            } => {
691                compiler.push_frame(CompilerFrame {
692                    closure: Rc::new(RefCell::new(Closure {
693                        path: compiler.path.clone(),
694                        ..Default::default()
695                    })),
696                    scopes: vec![Scope::default()],
697                    registers: 0,
698                });
699                for Located {
700                    value: param,
701                    pos: _,
702                } in params
703                {
704                    match param {
705                        Parameter::Ident(ident) => {
706                            compiler_frame_mut!(compiler).new_local(ident);
707                        }
708                        Parameter::Object(fields) => {
709                            let head =
710                                Source::Register(compiler_frame_mut!(compiler).new_register());
711                            for Located { value: ident, pos } in fields.into_iter() {
712                                let field = Source::Constant(
713                                    compiler_frame_mut!(compiler)
714                                        .new_const(Value::String(ident.clone())),
715                                );
716                                let dst = Location::Register(
717                                    compiler_frame_mut!(compiler).new_local(ident),
718                                );
719                                compiler_frame_mut!(compiler)
720                                    .write(ByteCode::Field { dst, head, field }, pos);
721                            }
722                        }
723                        Parameter::Vector(idents) => {
724                            let head =
725                                Source::Register(compiler_frame_mut!(compiler).new_register());
726                            for (idx, Located { value: ident, pos }) in
727                                idents.into_iter().enumerate()
728                            {
729                                let field = Source::Constant(
730                                    compiler_frame_mut!(compiler)
731                                        .new_const(Value::Int(idx as isize as i64)),
732                                );
733                                let dst = Location::Register(
734                                    compiler_frame_mut!(compiler).new_local(ident),
735                                );
736                                compiler_frame_mut!(compiler)
737                                    .write(ByteCode::Field { dst, head, field }, pos);
738                            }
739                        }
740                    }
741                }
742                body.compile(compiler)?;
743                compiler_frame_mut!(compiler).write(ByteCode::Return { src: None }, pos.clone());
744                let closure = compiler
745                    .pop_frame()
746                    .expect("no compiler frame on stack")
747                    .closure;
748                let addr = compiler_frame_mut!(compiler).new_closure(closure);
749                match path {
750                    Path::Ident(ident) => {
751                        let dst = compiler.get_variable_location(&ident).unwrap_or_else(|| {
752                            let addr =
753                                compiler_frame_mut!(compiler).new_const(Value::String(ident));
754                            Location::Global(addr)
755                        });
756                        compiler_frame_mut!(compiler).write(ByteCode::Function { dst, addr }, pos);
757                    }
758                    Path::Field {
759                        head,
760                        field:
761                            Located {
762                                value: field,
763                                pos: _,
764                            },
765                    } => {
766                        let head = head.compile(compiler)?;
767                        let field = compiler_frame_mut!(compiler).new_const(Value::String(field));
768                        let register = compiler_frame_mut!(compiler).new_register();
769                        compiler_frame_mut!(compiler).write(
770                            ByteCode::Function {
771                                dst: Location::Register(register),
772                                addr,
773                            },
774                            path_pos.clone(),
775                        );
776                        compiler_frame_mut!(compiler).write(
777                            ByteCode::SetField {
778                                head: head.into(),
779                                field: Source::Constant(field),
780                                src: Source::Register(register),
781                            },
782                            path_pos,
783                        );
784                        compiler_frame_mut!(compiler).registers = register;
785                    }
786                    Path::Index { head, index } => {
787                        let head = head.compile(compiler)?;
788                        let field = index.compile(compiler)?;
789                        let register = compiler_frame_mut!(compiler).new_register();
790                        compiler_frame_mut!(compiler).write(
791                            ByteCode::Function {
792                                dst: Location::Register(register),
793                                addr,
794                            },
795                            path_pos.clone(),
796                        );
797                        compiler_frame_mut!(compiler).write(
798                            ByteCode::SetField {
799                                head: head.into(),
800                                field,
801                                src: Source::Register(register),
802                            },
803                            path_pos,
804                        );
805                        compiler_frame_mut!(compiler).registers = register;
806                    }
807                }
808                Ok(None)
809            }
810            Statement::LetFn {
811                ident:
812                    Located {
813                        value: ident,
814                        pos: _,
815                    },
816                params,
817                var_args: _,
818                body,
819            } => {
820                let dst = Location::Register(compiler_frame_mut!(compiler).new_local(ident));
821                compiler.push_frame(CompilerFrame {
822                    closure: Rc::new(RefCell::new(Closure::default())),
823                    scopes: vec![Scope::default()],
824                    registers: 0,
825                });
826                for Located {
827                    value: param,
828                    pos: _,
829                } in params
830                {
831                    match param {
832                        Parameter::Ident(ident) => {
833                            compiler_frame_mut!(compiler).new_local(ident);
834                        }
835                        Parameter::Object(fields) => {
836                            let head =
837                                Source::Register(compiler_frame_mut!(compiler).new_register());
838                            for Located { value: ident, pos } in fields.into_iter() {
839                                let field = Source::Constant(
840                                    compiler_frame_mut!(compiler)
841                                        .new_const(Value::String(ident.clone())),
842                                );
843                                let dst = Location::Register(
844                                    compiler_frame_mut!(compiler).new_local(ident),
845                                );
846                                compiler_frame_mut!(compiler)
847                                    .write(ByteCode::Field { dst, head, field }, pos);
848                            }
849                        }
850                        Parameter::Vector(idents) => {
851                            let head =
852                                Source::Register(compiler_frame_mut!(compiler).new_register());
853                            for (idx, Located { value: ident, pos }) in
854                                idents.into_iter().enumerate()
855                            {
856                                let field = Source::Constant(
857                                    compiler_frame_mut!(compiler)
858                                        .new_const(Value::Int(idx as isize as i64)),
859                                );
860                                let dst = Location::Register(
861                                    compiler_frame_mut!(compiler).new_local(ident),
862                                );
863                                compiler_frame_mut!(compiler)
864                                    .write(ByteCode::Field { dst, head, field }, pos);
865                            }
866                        }
867                    }
868                }
869                body.compile(compiler)?;
870                compiler_frame_mut!(compiler).write(ByteCode::Return { src: None }, pos.clone());
871                let closure = compiler
872                    .pop_frame()
873                    .expect("no compiler frame on stack")
874                    .closure;
875                let addr = compiler_frame_mut!(compiler).new_closure(closure);
876                compiler_frame_mut!(compiler).write(ByteCode::Function { dst, addr }, pos);
877                Ok(None)
878            }
879            Statement::If {
880                cond,
881                case,
882                else_case,
883            } => {
884                let cond = cond.compile(compiler)?;
885                let check_addr =
886                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
887
888                compiler_frame_mut!(compiler).push_scope();
889                case.compile(compiler)?;
890                let scope = compiler_frame_mut!(compiler)
891                    .pop_scope()
892                    .expect(COMPILER_SCOPE_EXPECT);
893                if !scope.breaks.is_empty() {
894                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
895                        prev_scope.breaks.extend(scope.breaks);
896                    }
897                }
898                if !scope.continues.is_empty() {
899                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
900                        prev_scope.continues.extend(scope.continues);
901                    }
902                }
903                if let Some(else_case) = else_case {
904                    let else_addr = compiler_frame_mut!(compiler)
905                        .write(ByteCode::default(), Position::default());
906                    compiler_frame_mut!(compiler).push_scope();
907                    else_case.compile(compiler)?;
908                    let scope = compiler_frame_mut!(compiler)
909                        .pop_scope()
910                        .expect(COMPILER_SCOPE_EXPECT);
911                    if !scope.breaks.is_empty() {
912                        if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
913                            prev_scope.breaks.extend(scope.breaks);
914                        }
915                    }
916                    if !scope.continues.is_empty() {
917                        if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
918                            prev_scope.continues.extend(scope.continues);
919                        }
920                    }
921                    let exit_addr = compiler_frame_mut!(compiler).addr();
922                    compiler_frame_mut!(compiler).overwrite(
923                        check_addr,
924                        ByteCode::JumpIf {
925                            negative: true,
926                            cond,
927                            addr: else_addr + 1,
928                        },
929                        Some(pos.clone()),
930                    );
931                    compiler_frame_mut!(compiler).overwrite(
932                        else_addr,
933                        ByteCode::Jump { addr: exit_addr },
934                        Some(pos),
935                    );
936                } else {
937                    let exit_addr = compiler_frame_mut!(compiler).addr();
938                    compiler_frame_mut!(compiler).overwrite(
939                        check_addr,
940                        ByteCode::JumpIf {
941                            negative: true,
942                            cond,
943                            addr: exit_addr,
944                        },
945                        Some(pos.clone()),
946                    );
947                }
948
949                Ok(None)
950            }
951            Statement::IfLet {
952                param:
953                    Located {
954                        value: param,
955                        pos: _,
956                    },
957                expr,
958                case,
959                else_case,
960            } => {
961                compiler_frame_mut!(compiler).push_scope();
962                let cond = {
963                    let src = expr.compile(compiler)?;
964                    match param {
965                        Parameter::Ident(ident) => {
966                            let dst =
967                                Location::Register(compiler_frame_mut!(compiler).new_local(ident));
968                            compiler_frame_mut!(compiler)
969                                .write(ByteCode::Move { dst, src }, pos.clone());
970                        }
971                        Parameter::Object(fields) => {
972                            for Located { value: ident, pos } in fields.into_iter() {
973                                let field = Source::Constant(
974                                    compiler_frame_mut!(compiler)
975                                        .new_const(Value::String(ident.clone())),
976                                );
977                                let dst = Location::Register(
978                                    compiler_frame_mut!(compiler).new_local(ident),
979                                );
980                                compiler_frame_mut!(compiler).write(
981                                    ByteCode::Field {
982                                        dst,
983                                        head: src,
984                                        field,
985                                    },
986                                    pos,
987                                );
988                            }
989                        }
990                        Parameter::Vector(idents) => {
991                            for (idx, Located { value: ident, pos }) in
992                                idents.into_iter().enumerate()
993                            {
994                                let field = Source::Constant(
995                                    compiler_frame_mut!(compiler)
996                                        .new_const(Value::Int(idx as isize as i64)),
997                                );
998                                let dst = Location::Register(
999                                    compiler_frame_mut!(compiler).new_local(ident),
1000                                );
1001                                compiler_frame_mut!(compiler).write(
1002                                    ByteCode::Field {
1003                                        dst,
1004                                        head: src,
1005                                        field,
1006                                    },
1007                                    pos,
1008                                );
1009                            }
1010                        }
1011                    }
1012                    src
1013                };
1014                let check_addr =
1015                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
1016
1017                case.compile(compiler)?;
1018                let scope = compiler_frame_mut!(compiler)
1019                    .pop_scope()
1020                    .expect(COMPILER_SCOPE_EXPECT);
1021                if !scope.breaks.is_empty() {
1022                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
1023                        prev_scope.breaks.extend(scope.breaks);
1024                    }
1025                }
1026                if !scope.continues.is_empty() {
1027                    if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
1028                        prev_scope.continues.extend(scope.continues);
1029                    }
1030                }
1031                if let Some(else_case) = else_case {
1032                    let else_addr = compiler_frame_mut!(compiler)
1033                        .write(ByteCode::default(), Position::default());
1034                    compiler_frame_mut!(compiler).push_scope();
1035                    else_case.compile(compiler)?;
1036                    let scope = compiler_frame_mut!(compiler)
1037                        .pop_scope()
1038                        .expect(COMPILER_SCOPE_EXPECT);
1039                    if !scope.breaks.is_empty() {
1040                        if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
1041                            prev_scope.breaks.extend(scope.breaks);
1042                        }
1043                    }
1044                    if !scope.continues.is_empty() {
1045                        if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
1046                            prev_scope.continues.extend(scope.continues);
1047                        }
1048                    }
1049                    let exit_addr = compiler_frame_mut!(compiler).addr();
1050                    compiler_frame_mut!(compiler).overwrite(
1051                        check_addr,
1052                        ByteCode::JumpNull {
1053                            negative: false,
1054                            cond,
1055                            addr: else_addr + 1,
1056                        },
1057                        Some(pos.clone()),
1058                    );
1059                    compiler_frame_mut!(compiler).overwrite(
1060                        else_addr,
1061                        ByteCode::Jump { addr: exit_addr },
1062                        Some(pos),
1063                    );
1064                } else {
1065                    let exit_addr = compiler_frame_mut!(compiler).addr();
1066                    compiler_frame_mut!(compiler).overwrite(
1067                        check_addr,
1068                        ByteCode::JumpNull {
1069                            negative: false,
1070                            cond,
1071                            addr: exit_addr,
1072                        },
1073                        Some(pos.clone()),
1074                    );
1075                }
1076
1077                Ok(None)
1078            }
1079            Statement::Match { expr, cases } => {
1080                let expr = expr.compile(compiler)?;
1081                let registers = compiler_frame!(compiler).registers;
1082                let dst = Location::Register(compiler_frame_mut!(compiler).new_register());
1083                let mut exits = vec![];
1084                for (pattern, body) in cases {
1085                    compiler_frame_mut!(compiler).push_scope();
1086                    pattern.compile_match(compiler, expr, dst)?;
1087                    let check_addr = compiler_frame_mut!(compiler)
1088                        .write(ByteCode::default(), Position::default());
1089                    body.compile(compiler)?;
1090                    let scope = compiler_frame_mut!(compiler)
1091                        .pop_scope()
1092                        .expect(COMPILER_SCOPE_EXPECT);
1093                    if !scope.breaks.is_empty() {
1094                        if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
1095                            prev_scope.breaks.extend(scope.breaks);
1096                        }
1097                    }
1098                    if !scope.continues.is_empty() {
1099                        if let Some(prev_scope) = compiler_frame_mut!(compiler).scope_mut() {
1100                            prev_scope.continues.extend(scope.continues);
1101                        }
1102                    }
1103                    let exit_addr = compiler_frame_mut!(compiler)
1104                        .write(ByteCode::default(), Position::default());
1105                    compiler_frame_mut!(compiler).overwrite(
1106                        check_addr,
1107                        ByteCode::JumpIf {
1108                            negative: true,
1109                            cond: dst.into(),
1110                            addr: exit_addr + 1,
1111                        },
1112                        Some(pos.clone()),
1113                    );
1114                    exits.push(exit_addr);
1115                }
1116                let exit_addr = compiler_frame_mut!(compiler).addr();
1117                for addr in exits {
1118                    if addr + 1 != exit_addr {
1119                        compiler_frame_mut!(compiler).overwrite(
1120                            addr,
1121                            ByteCode::Jump { addr: exit_addr },
1122                            Some(pos.clone()),
1123                        );
1124                    }
1125                }
1126                compiler_frame_mut!(compiler).registers = registers;
1127                Ok(None)
1128            }
1129            Statement::While { cond, body } => {
1130                let start_addr = compiler_frame_mut!(compiler).addr();
1131                let cond = cond.compile(compiler)?;
1132                let check_addr =
1133                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
1134                compiler_frame_mut!(compiler).push_scope();
1135                body.compile(compiler)?;
1136                let scope = compiler_frame_mut!(compiler)
1137                    .pop_scope()
1138                    .expect(COMPILER_SCOPE_EXPECT);
1139                let exit_addr = compiler_frame_mut!(compiler)
1140                    .write(ByteCode::Jump { addr: start_addr }, pos.clone());
1141                for addr in scope.breaks {
1142                    compiler_frame_mut!(compiler).overwrite(
1143                        addr,
1144                        ByteCode::Jump {
1145                            addr: exit_addr + 1,
1146                        },
1147                        None,
1148                    );
1149                }
1150                for addr in scope.continues {
1151                    compiler_frame_mut!(compiler).overwrite(
1152                        addr,
1153                        ByteCode::Jump { addr: start_addr },
1154                        None,
1155                    );
1156                }
1157                compiler_frame_mut!(compiler).overwrite(
1158                    check_addr,
1159                    ByteCode::JumpIf {
1160                        negative: true,
1161                        cond,
1162                        addr: exit_addr + 1,
1163                    },
1164                    Some(pos),
1165                );
1166                Ok(None)
1167            }
1168            Statement::WhileLet {
1169                param:
1170                    Located {
1171                        value: param,
1172                        pos: _,
1173                    },
1174                expr,
1175                body,
1176            } => {
1177                let start_addr = compiler_frame_mut!(compiler).addr();
1178                let cond = {
1179                    let src = expr.compile(compiler)?;
1180                    match param {
1181                        Parameter::Ident(ident) => {
1182                            let dst =
1183                                Location::Register(compiler_frame_mut!(compiler).new_local(ident));
1184                            compiler_frame_mut!(compiler)
1185                                .write(ByteCode::Move { dst, src }, pos.clone());
1186                        }
1187                        Parameter::Object(fields) => {
1188                            for Located { value: ident, pos } in fields.into_iter() {
1189                                let field = Source::Constant(
1190                                    compiler_frame_mut!(compiler)
1191                                        .new_const(Value::String(ident.clone())),
1192                                );
1193                                let dst = Location::Register(
1194                                    compiler_frame_mut!(compiler).new_local(ident),
1195                                );
1196                                compiler_frame_mut!(compiler).write(
1197                                    ByteCode::Field {
1198                                        dst,
1199                                        head: src,
1200                                        field,
1201                                    },
1202                                    pos,
1203                                );
1204                            }
1205                        }
1206                        Parameter::Vector(idents) => {
1207                            for (idx, Located { value: ident, pos }) in
1208                                idents.into_iter().enumerate()
1209                            {
1210                                let field = Source::Constant(
1211                                    compiler_frame_mut!(compiler)
1212                                        .new_const(Value::Int(idx as isize as i64)),
1213                                );
1214                                let dst = Location::Register(
1215                                    compiler_frame_mut!(compiler).new_local(ident),
1216                                );
1217                                compiler_frame_mut!(compiler).write(
1218                                    ByteCode::Field {
1219                                        dst,
1220                                        head: src,
1221                                        field,
1222                                    },
1223                                    pos,
1224                                );
1225                            }
1226                        }
1227                    }
1228                    src
1229                };
1230                let check_addr =
1231                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
1232                compiler_frame_mut!(compiler).push_scope();
1233                body.compile(compiler)?;
1234                let scope = compiler_frame_mut!(compiler)
1235                    .pop_scope()
1236                    .expect(COMPILER_SCOPE_EXPECT);
1237                let exit_addr = compiler_frame_mut!(compiler)
1238                    .write(ByteCode::Jump { addr: start_addr }, pos.clone());
1239                for addr in scope.breaks {
1240                    compiler_frame_mut!(compiler).overwrite(
1241                        addr,
1242                        ByteCode::Jump {
1243                            addr: exit_addr + 1,
1244                        },
1245                        None,
1246                    );
1247                }
1248                for addr in scope.continues {
1249                    compiler_frame_mut!(compiler).overwrite(
1250                        addr,
1251                        ByteCode::Jump { addr: start_addr },
1252                        None,
1253                    );
1254                }
1255                compiler_frame_mut!(compiler).overwrite(
1256                    check_addr,
1257                    ByteCode::JumpNull {
1258                        negative: false,
1259                        cond,
1260                        addr: exit_addr + 1,
1261                    },
1262                    Some(pos),
1263                );
1264                Ok(None)
1265            }
1266            Statement::For {
1267                ident:
1268                    Located {
1269                        value: ident,
1270                        pos: _,
1271                    },
1272                iter,
1273                body,
1274            } => {
1275                //          iter !iter = [iter]
1276                // start:   next !register = @iter
1277                //          jumpnull @register *exit
1278                //          [body]
1279                //          jump *start
1280                // exit:    ...
1281
1282                let iter = iter.compile(compiler)?;
1283                let register = compiler_frame_mut!(compiler).new_local(ident);
1284                let func = Source::Global(
1285                    compiler_frame_mut!(compiler).new_const(Value::String(FOR_FUNC.into())),
1286                );
1287                let start_addr = compiler_frame_mut!(compiler).write(
1288                    ByteCode::CallSingle {
1289                        dst: Some(Location::Register(register)),
1290                        func,
1291                        arg: iter,
1292                    },
1293                    pos.clone(),
1294                );
1295                let check_addr =
1296                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
1297                compiler_frame_mut!(compiler).push_scope();
1298                body.compile(compiler)?;
1299                let scope = compiler_frame_mut!(compiler)
1300                    .pop_scope()
1301                    .expect(COMPILER_SCOPE_EXPECT);
1302                let exit_addr = compiler_frame_mut!(compiler)
1303                    .write(ByteCode::Jump { addr: start_addr }, pos.clone());
1304                for addr in scope.breaks {
1305                    compiler_frame_mut!(compiler).overwrite(
1306                        addr,
1307                        ByteCode::Jump {
1308                            addr: exit_addr + 1,
1309                        },
1310                        None,
1311                    );
1312                }
1313                for addr in scope.continues {
1314                    compiler_frame_mut!(compiler).overwrite(
1315                        addr,
1316                        ByteCode::Jump { addr: start_addr },
1317                        None,
1318                    );
1319                }
1320                compiler_frame_mut!(compiler).overwrite(
1321                    check_addr,
1322                    ByteCode::JumpNull {
1323                        negative: false,
1324                        cond: Source::Register(register),
1325                        addr: exit_addr + 1,
1326                    },
1327                    Some(pos),
1328                );
1329                Ok(None)
1330            }
1331            Statement::Return(expr) => {
1332                if let Some(expr) = expr {
1333                    let src = expr.compile(compiler)?;
1334                    compiler_frame_mut!(compiler).write(ByteCode::Return { src: Some(src) }, pos);
1335                    Ok(Some(src))
1336                } else {
1337                    compiler_frame_mut!(compiler).write(ByteCode::Return { src: None }, pos);
1338                    Ok(Some(Source::Null))
1339                }
1340            }
1341            Statement::Break => {
1342                let addr = compiler_frame_mut!(compiler).write(ByteCode::None, pos);
1343                compiler_frame_mut!(compiler)
1344                    .scope_mut()
1345                    .expect(COMPILER_SCOPE_EXPECT)
1346                    .breaks
1347                    .insert(addr);
1348                Ok(None)
1349            }
1350            Statement::Continue => {
1351                let addr = compiler_frame_mut!(compiler).write(ByteCode::None, pos);
1352                compiler_frame_mut!(compiler)
1353                    .scope_mut()
1354                    .expect(COMPILER_SCOPE_EXPECT)
1355                    .continues
1356                    .insert(addr);
1357                Ok(None)
1358            }
1359        }
1360    }
1361}
1362impl Located<Pattern> {
1363    fn compile_match(
1364        self,
1365        compiler: &mut Compiler,
1366        expr: Source,
1367        dst: Location,
1368    ) -> Result<(), Located<Box<dyn Error>>> {
1369        let Located {
1370            value: pattern,
1371            pos,
1372        } = self;
1373        match pattern {
1374            Pattern::Ident(ident) => {
1375                let ident = compiler_frame_mut!(compiler).new_local(ident);
1376                compiler_frame_mut!(compiler).write(
1377                    ByteCode::Move {
1378                        dst: Location::Register(ident),
1379                        src: expr,
1380                    },
1381                    pos.clone(),
1382                );
1383                compiler_frame_mut!(compiler).write(
1384                    ByteCode::Move {
1385                        dst,
1386                        src: Source::Bool(true),
1387                    },
1388                    pos,
1389                );
1390            }
1391            Pattern::Atom(atom) => {
1392                let atom = Located::new(atom, pos.clone()).compile(compiler)?;
1393                compiler_frame_mut!(compiler).write(
1394                    ByteCode::Binary {
1395                        op: BinaryOperation::EQ,
1396                        dst,
1397                        left: expr,
1398                        right: atom,
1399                    },
1400                    pos,
1401                );
1402            }
1403            Pattern::Guard { pattern, cond } => {
1404                pattern.compile_match(compiler, expr, dst)?;
1405                let cond = cond.compile(compiler)?;
1406                compiler_frame_mut!(compiler).write(
1407                    ByteCode::Binary {
1408                        op: BinaryOperation::And,
1409                        dst,
1410                        left: dst.into(),
1411                        right: cond,
1412                    },
1413                    pos,
1414                );
1415            }
1416        }
1417        Ok(())
1418    }
1419}
1420impl Compilable for Located<Expression> {
1421    type Output = Source;
1422    fn compile(self, compiler: &mut Compiler) -> Result<Self::Output, Located<Box<dyn Error>>> {
1423        let Located { value: expr, pos } = self;
1424        match expr {
1425            Expression::Atom(atom) => Located::new(atom, pos).compile(compiler),
1426            Expression::Binary { op, left, right } => {
1427                let left = left.compile(compiler)?;
1428                let right = right.compile(compiler)?;
1429                let register = compiler_frame_mut!(compiler).new_register();
1430                let dst = Location::Register(register);
1431                compiler_frame_mut!(compiler).write(
1432                    ByteCode::Binary {
1433                        op: op.into(),
1434                        dst,
1435                        left,
1436                        right,
1437                    },
1438                    pos,
1439                );
1440                Ok(dst.into())
1441            }
1442            Expression::Unary { op, right } => {
1443                let right = right.compile(compiler)?;
1444                let register = compiler_frame_mut!(compiler).new_register();
1445                let dst = Location::Register(register);
1446                compiler_frame_mut!(compiler).write(
1447                    ByteCode::Unary {
1448                        op: op.into(),
1449                        dst,
1450                        src: right,
1451                    },
1452                    pos,
1453                );
1454                Ok(dst.into())
1455            }
1456            Expression::Call { head, mut args } => {
1457                let head = head.compile(compiler)?;
1458                let amount = args.len() as u8;
1459                match amount {
1460                    0 => {
1461                        let dst = compiler_frame_mut!(compiler).new_register();
1462                        compiler_frame_mut!(compiler).write(
1463                            ByteCode::CallZero {
1464                                dst: Some(Location::Register(dst)),
1465                                func: head.into(),
1466                            },
1467                            pos,
1468                        );
1469                        Ok(Source::Register(dst))
1470                    }
1471                    1 => {
1472                        let arg = args.remove(0).compile(compiler)?;
1473                        let dst = compiler_frame_mut!(compiler).new_register();
1474                        compiler_frame_mut!(compiler).write(
1475                            ByteCode::CallSingle {
1476                                dst: Some(Location::Register(dst)),
1477                                func: head.into(),
1478                                arg,
1479                            },
1480                            pos,
1481                        );
1482                        Ok(Source::Register(dst))
1483                    }
1484                    amount => {
1485                        let offset = compiler_frame_mut!(compiler).registers;
1486                        compiler_frame_mut!(compiler).add_registers(amount as Register);
1487                        for (register, arg) in
1488                            (offset..offset + amount as Register).zip(args.into_iter())
1489                        {
1490                            let pos = arg.pos.clone();
1491                            let src = arg.compile(compiler)?;
1492                            compiler_frame_mut!(compiler).write(
1493                                ByteCode::Move {
1494                                    dst: Location::Register(register),
1495                                    src,
1496                                },
1497                                pos,
1498                            );
1499                        }
1500                        compiler_frame_mut!(compiler).registers = offset;
1501                        let dst = compiler_frame_mut!(compiler).new_register();
1502                        compiler_frame_mut!(compiler).write(
1503                            ByteCode::Call {
1504                                dst: Some(Location::Register(dst)),
1505                                func: head,
1506                                offset,
1507                                amount,
1508                            },
1509                            pos,
1510                        );
1511                        Ok(Source::Register(dst))
1512                    }
1513                }
1514            }
1515            Expression::SelfCall {
1516                head,
1517                field:
1518                    Located {
1519                        value: field,
1520                        pos: field_pos,
1521                    },
1522                args,
1523            } => {
1524                let head_pos = head.pos.clone();
1525                let head = head.compile(compiler)?;
1526                let func = {
1527                    let dst = compiler_frame_mut!(compiler).new_register();
1528                    let field_addr = compiler_frame_mut!(compiler).new_const(Value::String(field));
1529                    compiler_frame_mut!(compiler).write(
1530                        ByteCode::Field {
1531                            dst: Location::Register(dst),
1532                            head,
1533                            field: Source::Constant(field_addr),
1534                        },
1535                        field_pos,
1536                    );
1537                    Source::Register(dst)
1538                };
1539                let amount = args.len() as u8 + 1;
1540                match amount {
1541                    1 => {
1542                        let offset = compiler_frame_mut!(compiler).registers;
1543                        let arg = head.into();
1544                        compiler_frame_mut!(compiler).registers = offset;
1545                        let dst = compiler_frame_mut!(compiler).new_register();
1546                        compiler_frame_mut!(compiler).write(
1547                            ByteCode::CallSingle {
1548                                dst: Some(Location::Register(dst)),
1549                                func,
1550                                arg,
1551                            },
1552                            pos,
1553                        );
1554                        Ok(Source::Register(dst))
1555                    }
1556                    amount => {
1557                        let offset = compiler_frame_mut!(compiler).registers;
1558                        let head_register = compiler_frame_mut!(compiler).new_register();
1559                        compiler_frame_mut!(compiler).write(
1560                            ByteCode::Move {
1561                                dst: Location::Register(head_register),
1562                                src: head,
1563                            },
1564                            head_pos,
1565                        );
1566                        compiler_frame_mut!(compiler).add_registers(amount as Register);
1567                        for (register, arg) in
1568                            (offset + 1..offset + amount as Register).zip(args.into_iter())
1569                        {
1570                            let pos = arg.pos.clone();
1571                            let src = arg.compile(compiler)?;
1572                            compiler_frame_mut!(compiler).write(
1573                                ByteCode::Move {
1574                                    dst: Location::Register(register),
1575                                    src,
1576                                },
1577                                pos,
1578                            );
1579                        }
1580                        compiler_frame_mut!(compiler).registers = offset;
1581                        let dst = compiler_frame_mut!(compiler).new_register();
1582                        compiler_frame_mut!(compiler).write(
1583                            ByteCode::Call {
1584                                dst: Some(Location::Register(dst)),
1585                                func,
1586                                offset,
1587                                amount,
1588                            },
1589                            pos,
1590                        );
1591                        Ok(Source::Register(dst))
1592                    }
1593                }
1594            }
1595            Expression::Field {
1596                head,
1597                field:
1598                    Located {
1599                        value: field,
1600                        pos: _,
1601                    },
1602            } => {
1603                let head = head.compile(compiler)?;
1604                let field =
1605                    Source::Constant(compiler_frame_mut!(compiler).new_const(Value::String(field)));
1606                let dst = compiler_frame_mut!(compiler).new_register();
1607                compiler_frame_mut!(compiler).write(
1608                    ByteCode::Field {
1609                        dst: Location::Register(dst),
1610                        head,
1611                        field,
1612                    },
1613                    pos,
1614                );
1615                Ok(Source::Register(dst))
1616            }
1617            Expression::Index { head, index } => {
1618                let head = head.compile(compiler)?;
1619                let field = index.compile(compiler)?;
1620                let dst = compiler_frame_mut!(compiler).new_register();
1621                compiler_frame_mut!(compiler).write(
1622                    ByteCode::Field {
1623                        dst: Location::Register(dst),
1624                        head,
1625                        field,
1626                    },
1627                    pos,
1628                );
1629                Ok(Source::Register(dst))
1630            }
1631        }
1632    }
1633}
1634impl Compilable for Located<Atom> {
1635    type Output = Source;
1636    fn compile(self, compiler: &mut Compiler) -> Result<Self::Output, Located<Box<dyn Error>>> {
1637        let Located { value: atom, pos } = self;
1638        match atom {
1639            Atom::Path(path) => Ok(Located::new(path, pos).compile(compiler)?.into()),
1640            Atom::Null => Ok(Source::Null),
1641            Atom::Int(v) => Ok(Source::Constant(
1642                compiler_frame_mut!(compiler).new_const(Value::Int(v)),
1643            )),
1644            Atom::Float(v) => Ok(Source::Constant(
1645                compiler_frame_mut!(compiler).new_const(Value::Float(v)),
1646            )),
1647            Atom::Bool(v) => Ok(Source::Bool(v)),
1648            Atom::Char(v) => Ok(Source::Char(v)),
1649            Atom::String(v) => Ok(Source::Constant(
1650                compiler_frame_mut!(compiler).new_const(Value::String(v)),
1651            )),
1652            Atom::Expression(expr) => expr.compile(compiler),
1653            Atom::Vector(exprs) => {
1654                let amount = exprs.len() as VectorSize;
1655                let register = compiler_frame_mut!(compiler).new_register();
1656                let dst = Location::Register(register);
1657                let start = compiler_frame_mut!(compiler).registers;
1658                let registers = (1..=amount)
1659                    .map(|_| compiler_frame_mut!(compiler).new_register())
1660                    .collect::<Vec<Register>>();
1661                for (expr, register) in exprs.into_iter().zip(registers.into_iter()) {
1662                    let expr_pos = expr.pos.clone();
1663                    let src = expr.compile(compiler)?;
1664                    compiler_frame_mut!(compiler).write(
1665                        ByteCode::Move {
1666                            dst: Location::Register(register),
1667                            src,
1668                        },
1669                        expr_pos,
1670                    );
1671                }
1672                compiler_frame_mut!(compiler).registers = start;
1673                compiler_frame_mut!(compiler).write(ByteCode::Vector { dst, start, amount }, pos);
1674                Ok(dst.into())
1675            }
1676            Atom::Object(entries) => {
1677                let amount = entries.len() as ObjectSize;
1678                let register = compiler_frame_mut!(compiler).new_register();
1679                let dst = Location::Register(register);
1680                let start = compiler_frame_mut!(compiler).registers;
1681                let registers = (1..amount * 2 + 1)
1682                    .map(|_| compiler_frame_mut!(compiler).new_register())
1683                    .collect::<Vec<Register>>();
1684                for (
1685                    (
1686                        Located {
1687                            value: key,
1688                            pos: key_pos,
1689                        },
1690                        expr,
1691                    ),
1692                    register,
1693                ) in entries.into_iter().zip(registers.into_iter().step_by(2))
1694                {
1695                    let addr = compiler_frame_mut!(compiler).new_const(Value::String(key));
1696                    let expr_pos = expr.pos.clone();
1697                    let src = expr.compile(compiler)?;
1698                    compiler_frame_mut!(compiler).write(
1699                        ByteCode::Move {
1700                            dst: Location::Register(register),
1701                            src: Source::Constant(addr),
1702                        },
1703                        key_pos,
1704                    );
1705                    compiler_frame_mut!(compiler).write(
1706                        ByteCode::Move {
1707                            dst: Location::Register(register + 1),
1708                            src,
1709                        },
1710                        expr_pos,
1711                    );
1712                }
1713                compiler_frame_mut!(compiler).registers = start;
1714                compiler_frame_mut!(compiler).write(ByteCode::Object { dst, start, amount }, pos);
1715                Ok(dst.into())
1716            }
1717            Atom::If {
1718                cond,
1719                case,
1720                else_case,
1721            } => {
1722                let cond = cond.compile(compiler)?;
1723                let register = compiler_frame_mut!(compiler).new_register();
1724                let check_addr =
1725                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
1726
1727                let case = case.compile(compiler)?;
1728                compiler_frame_mut!(compiler).write(
1729                    ByteCode::Move {
1730                        dst: Location::Register(register),
1731                        src: case,
1732                    },
1733                    pos.clone(),
1734                );
1735                let else_addr =
1736                    compiler_frame_mut!(compiler).write(ByteCode::default(), Position::default());
1737                let else_case = else_case.compile(compiler)?;
1738                compiler_frame_mut!(compiler).write(
1739                    ByteCode::Move {
1740                        dst: Location::Register(register),
1741                        src: else_case,
1742                    },
1743                    pos.clone(),
1744                );
1745                let exit_addr = compiler_frame_mut!(compiler).addr();
1746                compiler_frame_mut!(compiler).overwrite(
1747                    check_addr,
1748                    ByteCode::JumpIf {
1749                        negative: true,
1750                        cond,
1751                        addr: else_addr + 1,
1752                    },
1753                    Some(pos.clone()),
1754                );
1755                compiler_frame_mut!(compiler).overwrite(
1756                    else_addr,
1757                    ByteCode::Jump { addr: exit_addr },
1758                    Some(pos),
1759                );
1760                Ok(Source::Register(register))
1761            }
1762            Atom::Fn {
1763                params,
1764                var_args: _,
1765                body,
1766            } => {
1767                compiler.push_frame(CompilerFrame {
1768                    closure: Rc::new(RefCell::new(Closure::default())),
1769                    scopes: vec![Scope::default()],
1770                    registers: 0,
1771                });
1772                for Located {
1773                    value: param,
1774                    pos: _,
1775                } in params
1776                {
1777                    match param {
1778                        Parameter::Ident(ident) => {
1779                            compiler_frame_mut!(compiler).new_local(ident);
1780                        }
1781                        Parameter::Object(fields) => {
1782                            let head =
1783                                Source::Register(compiler_frame_mut!(compiler).new_register());
1784                            for Located { value: ident, pos } in fields.into_iter() {
1785                                let field = Source::Constant(
1786                                    compiler_frame_mut!(compiler)
1787                                        .new_const(Value::String(ident.clone())),
1788                                );
1789                                let dst = Location::Register(
1790                                    compiler_frame_mut!(compiler).new_local(ident),
1791                                );
1792                                compiler_frame_mut!(compiler)
1793                                    .write(ByteCode::Field { dst, head, field }, pos);
1794                            }
1795                        }
1796                        Parameter::Vector(idents) => {
1797                            let head =
1798                                Source::Register(compiler_frame_mut!(compiler).new_register());
1799                            for (idx, Located { value: ident, pos }) in
1800                                idents.into_iter().enumerate()
1801                            {
1802                                let field = Source::Constant(
1803                                    compiler_frame_mut!(compiler)
1804                                        .new_const(Value::Int(idx as isize as i64)),
1805                                );
1806                                let dst = Location::Register(
1807                                    compiler_frame_mut!(compiler).new_local(ident),
1808                                );
1809                                compiler_frame_mut!(compiler)
1810                                    .write(ByteCode::Field { dst, head, field }, pos);
1811                            }
1812                        }
1813                    }
1814                }
1815                body.compile(compiler)?;
1816                compiler_frame_mut!(compiler).write(ByteCode::Return { src: None }, pos.clone());
1817                let closure = compiler
1818                    .pop_frame()
1819                    .expect("no compiler frame on stack")
1820                    .closure;
1821                let addr = compiler_frame_mut!(compiler).new_closure(closure);
1822                let register = compiler_frame_mut!(compiler).new_register();
1823                compiler_frame_mut!(compiler).write(
1824                    ByteCode::Function {
1825                        dst: Location::Register(register),
1826                        addr,
1827                    },
1828                    pos,
1829                );
1830                Ok(Source::Register(register))
1831            }
1832        }
1833    }
1834}
1835impl Compilable for Located<Path> {
1836    type Output = Location;
1837    fn compile(self, compiler: &mut Compiler) -> Result<Self::Output, Located<Box<dyn Error>>> {
1838        let Located { value: atom, pos } = self;
1839        match atom {
1840            Path::Ident(ident) => {
1841                if let Some(location) = compiler.get_variable_location(&ident) {
1842                    Ok(location)
1843                } else {
1844                    let addr = compiler_frame_mut!(compiler).new_const(Value::String(ident));
1845                    Ok(Location::Global(addr))
1846                }
1847            }
1848            Path::Field {
1849                head,
1850                field:
1851                    Located {
1852                        value: field,
1853                        pos: _,
1854                    },
1855            } => {
1856                let head = head.compile(compiler)?;
1857                let field =
1858                    Source::Constant(compiler_frame_mut!(compiler).new_const(Value::String(field)));
1859                let dst = compiler_frame_mut!(compiler).new_register();
1860                compiler_frame_mut!(compiler).write(
1861                    ByteCode::Field {
1862                        dst: Location::Register(dst),
1863                        head: head.into(),
1864                        field,
1865                    },
1866                    pos,
1867                );
1868                Ok(Location::Register(dst))
1869            }
1870            Path::Index { head, index } => {
1871                let head = head.compile(compiler)?;
1872                let field = index.compile(compiler)?;
1873                let dst = compiler_frame_mut!(compiler).new_register();
1874                compiler_frame_mut!(compiler).write(
1875                    ByteCode::Field {
1876                        dst: Location::Register(dst),
1877                        head: head.into(),
1878                        field,
1879                    },
1880                    pos,
1881                );
1882                Ok(Location::Register(dst))
1883            }
1884        }
1885    }
1886}