~starkingdoms/starkingdoms

ref: cd7053cdc98554b3e38dba6927a0e00d411b49ad starkingdoms/kabel/src/codegen.rs -rw-r--r-- 3.4 KiB
cd7053cd — ghostly_zsh codegen and also functioning strings 1 year, 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::{opcodes::OpCode, parser::{BinOp, Lit, AST}, vm::{Value, VM}};

pub struct Codegen {
    pub vm: VM
}

impl Codegen {
    pub fn new(text: String) -> Self {
        Codegen {
            vm: VM::new(Vec::new(), Vec::new(),
                Vec::new(), text.lines().map(|s| s.to_string()).collect()),
        }
    }
    pub fn visit(&mut self, ast: AST) {
        use crate::parser::ASTType::*;
        match ast.ast_type {
            Program(asts) => {
                for ast in asts {
                    self.visit(ast);
                }
            }
            // REMOVE LATER
            Print(ref expr) => {
                self.visit_print(&ast, *expr.clone());
            }
            Binary(left, oper, right) => {
                self.visit_binary(*left, oper, *right);
            }
            Lit(ref lit) => {
                self.visit_lit(&ast, lit.clone());
            }
            _ => {}
        }
    }
    // REMOVE LATER
    pub fn visit_print(&mut self, ast: &AST, expr: AST) {
        self.visit(expr);
        self.vm.chunk.push(OpCode::PRINT.into());
        if self.vm.lines.last().unwrap().0 != ast.end_line {
            self.vm.lines.push((ast.end_line, 1));
        } else {
            self.vm.lines.last_mut().unwrap().1 += 1;
        }
    }
    pub fn visit_binary(&mut self, left: AST, oper: BinOp, right: AST) {
        use crate::parser::BinOp::*;
        match oper {
            Add => {
                self.visit(right);
                self.visit(left);
                self.vm.chunk.push(OpCode::ADD.into());
                self.vm.lines.last_mut().unwrap().1 += 1;
            }
            Sub => {
                self.visit(right);
                self.visit(left);
                self.vm.chunk.push(OpCode::SUB.into());
                self.vm.lines.last_mut().unwrap().1 += 1;
            }
            _ => { panic!("not implemented") }
        }
    }
    pub fn visit_lit(&mut self, ast: &AST, lit: Lit) {
        match lit {
            Lit::Num(value) => {
                self.vm.pool.push(Value::Num(value));
                self.vm.chunk.push(OpCode::CONSTANT.into());
                self.vm.chunk.push((self.vm.pool.len()-1) as u8);
                if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line {
                    self.vm.lines.push((ast.end_line, 2));
                } else {
                    self.vm.lines.last_mut().unwrap().1 += 2;
                }
            }
            Lit::Str(value) => {
                self.vm.pool.push(Value::Str(value.into()));
                self.vm.chunk.push(OpCode::CONSTANT.into());
                self.vm.chunk.push((self.vm.pool.len()-1) as u8);
                if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line {
                    self.vm.lines.push((ast.end_line, 2));
                } else {
                    self.vm.lines.last_mut().unwrap().1 += 2;
                }
            }
            Lit::Bool(value) => {
                self.vm.pool.push(Value::Bool(value));
                self.vm.chunk.push(OpCode::CONSTANT.into());
                self.vm.chunk.push((self.vm.pool.len()-1) as u8);
                if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line {
                    self.vm.lines.push((ast.end_line, 2));
                } else {
                    self.vm.lines.last_mut().unwrap().1 += 2;
                }
            }
            _ => {}
        }
    }
}