phoenix_lang/
compiler.rs

1use std::collections::HashMap;
2use std::env;
3use std::fs::File;
4use std::io::Read;
5use std::process::exit;
6
7use serde::{Deserialize, Serialize};
8
9use crate::chunk::CompilerModuleChunk;
10use crate::chunk::OpCode::*;
11use crate::chunk::{Chunk, ClassChunk, FunctionChunk, FunctionType, Instr, ModuleChunk, OpCode};
12use crate::debug::{disassemble_class_chunk, disassemble_fn_chunk};
13use crate::native::native_functions::NATIVE_FUNCTIONS;
14use crate::precedence::{get_rule, ParseFn, Precedence};
15
16use crate::scanner::{Scanner, Token, TokenType};
17use crate::value::Value;
18use crate::VERSION;
19
20const DEFAULT_FILE_NAME: &str = "script";
21const MAX_MODULES: usize = 255;
22const MAX_JUMP: usize = 65535;
23
24#[derive(Debug)]
25pub struct Compiler {
26    /// The modules that are imported (and the main module)
27    modules: Vec<CompilerModuleChunk>,
28    /// The name of the module and the index in the modules vector
29    module_table: HashMap<String, usize>,
30    /// Which ModuleChunkScanner should the the compiler return to after. Acts as a stack
31    parent_modules: Vec<usize>,
32    // we are always in a module, because the code in the main file is in a module (index 0)
33    current_module: usize,
34    // normally equal to the current_module, but this says from which module we are currently compiling
35    current_module_code: usize,
36
37    had_error: bool,
38    panic_mode: bool,
39    quiet_mode: bool,
40    debug_mode: bool,
41    /// Means that before each line is executed, the VM will wait for user input
42    wait_mode: bool,
43}
44
45impl Compiler {
46    fn current_chunk(&mut self) -> &mut Chunk {
47        let index = self.current_module().current_function;
48        &mut self
49            .current_module()
50            .functions
51            .get_mut(index)
52            .unwrap()
53            .chunk
54    }
55
56    fn current_chunk_code(&mut self) -> &mut Chunk {
57        let index = self.current_code_module().current_function;
58        &mut self
59            .current_code_module()
60            .functions
61            .get_mut(index)
62            .unwrap()
63            .chunk
64    }
65
66    fn current_chunk_ref(&self) -> &Chunk {
67        &self
68            .current_module_ref()
69            .functions
70            .get(self.current_module_ref().current_function)
71            .unwrap()
72            .chunk
73    }
74
75    fn current_fn(&mut self) -> &mut FunctionChunk {
76        let index = self.current_module_ref().current_function;
77        self.current_module().functions.get_mut(index).unwrap()
78    }
79
80    fn current_fn_type(&self) -> FunctionType {
81        self.current_module_ref()
82            .functions
83            .get(self.current_module_ref().current_function)
84            .unwrap()
85            .fn_type
86    }
87
88    /// Panics if not in a class. Only call this if you're sure you're in a class def!
89    fn current_class(&mut self) -> &mut ClassChunk {
90        let index = self.current_module().current_class.unwrap();
91        self.current_module().classes.get_mut(index).unwrap()
92    }
93
94    pub fn current_module(&mut self) -> &mut CompilerModuleChunk {
95        self.modules.get_mut(self.current_module).unwrap()
96    }
97
98    pub fn current_code_module(&mut self) -> &mut CompilerModuleChunk {
99        self.modules.get_mut(self.current_module_code).unwrap()
100    }
101
102    // uses the current_module_code
103    pub fn set_current_module(&mut self, m: CompilerModuleChunk) {
104        self.modules[self.current_module_code] = m;
105    }
106
107    fn current_module_ref(&self) -> &CompilerModuleChunk {
108        self.modules.get(self.current_module).unwrap()
109    }
110
111    fn current_code_module_ref(&self) -> &CompilerModuleChunk {
112        self.modules.get(self.current_module_code).unwrap()
113    }
114
115    fn advance(&mut self) {
116        // heck, but idk another way, cause i cant have 2 mutable borrows
117        let mut m = self.current_code_module().clone();
118        let mut m2 = self.current_code_module().clone();
119        m2.tokens.push(m.scanner.scan_token()); // Fixme: Wastes memory by not just dropping the older tokens, make advance() drop older tokens after i finish the code?
120        self.set_current_module(m);
121        self.current_code_module().tokens = m2.tokens;
122        if self.current().token_type == TokenType::Error {
123            self.error(self.current().lexeme.clone().as_str());
124            self.advance();
125        }
126    }
127
128    fn previous(&self) -> &Token {
129        &self.current_code_module_ref().tokens[self.current_code_module_ref().tokens.len() - 2]
130    }
131
132    fn current(&self) -> &Token {
133        &self.current_code_module_ref().tokens[self.current_code_module_ref().tokens.len() - 1]
134    }
135
136    // also adds the opWait code if the token_type is a semicolon
137    fn consume(&mut self, token_type: TokenType, msg: &str) {
138        self.advance();
139        if self.previous().token_type == TokenType::Semicolon {
140            if self.wait_mode {
141                let file = self.current_module().scanner.file.clone();
142                let line = self.current_module().scanner.cur_line;
143                let s = format!(
144                    "{}:{}: {}",
145                    file, line,
146                    self.current_module()
147                        .scanner
148                        .code
149                        .split("\n")
150                        .collect::<Vec<&str>>()
151                        .iter()
152                        .nth(line - 1)
153                        .unwrap()
154                );
155                self.emit_constant(Value::PhoenixString(s));
156                self.emit_instr(OpCreateString);
157                self.emit_instr(OpWait);
158            }
159        }
160        if !(self.previous().token_type == token_type) {
161            self.error(msg);
162        }
163    }
164
165    fn match_cur(&mut self, token_type: TokenType) -> bool {
166        if !self.check(token_type) {
167            false
168        } else {
169            self.advance();
170            true
171        }
172    }
173
174    fn check(&self, token_type: TokenType) -> bool {
175        self.current().token_type == token_type
176    }
177
178    fn error(&mut self, message: &str) {
179        if self.panic_mode {
180            return;
181        } // Ignore other errors while in panic_mode
182
183        self.had_error = true;
184        self.panic_mode = true;
185
186        if self.quiet_mode {
187            return;
188        }
189
190        let token = self.previous();
191        eprint!(
192            "[{}:{}] Error",
193            self.current_module_ref().scanner.file.clone(),
194            token.line_num + 1
195        );
196        match token.token_type {
197            TokenType::EOF => eprint!(" at end of file"),
198            TokenType::Error => (), // nothing
199            _ => eprint!(" at '{}'", token.lexeme),
200        }
201
202        eprintln!(": {}", message);
203    }
204
205    fn synchronize(&mut self) {
206        self.panic_mode = false;
207
208        while !self.check(TokenType::EOF) {
209            if self.previous().token_type == TokenType::Semicolon {
210                return;
211            }
212            match self.current().token_type {
213                TokenType::Class
214                | TokenType::Fun
215                | TokenType::Var
216                | TokenType::For
217                | TokenType::If
218                | TokenType::While
219                | TokenType::Print
220                | TokenType::Return => return,
221                _ => (),
222            }
223            self.advance();
224        }
225    }
226
227    fn emit_instr(&mut self, op_code: OpCode) {
228        // println!("Emitting instr {:?} from token {:?}", op_code, self.previous()); kinda useful
229        let instr = Instr {
230            op_code,
231            line_num: self.previous().line_num,
232        };
233        self.current_chunk_code().write_instruction(instr)
234    }
235
236    fn emit_instrs(&mut self, op_codes: &[OpCode]) {
237        for oc in op_codes {
238            self.emit_instr(*oc)
239        }
240    }
241
242    fn emit_constant(&mut self, value: Value) -> usize {
243        let index = self.add_constant(value);
244        self.emit_instr(OpConstant(index));
245        index
246    }
247
248    fn add_constant(&mut self, value: Value) -> usize {
249        match self
250            .current_module()
251            .constants
252            .iter()
253            .position(|x| x == &value)
254        {
255            Some(i) => i,
256            None => {
257                self.current_module().constants.push(value);
258                self.current_module().constants.len() - 1
259            }
260        }
261    }
262
263    fn emit_return(&mut self) {
264        if self.current_fn_type() == FunctionType::Initializer {
265            self.emit_instrs(&[OpGetLocal(0), OpReturn]);
266        } else {
267            self.emit_instrs(&[OpNil, OpReturn]);
268        }
269    }
270
271    /// Emits OpCode::OpJump
272    ///
273    /// Returns the index of the jump instruction for patching
274    fn emit_jump(&mut self) -> usize {
275        self.emit_instr(OpJump(usize::MAX));
276        self.current_chunk().code.len() - 1
277    }
278
279    /// Emits OpCode::OpJumpIfFalse
280    ///
281    /// Returns the index of the jump instruction for patching
282    fn emit_jif(&mut self) -> usize {
283        self.emit_instr(OpJumpIfFalse(usize::MAX));
284        self.current_chunk().code.len() - 1
285    }
286
287    /// Given the index of the jump instruction in the chunk, update the opcode to jump to the instruction after the current one
288    fn patch_jump(&mut self, index: usize) {
289        let jump_amount = self.current_chunk().code.len() - index;
290        if jump_amount > MAX_JUMP {
291            self.error("Too much code to jump over");
292        }
293
294        let jump_instr = self.current_chunk().code.get_mut(index).unwrap();
295        macro_rules! replace_jump {
296            ($jump_type: path) => {{
297                jump_instr.op_code = $jump_type(jump_amount)
298            }};
299        }
300
301        match jump_instr.op_code {
302            OpJump(_) => replace_jump!(OpCode::OpJump),
303            OpJumpIfFalse(_) => replace_jump!(OpCode::OpJumpIfFalse),
304            _ => panic!(
305                "Compiler panic: Attempted to patch a non_jump op code instruction: {:?}",
306                jump_instr
307            ),
308        }
309    }
310
311    /// loop_start: Index of the instruction to jump back to
312    fn emit_loop(&mut self, loop_start: usize) {
313        let offset = self.current_chunk().code.len() - loop_start;
314        let loop_op = OpLoop(offset);
315
316        if offset > (u16::MAX as usize) {
317            self.error("Loop body too large");
318        }
319
320        self.emit_instr(loop_op);
321    }
322
323    /// Emits an OpReturn
324    fn end_compilation(&mut self) {
325        self.emit_return();
326    }
327
328    /// End scope by emitting pop instructions and cleaning the resolver
329    fn end_scope(&mut self) {
330        for _ in 0..self.current_module().resolver.end_scope() {
331            self.emit_instr(OpPop); // Remove old local variables
332        }
333    }
334
335    /// Calls Resolver::declare_variable() with the previous Token's lexeme (TokenIdentifier)
336    fn declare_variable(&mut self) {
337        let str_val = self.previous().lexeme.clone();
338        let success = self.current_module().resolver.declare_variable(str_val);
339        if !success {
340            self.error("Variable with this name already declared in this scope");
341        }
342    }
343
344    fn parse_precedence(&mut self, prec: Precedence) {
345        self.advance();
346
347        // Parse the start of the prefix expression
348        // We know this must be a prefix because we can't start with something that is an infix (eg + 3 2)
349        let prefix_rule = (get_rule(self.previous().token_type)).prefix;
350        // Used only by variable() to determine if a TokenIdentifier is for an assignment or get
351        let can_assign = prec <= Precedence::Assignment;
352        self.call_parse_fn(prefix_rule, can_assign);
353
354        // Parse any number of infix expressions, as long as they have higher precedence
355        while prec <= get_rule(self.current().token_type).precedence {
356            self.advance();
357            let infix_rule = (get_rule(self.previous().token_type)).infix;
358            self.call_parse_fn(infix_rule, can_assign);
359        }
360
361        // Show compilation error for a TokenEqual found in an infix position
362        if can_assign && self.previous().token_type == TokenType::Equal {
363            self.error("Invalid assignment target");
364        }
365    }
366
367    fn call_parse_fn(&mut self, parse_fn: ParseFn, can_assign: bool) {
368        match parse_fn {
369            ParseFn::None => self.error("Expected expression"),
370            ParseFn::Binary => self.binary(),
371            ParseFn::Grouping => self.grouping(),
372            ParseFn::Unary => self.unary(),
373            ParseFn::Number => self.number(),
374            ParseFn::Literal => self.literal(),
375            ParseFn::String => self.string(),
376            ParseFn::List => self.list(can_assign),
377            ParseFn::HashMap => self.hashmap(can_assign),
378            ParseFn::Variable => self.variable(can_assign),
379            ParseFn::And => self.and_operator(),
380            ParseFn::Or => self.or_operator(),
381            ParseFn::Call => self.call(),
382            ParseFn::Dot => self.dot(can_assign),
383            ParseFn::This => self.this(),
384            ParseFn::Super => self.super_(),
385            ParseFn::Increment => { /* gets handled by named_variable() */ }
386        }
387    }
388
389    fn declaration(&mut self) {
390        if self.match_cur(TokenType::Fun) {
391            self.fun_declaration();
392        } else if self.match_cur(TokenType::Class) {
393            self.class_declaration();
394        } else if self.match_cur(TokenType::Var) {
395            self.var_declaration();
396        } else {
397            self.statement();
398        }
399        if self.panic_mode {
400            self.synchronize();
401        }
402    }
403
404    fn fun_declaration(&mut self) {
405        let global = self.parse_variable("Expected function name");
406        self.current_module().resolver.mark_initialized(); // Initialize the function object if we are in a local scope
407        self.function(FunctionType::Function);
408        self.define_variable(global); // Emit the define instr if we are in the global scope
409    }
410
411    fn class_declaration(&mut self) {
412        self.consume(
413            TokenType::Identifier,
414            "Expected class name after keyword 'class'",
415        );
416        let name = self.previous().lexeme.clone();
417        let name_index = self.identifier_constant(&name);
418        self.declare_variable();
419
420        let class = ClassChunk::new(name);
421        let old_class = self.current_module().current_class;
422        self.current_module().classes.push(class);
423
424        let class_index = self.current_module().classes.len() - 1;
425        self.current_module().current_class = Some(class_index);
426
427        self.emit_instr(OpClass(class_index));
428        self.define_variable(name_index);
429
430        // Check for superclass
431        if self.match_cur(TokenType::Less) {
432            self.consume(TokenType::Identifier, "Expected superclass name");
433            // Resolve the superclass methods entirely at compile time instead of runtime because it fits how everything else works
434            // However because the compiler is single pass, you can only inherit a class that has already been defined
435            // Note: we know that all the methods the superclass will ever own must already be defined, since it will have had the same superclass resolution at compile time < Phoenix classes are closed
436            // Note: I like this bit of code, it is a really nice shiny implementation of superclasses that doesnt require any new opcodes and does not require any copying of the FunctionChunks. Fucking sick
437            let superclass_name = &self.previous().lexeme.clone();
438            let mut superclass_index: Option<usize> = None;
439            for (i, class_def) in self.current_module().classes.iter().enumerate() {
440                if class_def.name.eq(superclass_name) {
441                    superclass_index = Some(i);
442                }
443            }
444
445            if superclass_index == self.current_module().current_class {
446                self.error("A class cannot inherit from itself");
447            }
448
449            match superclass_index {
450                Some(i) => {
451                    let superclass = &self.current_module().classes[i];
452                    for (name_index, fn_index) in superclass.methods.clone().iter() {
453                        self.current_class().methods.insert(*name_index, *fn_index);
454                        // Inherit all the methods by just copying in all the fn_indices, nicely handles multiple levels of inheritance
455                        let name = self.current_module().identifier_constants[*name_index].clone();
456                        if name.as_str().eq("init") {
457                            self.current_class().has_init = true;
458                        }
459                    }
460                    self.current_class().superclass = superclass_index;
461                }
462                None => {
463                    self.error(format!("'{}' is not a valid superclass", superclass_name).as_str())
464                }
465            }
466        }
467
468        self.consume(TokenType::LeftBrace, "Expected '{' before class body");
469        while !self.check(TokenType::RightBrace) && !self.check(TokenType::EOF) {
470            self.method();
471        }
472        self.consume(TokenType::RightBrace, "Expected '}' after class body");
473
474        self.current_module().current_class = old_class;
475    }
476
477    // Note: Since this constantly confuses me, I'm gonna keep a note here so that I don't forget how variables work in Phoenix
478    // Globals: The opcodes GetGlobal and SetGlobal take a PhoenixString from the constants vec and map it into a HashMap in the VM, no resolving/checking is done before runtime
479    // Locals: Local variables live on the stack and since they are the ONLY values that do not get popped after statements, we know that they must live at the very bottom of the stack,
480    // and thus we can just raw index from the bottom of the stack to the index of the variable by looking at how many locals have been defined in this scope
481    fn var_declaration(&mut self) {
482        let global = self.parse_variable("Expected variable name");
483        if self.match_cur(TokenType::Equal) {
484            self.expression();
485        } else {
486            self.emit_instr(OpNil);
487        }
488        self.consume(
489            TokenType::Semicolon,
490            "Expected ';' after variable declaration",
491        );
492        self.define_variable(global);
493    }
494
495    /// Match the identifier token and pass it into identifier_constant to be added to the chunk if current scope is global
496    ///
497    /// Calls declare_variable() if the current scope is local
498    fn parse_variable(&mut self, error_msg: &str) -> usize {
499        self.consume(TokenType::Identifier, error_msg);
500        // check if the variable has the same name as a native function
501        if NATIVE_FUNCTIONS
502            .lock()
503            .unwrap()
504            .contains_key(&*self.previous().lexeme)
505        {
506            self.error("Cannot redefine a native function");
507        }
508        self.declare_variable();
509
510        if self.current_module().resolver.is_global() {
511            let str_val = self.previous().lexeme.clone();
512            self.identifier_constant(&str_val)
513        } else {
514            0
515        }
516    }
517
518    /// Add a string to the chunk as a constant and return the index
519    ///
520    /// Only used for global variables
521    fn identifier_constant(&mut self, str_val: &String) -> usize {
522        // self.add_constant(Value::PhoenixString(str_val.to_string()))
523        match self
524            .current_module()
525            .identifier_constants
526            .iter()
527            .position(|x| x == str_val)
528        {
529            Some(i) => i,
530            None => {
531                self.current_module()
532                    .identifier_constants
533                    .push(str_val.to_string());
534                self.current_module().identifier_constants.len() - 1
535            }
536        }
537    }
538
539    /// Add a string to the chunk as a constant and return the index
540    ///
541    /// Only used for global variables
542    pub fn identifier_constant_module(&mut self, str_val: &String, module: usize) -> usize {
543        // self.add_constant(Value::PhoenixString(str_val.to_string()))
544        match self
545            .modules
546            .get_mut(module)
547            .unwrap()
548            .identifier_constants
549            .iter()
550            .position(|x| x == str_val)
551        {
552            Some(i) => i,
553            None => {
554                self.modules
555                    .get_mut(module)
556                    .unwrap()
557                    .identifier_constants
558                    .push(str_val.to_string());
559                self.modules
560                    .get_mut(module)
561                    .unwrap()
562                    .identifier_constants
563                    .len()
564                    - 1
565            }
566        }
567    }
568
569    /// Emits the instruction to define the global variable
570    /// or to set the local variable as initialized
571    fn define_variable(&mut self, global: usize) {
572        if self.current_module().resolver.is_global() {
573            self.emit_instr(OpDefineGlobal(global));
574        } else {
575            self.current_module().resolver.mark_initialized();
576        }
577    }
578
579    fn statement(&mut self) {
580        if self.match_cur(TokenType::Print) {
581            self.print_statement();
582        } else if self.match_cur(TokenType::Import) {
583            self.import_statement();
584        } else if self.match_cur(TokenType::Return) {
585            self.return_statement();
586        } else if self.match_cur(TokenType::If) {
587            self.if_statement();
588        } else if self.match_cur(TokenType::While) {
589            self.while_statement();
590        } else if self.match_cur(TokenType::For) {
591            self.for_statement();
592        } else if self.match_cur(TokenType::LeftBrace) {
593            self.current_module().resolver.begin_scope();
594            self.block();
595            self.end_scope();
596        } else {
597            self.expression_statement();
598        }
599    }
600
601    fn print_statement(&mut self) {
602        self.expression();
603        self.consume(
604            TokenType::Semicolon,
605            "Expected ';' after value in print statement",
606        );
607        self.emit_instr(OpPrint);
608    }
609
610    fn import_statement(&mut self) {
611        // first we need to check if we are in a script function and else we error, because we can't import in a non-script function (for now)
612        if self.current_fn_type() != FunctionType::Script {
613            self.error("Can't import in a function");
614        }
615        // so we have something like "import foo" or "import bar from foo"
616        // for now we only support the first one
617        self.consume(TokenType::Identifier, "Expected identifier after import");
618        let name = self.previous().lexeme.clone();
619        self.consume(TokenType::Semicolon, "Expected ';' after import statement");
620        // now we have the name of the module we want to import
621
622        // first we try to open the file by doing current_dir + name + .phx
623        let mut path = env::current_dir().unwrap();
624        path.push(name.clone());
625        path.set_extension("phx");
626        // debug the path
627        if self.debug_mode {
628            println!("Importing module: {}", path.clone().to_str().unwrap());
629        }
630        let mut file = match File::open(path.clone()) {
631            Ok(f) => f,
632            Err(e) => {
633                self.error(format!("Could not open file: {}", e).as_str());
634                return;
635            }
636        };
637        // now we have the contents of the file in contents
638        let mut contents = String::new();
639        match file.read_to_string(&mut contents) {
640            Ok(_) => {}
641            Err(e) => {
642                self.error(format!("Could not read file: {}", e).as_str());
643                return;
644            }
645        }
646        let module = CompilerModuleChunk::new(
647            false,
648            name.clone(),
649            path.to_str().unwrap().to_string(),
650            contents,
651        );
652        if self.modules.len() > MAX_MODULES {
653            println!(
654                "[{}:{}] Can't load more than {} modules (maybe recursive imports?)",
655                self.current_module().scanner.file.clone(),
656                self.current_module().scanner.cur_line,
657                MAX_MODULES
658            );
659            exit(0);
660        }
661        self.modules.push(module);
662        self.parent_modules.push(self.current_module);
663        self.current_module = self.modules.len() - 1;
664        self.current_module_code = self.current_module;
665        self.module_table
666            .insert(name.clone(), self.modules.len() - 1);
667
668        // self.current_module().scanner.cur_line = 0;
669        let first_token = self.current_module().scanner.scan_token();
670        self.current_module().tokens.push(first_token.clone()); // Load up the first token
671
672        self.current_module()
673            .functions
674            .push(FunctionChunk::new(None, 0, FunctionType::Script)); // Start the compilation with a top level function
675
676        // Hack to account for the case where the first token is a TokenError
677        if let TokenType::Error = first_token.token_type {
678            self.advance();
679            self.error(first_token.lexeme.as_str());
680        }
681        while !self.match_cur(TokenType::EOF) {
682            self.declaration();
683        }
684        // idk if we need this tbh
685        self.end_compilation();
686
687        // now we need to add the module to the module table
688        let index_of_module = self.current_module;
689        self.current_module = self.parent_modules.pop().unwrap();
690        self.current_module_code = self.current_module;
691
692        // we create a global variable with the name of the module
693        self.emit_constant(Value::PhoenixModule(index_of_module));
694        let index = self.identifier_constant(&name);
695        self.define_variable(index);
696        self.emit_instr(OpImport(index_of_module));
697        // self.emit_instr(OpCode::OpPop);
698    }
699
700    fn return_statement(&mut self) {
701        if self.current_fn_type() == FunctionType::Script {
702            self.error("Cannot return from top-level code");
703        }
704
705        if self.match_cur(TokenType::Semicolon) {
706            // Nil return
707            self.emit_return();
708        } else {
709            if self.current_fn_type() == FunctionType::Initializer {
710                self.error("Cannot return a value from an initializer");
711            }
712
713            self.expression();
714            self.consume(TokenType::Semicolon, "Expected ';' after return value");
715            self.emit_instr(OpReturn);
716        }
717    }
718
719    fn if_statement(&mut self) {
720        // optional ( ) around the condition
721        // self.consume(TokenType::LeftParen, "Expected '(' after 'if'");
722        if self.match_cur(TokenType::LeftParen) {
723            self.advance();
724            self.expression();
725            self.consume(TokenType::RightParen, "Expected ')' after condition");
726        } else {
727            self.expression();
728        }
729
730        // Keep track of where we put the first conditional jump
731        let jump_index = self.emit_jif();
732
733        self.emit_instr(OpPop); // Pop off the if conditional in the 'then' case
734        self.statement(); // Then case
735
736        if self.match_cur(TokenType::Else) {
737            let else_jump = self.emit_jump(); // Keep track of where we put the jump to go over the else statement
738            self.patch_jump(jump_index);
739            self.emit_instr(OpPop); // Pop off the if conditional if we jump over the 'then' case
740            self.statement(); // Else case
741            self.patch_jump(else_jump);
742        } else {
743            self.patch_jump(jump_index); // No else case, so just jump to right after
744        }
745    }
746
747    fn while_statement(&mut self) {
748        let loop_start = self.current_chunk().code.len();
749
750        // self.consume(TokenType::LeftParen, "Expected '(' after 'while'");
751        self.expression();
752        // self.consume(TokenType::RightParen, "Expected ')' after loop condition");
753
754        let exit_jump = self.emit_jif();
755
756        self.emit_instr(OpPop);
757        self.statement();
758        self.emit_loop(loop_start);
759
760        self.patch_jump(exit_jump);
761        self.emit_instr(OpPop);
762    }
763
764    fn for_statement(&mut self) {
765        self.consume(TokenType::LeftParen, "Expected '(' after 'for'");
766
767        self.current_module().resolver.begin_scope();
768
769        // First clause: Can be var declaration or expression
770        if self.match_cur(TokenType::Semicolon) {
771            // Do nothing
772        } else if self.match_cur(TokenType::Var) {
773            self.var_declaration();
774        } else {
775            self.expression_statement(); //
776        }
777
778        let mut loop_start = self.current_chunk().code.len(); // Loop should include 2nd and 3rd clauses (if they exist)
779        let mut exit_jump = None;
780
781        // Loop conditional
782        if !self.match_cur(TokenType::Semicolon) {
783            self.expression();
784            self.consume(TokenType::Semicolon, "Expected ';' after loop condition");
785            exit_jump = Some(self.emit_jif());
786            self.emit_instr(OpPop); // Pop condition if we didn't jump
787        } // Note: if this conditional is not found, then there is no way to jump out of the loop
788
789        if !self.match_cur(TokenType::RightParen) {
790            // Jump to body, set this point to be the one to loop back to after executing the body, jump to next iteration
791            let body_jump = self.emit_jump(); // Jump to after the increment and the loop
792
793            let increment_start = self.current_chunk().code.len();
794            self.expression(); // Parse the increment expression
795            self.emit_instr(OpPop); // Pop the remaining value
796            self.consume(TokenType::RightParen, "Expected ')' after for loop clauses");
797
798            self.emit_loop(loop_start); // Loop back to the start after increment
799            loop_start = increment_start; // Make the body go to the start of the increment instead of the start of the loop
800
801            self.patch_jump(body_jump); // Patching up the body jump
802        }
803
804        self.statement();
805        self.emit_loop(loop_start);
806
807        if let Some(offset) = exit_jump {
808            self.patch_jump(offset);
809            self.emit_instr(OpPop);
810        }
811
812        self.end_scope();
813    }
814
815    fn block(&mut self) {
816        while !self.check(TokenType::RightBrace) && !self.check(TokenType::EOF) {
817            self.declaration();
818        }
819        self.consume(TokenType::RightBrace, "Expected '}' after block"); // Fails if we hit EOF instead
820    }
821
822    /// Parses a 'this' keyword by just treating it as a special class-only variable that will be magically instantiated
823    /// Our resolver will automatically put the 'this' variable in locals slot 0 for any methods, so this (ha) will always result in a Get/Set Local op being emitted
824    fn this(&mut self) {
825        if self.current_module().current_class.is_none() {
826            self.error("Cannot use keyword 'this' outside of a class");
827        }
828        self.variable(false);
829    }
830
831    /// Consumes super.method_name and emits an OpGetSuper(index of the "method_name" identifier)
832    fn super_(&mut self) {
833        if self.current_module().current_class.is_none() {
834            self.error("Cannot use keyword 'super' outside of a class");
835            return; // Ideally we would attempt to compile the rest of the expression, but trying to continue will cause a panic
836        }
837
838        let superclass_index = if self.current_class().superclass.is_none() {
839            self.error("Cannot use keyword 'super' in a class which does not inherit a class");
840            0 // Random value, we don't care that this value is wrong because we're going to exit because of the error anyway
841        } else {
842            self.current_class().superclass.unwrap()
843        };
844
845        self.consume(TokenType::Dot, "Expected '.' after 'super'");
846        self.consume(TokenType::Identifier, "Expected superclass method name");
847        let name = self.previous().lexeme.clone();
848        let name_index = self.identifier_constant(&name);
849
850        // At the time of OpGetSuper we want to know 2 things
851        // 1. The superclass we're going to be looking for values in
852        // 2. A pointer to the instance we want to bind the method to
853
854        let superclass_val = Value::PhoenixClass(superclass_index);
855        self.emit_constant(superclass_val);
856        self.named_variable(&String::from("this"), false); // Slightly better?
857        self.emit_instr(OpGetSuper(name_index));
858    }
859
860    fn method(&mut self) {
861        self.consume(TokenType::Identifier, "Expected method name");
862        let name = self.previous().lexeme.clone();
863        let name_index = self.identifier_constant(&name);
864
865        let index = if name.eq("init") {
866            self.current_class().has_init = true;
867            self.function(FunctionType::Initializer)
868        } else {
869            self.function(FunctionType::Method)
870        };
871        self.current_class().methods.insert(name_index, index); // Note: This provides method overriding since we do not check if the name already existed in the map
872
873        // NOTE!! this way of doing methods does NOT bind closures... So there is a very very stupid way this could go wrong
874        // Something like fun thing() { class Inner { method() { // use a local variable from thing in here }}}
875        // ...
876        // ...
877        // Fuck it
878        // This is a feature
879        // Not a bug
880        // I swear
881    }
882
883    /// Compiles the function into a new FunctionChunk, adds it to the current parser, adds the PhoenixFunction object to the constants stack, emits a OpConstant pointing to it and a OpClosure to wrap it
884    fn function(&mut self, fun_type: FunctionType) -> usize {
885        //let mut function_parser = self.from_old(fun_type);
886
887        let index = self.start_child(fun_type);
888        self.current_module().resolver.begin_scope();
889
890        self.consume(TokenType::LeftParen, "Expected '(' after function name");
891        if !self.check(TokenType::RightParen) {
892            loop {
893                let param_constant = self.parse_variable("Expected parameter name");
894                self.define_variable(param_constant);
895
896                let cur_function = self.current_fn();
897                cur_function.arity += 1;
898                if cur_function.arity > 255 {
899                    self.error("Cannot have more than 255 parameters");
900                }
901
902                if !self.match_cur(TokenType::Comma) {
903                    break;
904                }
905            }
906        }
907        self.consume(
908            TokenType::RightParen,
909            "Expected ')' after function parameters",
910        );
911
912        self.consume(TokenType::LeftBrace, "Expected '{' before function body");
913        self.block();
914
915        let upvalues = self.current_module().resolver.pop();
916        let has_upvalues = !upvalues.is_empty();
917        if !upvalues.is_empty() {
918            self.current_fn().set_upvalues(upvalues); // Gotta set this before end_child() switches what the current_fn is
919        }
920
921        self.end_child();
922
923        if fun_type != FunctionType::Method && fun_type != FunctionType::Initializer {
924            // We don't need this for methods because they are statically loaded into the ClassChunk, not at runtime on the stack
925            self.emit_constant(Value::PhoenixFunction(index));
926
927            if has_upvalues {
928                self.emit_instr(OpClosure);
929            }
930        }
931
932        index
933    }
934
935    fn expression_statement(&mut self) {
936        self.expression();
937        self.consume(TokenType::Semicolon, "Expected ';' after value");
938        self.emit_instr(OpPop);
939    }
940
941    fn expression(&mut self) {
942        self.parse_precedence(Precedence::Assignment)
943    }
944
945    fn and_operator(&mut self) {
946        let end_jump = self.emit_jif();
947
948        self.emit_instr(OpPop);
949        self.parse_precedence(Precedence::And); // Parse right hand side of the infix expression
950        self.patch_jump(end_jump); // Jump to after it if the first argument was already false, leaving the false value on the top of the stack to be the result
951        // Otherwise the first argument is true, so the value of the whole and is equal to the value of the second argument, so just proceed as normal
952    }
953
954    fn or_operator(&mut self) {
955        // If false then execute the other expression
956        let else_jump = self.emit_jif();
957
958        // If the first one is already truthy, go to the end
959        let end_jump = self.emit_jump();
960
961        self.patch_jump(else_jump);
962        self.emit_instr(OpPop);
963        self.parse_precedence(Precedence::Or);
964
965        self.patch_jump(end_jump);
966    }
967
968    fn number(&mut self) {
969        // We trust that the scanner has given us something that looks like a number (124214.52)
970        // BUT the scanner does NOT check the size, so this parse to f32 can still fail due to overflow
971
972        let s = &self.previous().lexeme;
973
974        // we want to cast all numbers first to i64, and if that fails to f32, because normally we want integers
975        if let Ok(value) = s.parse::<i64>() {
976            self.emit_constant(Value::Long(value));
977        } else {
978            // we try it as a long, maybe it's an integer
979            if let Ok(value) = if s.ends_with('f') {
980                &s[0..s.len() - 1]
981            } else {
982                s
983            }
984                .parse::<f32>()
985            {
986                self.emit_constant(Value::Float(value));
987            } else {
988                self.error(format!("Invalid number: {s}").as_str());
989            }
990        }
991    }
992
993    fn literal(&mut self) {
994        match self.previous().token_type {
995            TokenType::False => self.emit_instr(OpFalse),
996            TokenType::True => self.emit_instr(OpTrue),
997            TokenType::Nil => self.emit_instr(OpNil),
998            _ => unreachable!(
999                "Unreachable state reached, attempted to make a literal out of a non-literal type???"
1000            ),
1001        }
1002    }
1003
1004    fn string(&mut self) {
1005        let str_val = self.previous().lexeme.clone();
1006        let cleaned = str_val[1..str_val.len() - 1].to_string();
1007
1008        self.emit_constant(Value::PhoenixString(cleaned));
1009        self.emit_instr(OpCreateString);
1010    }
1011
1012    fn list(&mut self, _can_assign: bool) {
1013        // * list: [1, 2, 3, 4, ...]
1014        let mut size = 0;
1015        if !self.check(TokenType::RightBracket) {
1016            loop {
1017                self.expression();
1018                size += 1;
1019                if !self.match_cur(TokenType::Comma) {
1020                    break;
1021                }
1022            }
1023        }
1024        self.consume(TokenType::RightBracket, "Expected ']' after list");
1025        self.emit_instr(OpCreateList(size));
1026    }
1027
1028    fn hashmap(&mut self, _can_assign: bool) {
1029        // hashmap looks like this: var hashmap = { "key": "value", "key2": "value2" }
1030        // and we should push all the values in this order on the stack and then emit OpCode::CreateHashMap(size)
1031        // with size equal to the amount of keys
1032        let mut size = 0;
1033        if !self.check(TokenType::RightBrace) {
1034            loop {
1035                self.expression();
1036                self.consume(TokenType::Colon, "Expected ':' after key");
1037                self.expression();
1038                size += 1;
1039                if !self.match_cur(TokenType::Comma) {
1040                    break;
1041                }
1042            }
1043        }
1044        self.consume(TokenType::RightBrace, "Expected '}' after hashmap");
1045        self.emit_instr(OpCreateHashMap(size));
1046    }
1047
1048    /// Parse an identifier that we know to be a variable
1049    ///
1050    /// Eventually emits a get instr or a set instr + the instructions to process the expr
1051    ///
1052    /// Note: Uses named_variable to do all the heavy lifting
1053    fn variable(&mut self, can_assign: bool) {
1054        let name = &self.previous().lexeme.clone();
1055        self.named_variable(name, can_assign)
1056    }
1057
1058    // Note: parse_precedence with TokenIdentifier => variable() -> named_variable(previous.lexeme)
1059    // Could be a getter or a setter, so lookahead for a '='
1060    /// Helper function for variable.
1061    /// 1. Determine if this is a local var, upvalue, or global and make the get and set ops
1062    /// 2. Determine if this is a get or a set based on can_assign and the existence of a '='
1063    fn named_variable(&mut self, name: &String, can_assign: bool) {
1064        let local_arg = match self.current_module().resolver.resolve_local(name) {
1065            Some(opt) => opt,
1066            None => {
1067                self.error("Cannot read local variable in its own initializer");
1068                return;
1069            }
1070        };
1071
1072        // Figure out which type of get/set OpCodes we want
1073        let (get_op, set_op) = if let Some(local_index) = local_arg {
1074            (OpGetLocal(local_index), OpSetLocal(local_index))
1075        } else if let Some(upvalue_index) = self.current_module().resolver.resolve_upvalue(name) {
1076            (OpGetUpvalue(upvalue_index), OpSetUpvalue(upvalue_index))
1077        } else {
1078            let global_arg = self.identifier_constant(name); // Does NOT check at compile time if this variable can be resolved
1079
1080            if self.match_cur(TokenType::LeftParen) {
1081                let arg_count = self.argument_list();
1082                (
1083                    OpCallGlobal(self.current_module, global_arg, arg_count),
1084                    OpSetGlobal(global_arg),
1085                )
1086            } else {
1087                (OpGetGlobal(global_arg), OpSetGlobal(global_arg))
1088            }
1089        };
1090
1091        // hacky way to implement all kinds of operations
1092        // todo: make this better
1093        // todo: check if this works correctly with classes and all that stuff
1094        // Figure out if we want to use the get or the set from the pair of possible ops we determined earlier
1095        macro_rules! emit_assign {
1096            ($operation: path) => {{
1097                self.emit_instr(get_op);
1098                self.advance();
1099                self.expression();
1100                self.emit_instr($operation);
1101                self.emit_instr(set_op);
1102            }};
1103        }
1104        if can_assign {
1105            match self.current().token_type {
1106                TokenType::Equal => {
1107                    self.advance();
1108                    self.expression();
1109                    self.emit_instr(set_op);
1110                }
1111                TokenType::PlusAssign => emit_assign!(OpAdd),
1112                TokenType::MinusAssign => emit_assign!(OpSubtract),
1113                TokenType::StarAssign => emit_assign!(OpMultiply),
1114                TokenType::SlashAssign => emit_assign!(OpDivide),
1115                TokenType::PlusPlus => {
1116                    self.emit_instr(get_op);
1117                    self.emit_constant(Value::Long(1));
1118                    self.emit_instr(OpAdd);
1119                    self.emit_instr(set_op);
1120                }
1121                TokenType::MinusMinus => {
1122                    self.emit_instr(get_op);
1123                    self.emit_constant(Value::Long(1));
1124                    self.emit_instr(OpSubtract);
1125                    self.emit_instr(set_op);
1126                }
1127                TokenType::LeftBracket => {
1128                    // check if this is a list
1129                    self.advance();
1130                    self.emit_instr(get_op);
1131                    self.expression();
1132                    self.consume(TokenType::RightBracket, "Expected ']' after index");
1133                    if self.match_cur(TokenType::Equal) {
1134                        self.expression();
1135                        self.emit_instr(OpSetIndex);
1136                        // self.emit_instr(set_op);
1137                    } else {
1138                        self.emit_instr(OpGetIndex);
1139                    }
1140                }
1141                _ => self.emit_instr(get_op),
1142            }
1143        } else {
1144            self.emit_instr(get_op);
1145        }
1146    }
1147
1148    fn grouping(&mut self) {
1149        self.expression();
1150        self.consume(TokenType::RightParen, "Expected ')' after expression");
1151    }
1152
1153    fn unary(&mut self) {
1154        let operator_type = self.previous().token_type;
1155        self.parse_precedence(Precedence::Unary); // evaluate the expression in the unary
1156        match operator_type {
1157            TokenType::Minus => self.emit_instr(OpNegate),
1158            TokenType::Bang => self.emit_instr(OpNot),
1159            _ => (), // Error?
1160        }
1161    }
1162
1163    fn binary(&mut self) {
1164        let operator_type = self.previous().token_type;
1165
1166        let rule = get_rule(operator_type);
1167        self.parse_precedence(rule.next_precedence());
1168
1169        // Stack based vm, so emit the binary instr after
1170        match operator_type {
1171            TokenType::Plus => self.emit_instr(OpAdd),
1172            TokenType::Minus => self.emit_instr(OpSubtract),
1173            TokenType::Star => self.emit_instr(OpMultiply),
1174            TokenType::Slash => self.emit_instr(OpDivide),
1175            TokenType::BangEqual => self.emit_instrs(&[OpEqual, OpNot]),
1176            TokenType::EqualEqual => self.emit_instr(OpEqual),
1177            TokenType::Greater => self.emit_instr(OpGreater),
1178            TokenType::GreaterEqual => self.emit_instrs(&[OpLess, OpNot]),
1179            TokenType::Less => self.emit_instr(OpLess),
1180            TokenType::LessEqual => self.emit_instrs(&[OpGreater, OpNot]),
1181            _ => {
1182                self.error("Invalid binary operator");
1183            } // error?
1184        }
1185    }
1186
1187    /// Infix operation for function calls, assumes that the PhoenixFunction will be at the top of the stack when this is called, usually
1188    /// via a global/local variable resolution
1189    fn call(&mut self) {
1190        let arg_count = self.argument_list();
1191        self.emit_instr(OpCall(arg_count, self.current_module))
1192    }
1193
1194    /// Parses expressions while looking for commas between and for the closing paren. Leaves the values on the stack
1195    fn argument_list(&mut self) -> usize {
1196        let mut arg_count = 0;
1197        if !self.check(TokenType::RightParen) {
1198            loop {
1199                self.expression();
1200                if arg_count == 255 {
1201                    self.error("Cannot have more than 255 arguments");
1202                }
1203                arg_count += 1;
1204
1205                if !self.match_cur(TokenType::Comma) {
1206                    break;
1207                }
1208            }
1209        }
1210        self.consume(
1211            TokenType::RightParen,
1212            "Expected ')' after function argument list",
1213        );
1214        arg_count
1215    }
1216
1217    fn dot(&mut self, can_assign: bool) {
1218        let module_name = &self.current_module_ref().tokens
1219            [self.current_module_ref().tokens.len() - 3]
1220            .lexeme
1221            .clone();
1222        // check if this is a module name
1223        if self.module_table.contains_key(module_name) {
1224            // pop the name of the module off the stack
1225            self.emit_instr(OpPop);
1226            // get the index of the module
1227            let module_index = *self.module_table.get(module_name).unwrap();
1228            // let function_index = self.identifier_constant_module(function_name, module_index);
1229            // self.emit_instr(OpGetModuleVar(module_index, function_index));
1230            // self.emit_instr(OpCall(arg_count, module_index));
1231            let current_module = self.current_module;
1232            self.current_module = module_index;
1233            // dbg!(self.current());
1234            self.expression();
1235            self.current_module = current_module;
1236            return;
1237        }
1238        self.consume(TokenType::Identifier, "Expected property name after '.'");
1239        let name_index = self.identifier_constant(&self.previous().lexeme.clone());
1240        // let function_name = &self.current_module_ref().tokens
1241        //     [self.current_module_ref().tokens.len() - 2]
1242        //     .lexeme
1243        //     .clone();
1244
1245        if can_assign && self.match_cur(TokenType::Equal) {
1246            // We check can_assign so that a + b.c = 3 does not invalidly emit a set op
1247            // Setter
1248            self.expression();
1249            self.emit_instr(OpSetProperty(name_index));
1250        } else if self.match_cur(TokenType::LeftParen) {
1251            // A left paren after the initializer will usually mean a method invocation, so compress that into a single OpCode here
1252            // but it could also be a call to a function in a module with that name, so we need to check for that
1253            // println!("{}.{} {}", module_name, function_name, name_index);
1254            let arg_count = self.argument_list();
1255            self.emit_instr(OpInvoke(name_index, arg_count, self.current_module));
1256        } else if self.match_cur(TokenType::LeftBracket) {
1257            self.emit_instr(OpGetProperty(name_index));
1258            self.expression();
1259            self.consume(TokenType::RightBracket, "Expected ']' after index");
1260            if self.match_cur(TokenType::Equal) {
1261                self.expression();
1262                self.emit_instr(OpSetIndex);
1263                // self.emit_instr(set_op);
1264            } else {
1265                self.emit_instr(OpGetIndex);
1266            }
1267        } else {
1268            self.emit_instr(OpGetProperty(name_index));
1269        }
1270    }
1271
1272    /// Sets the compiler to generate a new function chunk for the next segment of code
1273    fn start_child(&mut self, function_type: FunctionType) -> usize {
1274        let function_name = self.previous().lexeme.clone();
1275        self.current_module().functions.push(FunctionChunk::new(
1276            Some(function_name),
1277            0,
1278            function_type,
1279        ));
1280        self.current_module().resolver.push(function_type);
1281        let index = self.current_module_ref().current_function;
1282        self.current_module().parent_functions.push(index);
1283        self.current_module().current_function = self.current_module().functions.len() - 1;
1284
1285        self.current_module().functions.len() - 1
1286    }
1287
1288    /// Switches the current chunk out of the new function def
1289    fn end_child(&mut self) {
1290        // Emit an implicit nil return if not specified explicit
1291        let last_instr = self.current_chunk_ref().code.last();
1292        if last_instr.is_none() || last_instr.unwrap().op_code != OpReturn {
1293            self.emit_return();
1294        }
1295        self.current_module().current_function =
1296            self.current_module().parent_functions.pop().unwrap();
1297    }
1298
1299    #[deprecated(note = "Use new instead")]
1300    pub fn new_default(code: String, quiet: bool, start_line: usize) -> Compiler {
1301        Compiler::new_file(
1302            DEFAULT_FILE_NAME.to_string(),
1303            code,
1304            quiet,
1305            start_line,
1306            false,
1307            false,
1308        )
1309    }
1310
1311    pub fn new_file(
1312        file: String,
1313        code: String,
1314        quiet: bool,
1315        start_line: usize,
1316        debug_mode: bool,
1317        wait_mode: bool,
1318    ) -> Compiler {
1319        let mut compiler = Compiler {
1320            modules: vec![CompilerModuleChunk::new(
1321                true,
1322                "main".to_string(),
1323                file.to_string(),
1324                code.clone(),
1325            )],
1326            module_table: Default::default(),
1327            parent_modules: vec![],
1328            current_module: 0,
1329            current_module_code: 0,
1330
1331            had_error: false,
1332            panic_mode: false,
1333            quiet_mode: quiet,
1334            debug_mode,
1335            wait_mode,
1336        };
1337        compiler.new_start(file, code, quiet, start_line, 0);
1338        compiler
1339    }
1340
1341    /// whether it had an  error
1342    pub fn new_start(
1343        &mut self,
1344        file: String,
1345        code: String,
1346        quiet: bool,
1347        start_line: usize,
1348        start_pos: usize,
1349    ) {
1350        self.current_module().scanner = Scanner::new(file, code, start_line);
1351        self.current_module().scanner.cur_pos = start_pos;
1352        self.current_module().scanner.start_pos = start_pos;
1353        self.quiet_mode = quiet;
1354    }
1355
1356    pub fn compile(&mut self, debug: bool) -> Option<CompilationResult> {
1357        self.debug_mode = debug;
1358        let first_token = self.current_module().scanner.scan_token();
1359        self.current_module().tokens.push(first_token.clone()); // Load up the first token
1360
1361        self.current_module()
1362            .functions
1363            .push(FunctionChunk::new(None, 0, FunctionType::Script)); // Start the compilation with a top level function
1364
1365        // Hack to account for the case where the first token is a TokenError
1366        if let TokenType::Error = first_token.token_type {
1367            self.advance();
1368            self.error(first_token.lexeme.as_str());
1369        }
1370        while !self.match_cur(TokenType::EOF) {
1371            self.declaration();
1372        }
1373        self.end_compilation();
1374
1375        if !self.had_error {
1376            if debug {
1377                for m in self.modules.iter() {
1378                    println!("========= module: {} =========", m.scanner.file);
1379                    for (index, fn_chunk) in m.functions.iter().enumerate() {
1380                        if fn_chunk.fn_type != FunctionType::Method
1381                            && fn_chunk.fn_type != FunctionType::Initializer
1382                        {
1383                            disassemble_fn_chunk(
1384                                m.scanner.file.as_str().to_string(),
1385                                index,
1386                                fn_chunk,
1387                                &m.constants,
1388                                &m.identifier_constants,
1389                            );
1390                        }
1391                    }
1392
1393                    for class_chunk in m.classes.iter() {
1394                        disassemble_class_chunk(
1395                            class_chunk,
1396                            &m.functions,
1397                            &m.classes,
1398                            &m.constants,
1399                            &m.identifier_constants,
1400                        );
1401                    }
1402                }
1403            }
1404            Some(CompilationResult {
1405                version: VERSION.to_string(),
1406                modules: self
1407                    .modules
1408                    .clone()
1409                    .iter()
1410                    .map(|m| ModuleChunk::from(m.clone()))
1411                    .collect(),
1412                modules_table: self.module_table.clone(),
1413                cur_pos: self.current_module().scanner.cur_pos,
1414            })
1415        } else {
1416            None
1417        }
1418    }
1419
1420    pub fn compile_code(code: String, debug: bool, wait: bool) -> Option<CompilationResult> {
1421        let mut compiler =
1422            Compiler::new_file(DEFAULT_FILE_NAME.to_string(), code, false, 0, debug, wait);
1423        compiler.compile(debug)
1424    }
1425}
1426
1427impl Clone for Compiler {
1428    fn clone(&self) -> Self {
1429        Compiler {
1430            modules: self.modules.clone(),
1431            module_table: self.module_table.clone(),
1432            parent_modules: self.parent_modules.clone(),
1433            current_module: self.current_module,
1434            current_module_code: 0,
1435
1436            had_error: self.had_error,
1437            panic_mode: self.panic_mode,
1438            quiet_mode: self.quiet_mode,
1439            debug_mode: false,
1440            wait_mode: self.wait_mode,
1441        }
1442    }
1443}
1444
1445#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1446pub struct CompilationResult {
1447    pub version: String,
1448    pub modules: Vec<ModuleChunk>,
1449    pub modules_table: HashMap<String, usize>,
1450    pub cur_pos: usize,
1451}
1452
1453impl Default for CompilationResult {
1454    fn default() -> Self {
1455        CompilationResult::new()
1456    }
1457}
1458
1459impl CompilationResult {
1460    pub fn new() -> CompilationResult {
1461        CompilationResult {
1462            version: VERSION.to_string(),
1463            modules: vec![],
1464            modules_table: Default::default(),
1465            cur_pos: 0,
1466        }
1467    }
1468
1469    // pub fn append(&mut self, mut other: CompilationResult) {
1470    //     self.classes.append(&mut other.classes);
1471    //     self.functions.append(&mut other.functions);
1472    //     // filter out all functions that f.fn_type == FunctionType::Script
1473    //     self.functions.retain(|f| f.fn_type != FunctionType::Script);
1474    //     // remove all duplicates (fu.name == f.name)
1475    //     let mut used_names = Vec::new();
1476    //     self.functions.retain(|f| {
1477    //         return if used_names.contains(&f.clone().name.unwrap()) {
1478    //             false
1479    //         } else {
1480    //             used_names.push(f.clone().name.unwrap());
1481    //             true
1482    //         };
1483    //     });
1484    //     // debug the functions
1485    //     for f in self.functions.clone() {
1486    //         println!("got function {}", f.name.unwrap());
1487    //     }
1488    //     self.constants.append(&mut other.constants);
1489    //     self.identifier_constants.append(&mut other.identifier_constants);
1490    // }
1491}