silt_lua/
compiler.rs

1use std::{
2    fmt::{Display, Formatter},
3    iter::Peekable,
4    mem::{swap, take},
5    println,
6    rc::Rc,
7    vec,
8};
9
10use hashbrown::HashMap;
11
12use crate::{
13    chunk::Chunk,
14    code::OpCode,
15    error::{ErrorTuple, Location, SiltError},
16    function::FunctionObject,
17    lexer::{Lexer, TokenResult},
18    token::{Operator, Token},
19    value::Value,
20};
21
22macro_rules! build_block_until_then_eat {
23    ($self:ident, $($rule:ident)|*) => {{
24        while match $self.peek()? {
25            $( Token::$rule)|* => {$self.eat(); false}
26            Token::EOF => {
27                return Err($self.error_at(SiltError::UnterminatedBlock));
28            }
29            _ =>{declaration($self)?; true}
30        } {
31        }
32    }};
33}
34
35macro_rules! build_block_until {
36    ($self:ident, $($rule:ident)|*) => {{
37        while match $self.peek()? {
38            $( Token::$rule)|* => false,
39            Token::EOF => {
40                return Err($self.error_at(SiltError::UnterminatedBlock));
41            }
42            _ =>{declaration($self)?; true}
43        } {
44        }
45    }};
46}
47
48macro_rules! scope_and_block_until {
49    ($self:ident, $($rule:ident)|*) => {{
50        begin_scope($self);
51        build_block_until!($self, $($rule)|*);
52        end_scope($self,false);
53    }};
54}
55
56macro_rules! scope_and_block_until_then_eat {
57    ($self:ident, $($rule:ident)|*) => {{
58        begin_scope($self);
59        build_block_until_then_eat!($self, $($rule)|*);
60        end_scope($self,false);
61    }};
62}
63
64macro_rules! devnote {
65    ($self:ident $message:literal) => {
66        #[cfg(feature = "dev-out")]
67        println!(
68            "=> {}: peek: {:?} -> current: {:?}",
69            $message,
70            $self.peek().unwrap_or(&Token::Nil).clone(),
71            $self.get_current().unwrap_or(&Token::Nil)
72        );
73    };
74}
75
76macro_rules! devout {
77        ($($arg:tt)*) => {
78            #[cfg(feature = "dev-out")]
79            println!($($arg)*);
80        }
81    }
82
83macro_rules! op_assign {
84    ($self:ident, $ident:ident,$op:ident) => {{
85        let value = $self.expression();
86        let bin = Expression::Binary {
87            left: Box::new(Expression::Variable {
88                $ident,
89                location: $self.get_last_loc(),
90            }),
91            operator: Operator::$op,
92            right: Box::new(value),
93            location: $self.get_last_loc(),
94        };
95        Expression::Assign {
96            ident: $ident,
97            value: Box::new(bin),
98            location: $self.get_last_loc(),
99        }
100    }};
101}
102
103/** error if missing, eat if present */
104macro_rules! expect_token {
105    ($self:ident $token:ident) => {{
106        if let Token::$token = $self.peek()? {
107            $self.eat();
108        } else {
109            return Err($self.error_at(SiltError::ExpectedToken(Token::$token)));
110        }
111    };};
112    ($self:ident, $token:ident, $custom_error:expr) => {{
113        if let Token::$token = $self.peek()? {
114            $self.eat();
115        } else {
116            return Err($custom_error);
117        }
118    };};
119}
120macro_rules! expect_token_exp {
121    ($self:ident $token:ident) => {{
122        if let Some(&Token::$token) = $self.peek() {
123            $self.eat();
124        } else {
125            $self.error(SiltError::ExpectedToken(Token::$token));
126            return Expression::InvalidExpression;
127        }
128    };};
129}
130
131macro_rules! rule {
132    ($prefix:expr, $infix:expr, $precedence:tt) => {{
133        ParseRule {
134            prefix: $prefix,
135            infix: $infix,
136            precedence: Precedence::$precedence,
137        }
138    }};
139    () => {};
140}
141
142/** the higher the precedence, */
143#[derive(PartialEq, PartialOrd)]
144enum Precedence {
145    None,
146    Assignment, // =
147    Or,         // or
148    And,        // and
149    Equality,   // == ~= !=
150    Comparison, // < > <= >=
151    Concat,     // ..
152    Term,       // + -
153    Factor,     // * /
154    Unary,      // ~ - !
155    Call,       // . ()
156    Primary,
157}
158// precedence enum includes concat ..
159
160type Ident = u8;
161
162type Catch = Result<(), ErrorTuple>;
163
164impl Precedence {
165    fn next(self) -> Self {
166        match self {
167            Precedence::None => Precedence::Assignment,
168            Precedence::Assignment => Precedence::Or,
169            Precedence::Or => Precedence::And,
170            Precedence::And => Precedence::Equality,
171            Precedence::Equality => Precedence::Comparison,
172            Precedence::Comparison => Precedence::Concat,
173            Precedence::Concat => Precedence::Term,
174            Precedence::Term => Precedence::Factor,
175            Precedence::Factor => Precedence::Unary,
176            Precedence::Unary => Precedence::Call,
177            Precedence::Call => Precedence::Primary,
178            Precedence::Primary => Precedence::Primary, // TODO over?
179        }
180    }
181}
182
183impl Display for Precedence {
184    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
185        match self {
186            Precedence::None => write!(f, "None"),
187            Precedence::Assignment => write!(f, "Assignment"),
188            Precedence::Or => write!(f, "Or"),
189            Precedence::And => write!(f, "And"),
190            Precedence::Equality => write!(f, "Equality"),
191            Precedence::Comparison => write!(f, "Comparison"),
192            Precedence::Concat => write!(f, "Concat"),
193            Precedence::Term => write!(f, "Term"),
194            Precedence::Factor => write!(f, "Factor"),
195            Precedence::Unary => write!(f, "Unary"),
196            Precedence::Call => write!(f, "Call"),
197            Precedence::Primary => write!(f, "Primary"),
198        }
199    }
200}
201
202struct ParseRule {
203    prefix: fn(&mut Compiler, can_assign: bool) -> Catch,
204    infix: fn(&mut Compiler, can_assign: bool) -> Catch,
205    precedence: Precedence,
206}
207
208/** stores a local identifier's name by boxed string, if none is provbided it serves as a placeholder for statements such as a loop, this way they cannot be resolved as variables */
209struct Local {
210    ident: Option<Box<String>>,
211    /** scope depth, indepedent of functional depth */
212    depth: usize,
213    /** how many layers deep the local value is nested in a function, with 0 being global (should only happen once to reserve the root func on the stack) */
214    functional_depth: usize,
215    is_captured: bool,
216}
217
218struct UpLocal {
219    /** location on the overall stack */
220    ident: u8,
221    /** location on the immediately scoped stack, 1 if it's the first declared value in scope (after closure) */
222    // scoped_ident: u8,
223    neighboring: bool,
224    universal_ident: u8,
225}
226
227pub struct Compiler {
228    pub body: FunctionObject,
229    iterator: Peekable<Lexer>,
230    pub current_index: usize,
231    pub errors: Vec<ErrorTuple>,
232    pub valid: bool,
233    current: Result<Token, ErrorTuple>,
234    current_location: Location,
235    scope_depth: usize,
236    functional_depth: usize,
237    // TODO we need a fail catch if we exceed a local variable amount of up values as well
238    up_values: Vec<Vec<UpLocal>>,
239    local_offset: Vec<usize>,
240    /** an offset tracker each time we descend into a new functional scope. For instance if we drop 1 level down from the root level that had 3 locals prior [A,B,C] then our stack looks like [root, A, B, C, fn] then we'll store 3 at this field's index 0 since the calling function is always at the bottom of the stack */
241    local_functional_offset: Vec<usize>,
242    locals: Vec<Local>,
243    local_count: usize,
244    labels: HashMap<String, usize>,
245    // location: (usize, usize),
246    // previous: TokenTuple,
247    // pre_previous: TokenTuple,
248    pending_gotos: Vec<(String, usize, Location)>,
249    extra: bool, // pub global: &'a mut Environment,
250    /** hack to flip off a pop when an expression takes on statement properties, used only for := right now */
251    override_pop: bool,
252}
253
254impl<'a> Compiler {
255    /** Create a new compiler instance */
256    pub fn new() -> Compiler {
257        // assert!(p.len() == p.len());
258        Self {
259            body: FunctionObject::new(None, true),
260            iterator: Lexer::new("".to_string()).peekable(),
261            current: Ok(Token::Nil),
262            current_location: (0, 0),
263            current_index: 0,
264            errors: vec![],
265            valid: true,
266            scope_depth: 0,
267            functional_depth: 0,
268            up_values: vec![vec![]],
269            locals: vec![Local {
270                ident: None,
271                depth: 0,
272                functional_depth: 0,
273                is_captured: false,
274            }],
275            local_functional_offset: vec![],
276            local_offset: vec![],
277            local_count: 1,
278            labels: HashMap::new(),
279            pending_gotos: vec![],
280            // location: (0, 0),
281            // previous: (Token::Nil, (0, 0)),
282            // pre_previous: (Token::Nil, (0, 0)),
283            extra: true,
284            override_pop: false,
285        }
286    }
287
288    /** Syntax error with code at location */
289    fn error_syntax(&mut self, code: SiltError, location: Location) -> ErrorTuple {
290        self.valid = false;
291        self.body.chunk.invalidate();
292        ErrorTuple { code, location }
293    }
294
295    /**syntax error at current token location with provided code */
296    fn error_at(&mut self, code: SiltError) -> ErrorTuple {
297        self.error_syntax(code, self.current_location)
298    }
299
300    /** Print all syntax errors */
301    pub fn print_errors(&self) {
302        for e in &self.errors {
303            println!("!!{} at {}:{}", e.code, e.location.0, e.location.1);
304        }
305    }
306
307    pub fn error_string(&self) -> String {
308        let mut s = String::new();
309        for e in &self.errors {
310            s.push_str(&format!(
311                "!!{} at {}:{}",
312                e.code, e.location.0, e.location.1
313            ));
314        }
315        s
316    }
317
318    /** Push error and location on to error stack */
319    fn push_error(&mut self, code: ErrorTuple) {
320        self.errors.push(code);
321    }
322
323    /** Return current array of errors */
324    pub fn get_errors(&self) -> &Vec<ErrorTuple> {
325        &self.errors
326    }
327
328    pub fn pop_errors(&mut self) -> Vec<ErrorTuple> {
329        std::mem::replace(&mut self.errors, vec![])
330    }
331
332    fn get_chunk(&self) -> &Chunk {
333        &self.body.chunk
334    }
335
336    fn get_chunk_mut(&mut self) -> &mut Chunk {
337        &mut self.body.chunk
338    }
339
340    fn get_chunk_size(&self) -> usize {
341        self.body.chunk.code.len()
342    }
343
344    fn write_code(&mut self, byte: OpCode, location: Location) -> usize {
345        self.body.chunk.write_code(byte, location)
346    }
347
348    fn read_last_code(&self) -> &OpCode {
349        self.body.chunk.read_last_code()
350    }
351
352    fn write_identifier(&mut self, identifier: Box<String>) -> usize {
353        self.body.chunk.write_identifier(identifier)
354    }
355
356    /** Tokens, not stack. Pop and return the token tuple, take care as this does not wipe the current token but does advance the iterator */
357    fn pop(&mut self) -> (Result<Token, ErrorTuple>, Location) {
358        self.current_index += 1;
359        match self.iterator.next() {
360            Some(Ok(t)) => {
361                devout!("popped {}", t.0);
362                (Ok(t.0), t.1)
363            }
364            Some(Err(e)) => {
365                let l = e.location;
366                (Err(e), l)
367            }
368            None => (Ok(Token::EOF), (0, 0)),
369        }
370    }
371
372    /** Force stack to pop N values without usual niceties, this both emits opcode and drops off the emulated stack locals */
373    fn force_stack_pop(&mut self, n: usize) {
374        self.locals.truncate(self.locals.len() - n);
375        self.emit_at(OpCode::POPS(n as u8));
376    }
377
378    /** Slightly faster pop that devourse the token or error, should follow a peek or risk skipping as possible error. Probably irrelevant otherwise. */
379    fn eat(&mut self) {
380        self.current_index += 1;
381        let t = self.iterator.next();
382        #[cfg(feature = "dev-out")]
383        {
384            match t {
385                Some(Ok(t)) => println!("eat {}", t.0),
386                Some(Err(e)) => println!("eat {}", e.code),
387                None => println!("eat {:?}", Token::EOF),
388            }
389        }
390    }
391
392    /** pop and store on to self as current token tuple */
393    fn store(&mut self) {
394        self.current_index += 1;
395        (self.current, self.current_location) = match self.iterator.next() {
396            Some(Ok(t)) => (Ok(t.0), t.1),
397            Some(Err(e)) => {
398                // self.error_syntax(e.code, e.location);
399                let l = e.location;
400                (Err(e), l)
401            }
402            None => (Ok(Token::EOF), (0, 0)),
403        };
404    }
405
406    /** take by value and gain ownership of the currently stored token */
407    fn copy_store(&mut self) -> Result<Token, ErrorTuple> {
408        // std::mem::replace(&mut self.current, Ok(Token::Nil))
409        self.current.clone()
410    }
411
412    /** take current, replace with next. a true pop*/
413    fn store_and_return(&mut self) -> Result<Token, ErrorTuple> {
414        self.current_index += 1;
415        let (r, l) = match self.iterator.next() {
416            Some(Ok(t)) => (Ok(t.0), t.1),
417            Some(Err(e)) => {
418                // self.error_syntax(e.code, e.location);
419                let l = e.location;
420                (Err(e), l)
421            }
422            None => (Ok(Token::EOF), (0, 0)),
423        };
424
425        self.current_location = l;
426        std::mem::replace(&mut self.current, r)
427    }
428
429    /** return the current token result */
430    fn get_current(&self) -> Result<&Token, ErrorTuple> {
431        match &self.current {
432            Ok(t) => {
433                devout!("get_current {}", t);
434                Ok(t)
435            }
436            Err(e) => Err(e.clone()),
437        }
438    }
439
440    /** only use after peek */
441    // pub fn eat_out(&mut self) -> TokenResult {
442    //     self.current_index += 1;
443    //     self.iterator.next().unwrap()
444    // }
445
446    /** return the peeked token result */
447    fn peek(&mut self) -> Result<&Token, ErrorTuple> {
448        match self.iterator.peek() {
449            Some(Ok(t)) => {
450                devout!("peek {}", t.0);
451                Ok(&t.0)
452            }
453            Some(Err(e)) => {
454                // self.error_syntax(e.code, e.location);
455                devout!("peek err {}", e.code);
456                let l = e.location;
457                Err(ErrorTuple {
458                    code: e.code.clone(),
459                    location: l,
460                })
461            }
462            None => Ok(&Token::EOF),
463        }
464    }
465
466    /** return the peeked token tuple (token+location) result */
467    fn peek_result(&mut self) -> &TokenResult {
468        #[cfg(feature = "dev-out")]
469        match self.iterator.peek() {
470            Some(r) => {
471                match r {
472                    Ok(t) => {
473                        println!("peek_res {}", t.0);
474                    }
475                    Err(e) => {
476                        println!("peek_res err {}", e.code);
477                    }
478                }
479                r
480            }
481            None => &Ok((Token::EOF, (0, 0))),
482        }
483        #[cfg(not(feature = "dev-out"))]
484        match self.iterator.peek() {
485            Some(r) => r,
486            None => &Ok((Token::EOF, (0, 0))),
487        }
488    }
489
490    /** emit op code at token location */
491    fn emit(&mut self, op: OpCode, location: Location) {
492        #[cfg(feature = "dev-out")]
493        {
494            println!("emit ... {}", op);
495            // self.chunk.print_chunk();
496        }
497        self.write_code(op, location);
498    }
499
500    /** emit op code at current token location */
501    fn emit_at(&mut self, op: OpCode) {
502        #[cfg(feature = "dev-out")]
503        {
504            println!("emit_at ...{}", op);
505            // self.chunk.print_chunk()
506        }
507        self.write_code(op, self.current_location);
508    }
509
510    /** emit op code at current token location and return op index */
511    fn emit_index(&mut self, op: OpCode) -> usize {
512        #[cfg(feature = "dev-out")]
513        {
514            println!("emit_index ... {}", op);
515            // frame.chunk.print_chunk()
516        }
517        self.write_code(op, self.current_location)
518    }
519
520    /** patch the op code that specified index */
521    fn patch(&mut self, offset: usize) -> Catch {
522        let jump = self.get_chunk().code.len() - offset - 1;
523        if jump > u16::MAX as usize {
524            self.error_at(SiltError::TooManyOperations);
525        }
526        // self.chunk.code[offset] = ((jump >> 8) & 0xff) as u8;
527        // self.chunk.code[offset + 1] = (jump & 0xff) as u8;
528        match self.get_chunk().code[offset] {
529            OpCode::GOTO_IF_FALSE(_) => {
530                self.get_chunk_mut().code[offset] = OpCode::GOTO_IF_FALSE(jump as u16)
531            }
532            OpCode::GOTO_IF_TRUE(_) => {
533                self.get_chunk_mut().code[offset] = OpCode::GOTO_IF_TRUE(jump as u16)
534            }
535            OpCode::POP_AND_GOTO_IF_FALSE(_) => {
536                self.get_chunk_mut().code[offset] = OpCode::POP_AND_GOTO_IF_FALSE(jump as u16)
537            }
538            OpCode::FORWARD(_) => self.get_chunk_mut().code[offset] = OpCode::FORWARD(jump as u16),
539            OpCode::REWIND(_) => self.get_chunk_mut().code[offset] = OpCode::REWIND(jump as u16),
540            OpCode::FOR_NUMERIC(_) => {
541                self.get_chunk_mut().code[offset] = OpCode::FOR_NUMERIC(jump as u16)
542            }
543            _ => {
544                return Err(self.error_at(SiltError::ChunkCorrupt));
545            }
546        }
547        Ok(())
548    }
549
550    fn emit_rewind(&mut self, start: usize) {
551        // we base the jump off of the index we'll be at one we've written the rewind op below
552        let jump = (self.get_chunk_size() + 1) - start;
553        if jump > u16::MAX as usize {
554            self.error_at(SiltError::TooManyOperations);
555        }
556        self.write_code(OpCode::REWIND(jump as u16), self.current_location);
557    }
558
559    fn set_label(&mut self, label: String) {
560        self.labels.insert(label, self.get_chunk_size());
561    }
562
563    fn identifer_constant(&mut self, ident: Box<String>) -> u8 {
564        self.write_identifier(ident) as u8
565    }
566
567    /** write to constant table  */
568    fn write_constant(&mut self, value: Value) -> u8 {
569        self.body.chunk.write_constant(value) as u8
570    }
571
572    /** write to constant table and emit the op code at location */
573    fn constant(&mut self, value: Value, location: Location) {
574        let constant = self.write_constant(value);
575        self.emit(OpCode::CONSTANT { constant }, location);
576    }
577
578    /** write to constant table and emit the op code at the current location */
579    fn constant_at(&mut self, value: Value) {
580        self.constant(value, self.current_location);
581    }
582
583    /** write identifier to constant table, remove duplicates, and emit code */
584    fn emit_identifer_constant_at(&mut self, ident: Box<String>) {
585        let constant = self.write_identifier(ident) as u8;
586        self.emit(OpCode::CONSTANT { constant }, self.current_location);
587    }
588
589    fn is_end(&mut self) -> bool {
590        match self.iterator.peek() {
591            None => true,
592            _ => false,
593        }
594    }
595
596    /** replaces the conents of func with the compilers body */
597    fn swap_function(&mut self, mut func: &mut FunctionObject) {
598        swap(&mut self.body, func);
599        // func
600    }
601
602    fn get_rule(token: &Token) -> ParseRule {
603        // ParseRule {
604        //     prefix: Some(|self| self.grouping()),
605        //     infix: None,
606        //     precedence: Precedence::None,
607        // },
608        // let func: dyn FnMut(&mut Compiler<'_>) = &Self::grouping;
609        // store reference of callable function within self
610        // let func: &fn(&'a mut Compiler<'_>) = &Self::grouping as &fn(&'a mut Compiler<'_>);
611        // let func: fn(&mut Compiler) = unary;
612
613        match token {
614            Token::OpenParen => rule!(grouping, call, Call),
615            Token::OpenBrace => rule!(tabulate, call_table, None),
616            Token::Assign => rule!(void, void, None),
617            Token::Op(op) => match op {
618                Operator::Sub => rule!(unary, binary, Term),
619                Operator::Add => rule!(void, binary, Term),
620                Operator::Multiply => rule!(void, binary, Factor),
621                Operator::Divide => rule!(void, binary, Factor),
622                Operator::Not => rule!(unary, void, None),
623                Operator::NotEqual => rule!(void, binary, Equality),
624                Operator::Equal => rule!(void, binary, Equality),
625                Operator::Less => rule!(void, binary, Comparison),
626                Operator::LessEqual => rule!(void, binary, Comparison),
627                Operator::Greater => rule!(void, binary, Comparison),
628                Operator::GreaterEqual => rule!(void, binary, Comparison),
629                Operator::Concat => rule!(void, concat, Concat),
630                Operator::And => rule!(void, and, And),
631                Operator::Or => rule!(void, or, Or),
632                Operator::Length => rule!(unary, void, None),
633                _ => rule!(void, void, None),
634            },
635            Token::Identifier(_) => rule!(variable, void, None),
636            // Token::OpenBracket => rule!(void, indexer, Call),
637            Token::Integer(_) => rule!(integer, void, None),
638            Token::Number(_) => rule!(number, void, None),
639            Token::StringLiteral(_) => rule!(string, call_string, None),
640            Token::Nil => rule!(literal, void, None),
641            Token::True => rule!(literal, void, None),
642            Token::False => rule!(literal, void, None),
643            // Token::Bang => rule!(unary, void, None),
644            _ => rule!(void, void, None),
645        }
646    }
647
648    pub fn compile(&mut self, source: String) -> FunctionObject {
649        #[cfg(feature = "dev-out")]
650        {
651            let lexer = Lexer::new(source.to_owned());
652            lexer.for_each(|r| match r {
653                Ok(t) => {
654                    println!("token {}", t.0);
655                }
656                Err(e) => println!("err {}", e),
657            });
658        }
659        let lexer = Lexer::new(source.to_owned());
660        self.iterator = lexer.peekable();
661        while !self.is_end() {
662            match declaration(self) {
663                Ok(()) => {}
664                Err(e) => {
665                    self.push_error(e);
666                    self.synchronize();
667                }
668            }
669        }
670
671        self.emit(OpCode::RETURN, (0, 0));
672        take(&mut self.body)
673    }
674
675    fn synchronize(&mut self) {
676        // TODO should we unwind or just dump it all?
677        // self.eat();
678        // while !self.is_end() {
679        //     match self.get_current() {
680        //         Ok(Token::Print) => return,
681        //         _ => {}
682        //     }
683        //     self.eat();
684        // }
685    }
686
687    fn parse_precedence(&mut self, precedence: Precedence, skip_step: bool) -> Catch {
688        if !skip_step {
689            self.store();
690        }
691        // self.store(); // MARK with store first it works for normal statements, but it breaks for incomplete expressions that are meant to pop off
692        // Basically the integer we just saw is dropped off when we reach here because of store
693        let t = self.get_current()?;
694        let loc = self.current_location;
695
696        devout!("check rule for token {}", t);
697        let rule = Self::get_rule(&t);
698        // #[cfg(feature = "dev-out")]
699        devout!(
700            "target precedence:  {}, current precedence: {}",
701            precedence,
702            rule.precedence,
703        );
704        // if (rule.prefix) != Self::void { // TODO bubble error up if no prefix, call invalid func to bubble?
705        let can_assign = precedence <= Precedence::Assignment;
706        (rule.prefix)(self, can_assign)?;
707
708        loop {
709            let c = self.peek_result();
710            let rule = match c {
711                Ok((Token::EOF, _)) => break,
712                Ok((t, _)) => Self::get_rule(t),
713                Err(e) => {
714                    return Err(e.clone());
715                }
716            };
717            devout!(
718                "loop target precedence for :  {}, current precedence for  : {}",
719                precedence,
720                rule.precedence
721            );
722            if precedence > rule.precedence {
723                break;
724            }
725            self.store();
726            (rule.infix)(self, false)?;
727        }
728
729        // TODO test this with `local b="b" sprint b`
730        if can_assign
731            && if let Token::Assign = self.peek()? {
732                true
733            } else {
734                false
735            }
736        {
737            let res = self.peek()?.clone();
738            return Err(self.error_at(SiltError::InvalidAssignment(res)));
739        }
740
741        // if skip_step {
742        //     self.store();
743        // }
744        Ok(())
745    }
746}
747
748fn declaration(this: &mut Compiler) -> Catch {
749    devout!("----------------------------");
750    devnote!(this "declaration");
751
752    let t = this.peek()?;
753    match t {
754        Token::Local => declaration_keyword(this, true, false)?,
755        Token::Global => declaration_keyword(this, false, false)?,
756        Token::Function => {
757            this.eat();
758            define_function(this, true, None)?;
759        }
760        _ => statement(this)?,
761    }
762    Ok(())
763}
764
765fn declaration_keyword(this: &mut Compiler, local: bool, already_function: bool) -> Catch {
766    devnote!(this "declaration_keyword");
767    this.eat();
768    let (res, location) = this.pop();
769    match res? {
770        Token::Identifier(ident) => {
771            if this.scope_depth > 0 && local {
772                //local
773                //TODO should we warn? redefine_behavior(this,ident)?
774                add_local(this, ident)?;
775                typing(this, None)?;
776            } else {
777                let ident = this.identifer_constant(ident); //(self.global.to_register(&ident), 0);
778                typing(this, Some((ident, location)))?;
779            }
780        }
781        Token::Function => {
782            if !already_function {
783                define_function(this, local, None)?;
784            } else {
785                return Err(this.error_at(SiltError::ExpectedLocalIdentifier));
786                // Statement::InvalidStatement
787            }
788        }
789        // _ => {
790        //     self.error(SiltError::ExpectedLocalIdentifier);
791        //     Statement::InvalidStatement
792        // }
793        _ => todo!(),
794    }
795    Ok(())
796}
797
798fn declaration_scope(
799    this: &mut Compiler,
800    ident: Box<String>,
801    local: bool,
802    location: Location,
803) -> Catch {
804    if this.scope_depth > 0 && local {
805        //local
806        //TODO should we warn? redefine_behavior(this,ident)?
807        add_local(this, ident)?;
808        typing(this, None)?;
809    } else {
810        let ident = this.identifer_constant(ident);
811        typing(this, Some((ident, location)))?;
812    }
813    Ok(())
814}
815
816// TODO Warning?
817// fn redefine_behavior(this: &mut Compiler, ident: Box<String>) -> Catch {
818//     // TODO depth !=-1 ?
819//     for l in this.locals.iter().rev() {
820//         if l.depth != -1 && l.depth < this.scope_depth {
821//             return Ok(());
822//         } else {
823//             if l.ident == ident {
824//                 return Err(this.error_at(SiltError::AlreadyDefined(ident)));
825//             }
826//         }
827//     }
828//     Ok(())
829// }
830
831/** Store location as a local to resolve getters with, the index pointing to the stack */
832fn add_local(this: &mut Compiler, ident: Box<String>) -> Result<u8, ErrorTuple> {
833    _add_local(this, Some(ident))
834}
835
836/** Store location on the stack with a placeholder that cannot be resolved as a variable, only reserves for operations */
837fn add_local_placeholder(this: &mut Compiler) -> Result<u8, ErrorTuple> {
838    _add_local(this, None)
839}
840
841fn _add_local(this: &mut Compiler, ident: Option<Box<String>>) -> Result<u8, ErrorTuple> {
842    devnote!(this "add_local");
843    // let offset = if this.functional_depth > 0 {
844    //     this.local_functional_offset[this.functional_depth - 1]
845    // } else {
846    //     0
847    // };
848    let i = this.local_count; //- offset;
849    if i == 255 {
850        return Err(this.error_at(SiltError::TooManyLocals));
851    }
852    this.locals.push(Local {
853        ident,
854        depth: this.scope_depth,
855        functional_depth: this.functional_depth,
856        is_captured: false,
857    });
858    this.local_count += 1;
859    // let offset = if this.functional_depth > 0 {
860    //     this.local_functional_offset[this.functional_depth - 1]
861    // } else {
862    //     0
863    // };
864    Ok(i as u8)
865}
866
867// /** Remove a single reserved local */
868// fn pop_local(this: &mut Compiler) {
869//     devnote!(this "pop_local");
870//     this.local_count -= 1;
871//     this.locals.pop();
872// }
873
874fn resolve_local(this: &mut Compiler, ident: &Box<String>) -> Option<(u8, bool)> {
875    devnote!(this "resolve_local");
876    for (i, l) in this.locals.iter_mut().enumerate().rev() {
877        if let Some(local_ident) = &l.ident {
878            if local_ident == ident {
879                #[cfg(feature = "dev-out")]
880                println!("matched local {}->{} at {}", ident, local_ident, i);
881                let ident_byte = i as u8;
882
883                // first establish we're accessing a value by a closure, it exists outside this function
884                let is_upvalue = l.functional_depth < this.functional_depth;
885                return if is_upvalue {
886                    (*l).is_captured = true;
887                    let offset_ident = if l.functional_depth > 0 {
888                        let offset = this.local_functional_offset[l.functional_depth - 1];
889                        i - offset
890                    } else {
891                        i
892                    } as u8;
893                    // MARK we're passing in a target depth of 0, huh?? that's global isnt it? our upvals dont exist there
894                    Some((
895                        resolve_upvalue(
896                            &mut this.up_values,
897                            ident_byte,
898                            offset_ident,
899                            this.functional_depth,
900                            l.functional_depth,
901                        ),
902                        is_upvalue,
903                    ))
904                } else {
905                    let offset_ident = if this.functional_depth > 0 {
906                        let offset = this.local_functional_offset[this.functional_depth - 1];
907                        i - offset
908                    } else {
909                        i
910                    } as u8;
911                    Some((offset_ident as u8, false))
912                };
913            }
914        }
915    }
916    None
917}
918
919/** check if upvalue is registered at this closest level and decend down until reach destination, registiner upvalues as we go if not already*/
920fn resolve_upvalue(
921    up_values: &mut Vec<Vec<UpLocal>>,
922    ident: u8,
923    scoped_ident: u8,
924    level: usize,
925    target: usize,
926) -> u8 {
927    let m = &mut up_values[level];
928    for (u, i) in m.iter().enumerate() {
929        if i.universal_ident == ident {
930            return u as u8;
931        }
932    }
933    // if level is equal to or no greater than target +1
934    if level <= target + 1 {
935        m.push(UpLocal {
936            ident: scoped_ident,
937            universal_ident: ident,
938            neighboring: true,
939        });
940        (m.len() - 1) as u8
941    } else {
942        // drop(m);
943        let higher = resolve_upvalue(up_values, ident, scoped_ident, level - 1, target);
944        let m = &mut up_values[level];
945        m.push(UpLocal {
946            ident: higher,
947            universal_ident: ident,
948            neighboring: false,
949        });
950        (m.len() - 1) as u8
951        // resolve_upvalue(up_values, ident, level - 1, target)
952    }
953}
954
955// fn resolve_upvalue(this: &mut Compiler, ident: &Box<String>) -> Result<Option<u8>, ErrorTuple> {
956//     devnote!(this "resolve_upvalue");
957//     if this.scope_depth == 0 {
958//         return Ok(None);
959//     }
960//     if let Some(local) = resolve_local(this, ident)? {
961//         return Ok(Some(add_upvalue(this, local, true)?));
962//     }
963//     if let Some(upvalue) = this.body.upvalues.iter().position(|u| u.0 == ident) {
964//         return Ok(Some(upvalue as u8));
965//     }
966//     Ok(None)
967// }
968
969fn typing(this: &mut Compiler, ident_tuple: Option<(Ident, Location)>) -> Catch {
970    devnote!(this "typing");
971    if let Token::Colon = this.peek()? {
972        // typing or self calling
973        this.eat();
974        this.store();
975        let t = this.get_current()?;
976        if let Token::ColonIdentifier(target) = t {
977            // method or type name
978            // if let Some(&Token::OpenParen) = self.peek() {
979            //     // self call
980
981            //     Statement::InvalidStatement
982            // } else {
983            //     // typing
984            //     // return self.assign(self.peek(), ident);
985            //     Statement::InvalidStatement
986            // }
987            define_declaration(this, ident_tuple)?;
988        } else {
989            todo!("typing");
990            // self.error(SiltError::InvalidColonPlacement);
991            // Statement::InvalidStatement
992        }
993    } else {
994        define_declaration(this, ident_tuple)?;
995    }
996    Ok(())
997}
998
999fn define_declaration(this: &mut Compiler, ident_tuple: Option<(Ident, Location)>) -> Catch {
1000    devnote!(this "define_declaration");
1001    this.store();
1002    let t = this.get_current()?;
1003    match t {
1004        Token::Assign => {
1005            expression(this, false)?;
1006        }
1007        // we can't increment what doesn't exist yet, like what are you even doing?
1008        Token::AddAssign
1009        | Token::SubAssign
1010        | Token::MultiplyAssign
1011        | Token::DivideAssign
1012        | Token::ModulusAssign => {
1013            // let tt = t.unwrap().clone(); // TODO
1014            // self.error(SiltError::InvalidAssignment(tt));
1015            // Statement::InvalidStatement
1016            todo!()
1017        }
1018        _ => this.emit_at(OpCode::NIL), // TODO are more then just declarations hitting this syntactic sugar?
1019    }
1020    define_variable(this, ident_tuple)?;
1021    Ok(())
1022}
1023
1024fn define_variable(this: &mut Compiler, ident: Option<(Ident, Location)>) -> Catch {
1025    devnote!(this "define_variable");
1026
1027    if let Some(ident) = ident {
1028        this.emit(OpCode::DEFINE_GLOBAL { constant: ident.0 }, ident.1);
1029    }
1030    Ok(())
1031}
1032
1033fn define_function(this: &mut Compiler, local: bool, pre_ident: Option<usize>) -> Catch {
1034    let (ident, location) = if let &Token::Identifier(_) = this.peek()? {
1035        let (res, location) = this.pop();
1036        if let Token::Identifier(ident) = res? {
1037            (ident, location)
1038        } else {
1039            unreachable!()
1040        }
1041    } else {
1042        (Box::new("anonymous".to_string()), this.current_location)
1043    };
1044
1045    let ident_clone = *ident.clone();
1046    let global_ident = if this.scope_depth > 0 && local {
1047        //local
1048        //TODO should we warn? redefine_behavior(this,ident)?
1049        add_local(this, ident)?;
1050        None
1051    } else {
1052        let ident = Some((this.identifer_constant(ident), location));
1053        ident
1054    };
1055
1056    build_function(this, ident_clone, global_ident, false, false)?;
1057
1058    Ok(())
1059}
1060
1061/** builds function, implicit return specifices whether a nil is return or the last value popped */
1062fn build_function(
1063    this: &mut Compiler,
1064    ident: String,
1065    global_ident: Option<(u8, Location)>,
1066    is_script: bool,
1067    implicit_return: bool,
1068) -> Catch {
1069    // TODO this function could be called called rercursivelly due to the recursive decent nature of the parser, we should add a check to make sure we don't overflow the stack
1070    devnote!(this "build_function");
1071    let mut sidelined_func = FunctionObject::new(Some(ident), is_script);
1072    this.swap_function(&mut sidelined_func);
1073    begin_scope(this);
1074    begin_functional_scope(this);
1075    expect_token!(this OpenParen);
1076    let mut arity = 0;
1077    if let Token::Identifier(_) = this.peek()? {
1078        arity += 1;
1079        build_param(this)?;
1080
1081        while let Token::Comma = this.peek()? {
1082            this.eat();
1083            arity += 1;
1084            if arity > 255 {
1085                // TODO we should use an arity value on the function object but let's make it only exist on compile time
1086                return Err(this.error_at(SiltError::TooManyParameters));
1087            }
1088            build_param(this)?;
1089        }
1090    }
1091
1092    block(this)?;
1093    if let &OpCode::RETURN = this.read_last_code() {
1094    } else {
1095        // TODO if last was semicolon we also push a nil
1096        if !implicit_return {
1097            this.emit_at(OpCode::NIL);
1098        }
1099        this.emit_at(OpCode::RETURN);
1100    }
1101
1102    // TODO why do we need to eat again? This prevents an expression_statement of "End" being called but block should have eaten it?
1103    // if let Token::End = this.peek()? {
1104    //     this.eat();
1105    // }
1106
1107    end_scope(this, true);
1108    let upvals = end_functional_scope(this);
1109    // When we're done compiling the function object we drop the current body function back in and push the compiled func as a constant within that body
1110    this.swap_function(&mut sidelined_func);
1111    sidelined_func.upvalue_count = upvals.len() as u8;
1112    let func_value = Value::Function(Rc::new(sidelined_func));
1113    if true {
1114        // need closure
1115        let constant = this.body.chunk.write_constant(func_value) as u8;
1116        this.emit_at(OpCode::CLOSURE { constant });
1117        // emit upvalues
1118
1119        for val in upvals.iter() {
1120            // TODO is it worth specifying difference between first function enclosure from higher functional enclosure?
1121            this.emit_at(OpCode::REGISTER_UPVALUE {
1122                index: val.ident,
1123                neighboring: val.neighboring,
1124            });
1125        }
1126    } else {
1127        // no closure needed
1128        this.constant_at(func_value);
1129    }
1130    define_variable(this, global_ident)?;
1131
1132    Ok(())
1133}
1134
1135fn build_param(this: &mut Compiler) -> Catch {
1136    let (res, _) = this.pop();
1137    match res? {
1138        Token::Identifier(ident) => {
1139            add_local(this, ident)?;
1140        }
1141        _ => {
1142            return Err(this.error_at(SiltError::ExpectedLocalIdentifier));
1143        }
1144    }
1145    Ok(())
1146}
1147
1148fn statement(this: &mut Compiler) -> Catch {
1149    devnote!(this "statement");
1150    match this.peek()? {
1151        Token::Print => print(this)?,
1152        Token::If => if_statement(this)?,
1153        Token::Do => {
1154            this.eat();
1155            begin_scope(this);
1156            block(this)?;
1157            end_scope(this, false);
1158        }
1159        Token::While => while_statement(this)?,
1160        Token::For => for_statement(this)?,
1161        Token::Return => return_statement(this)?,
1162        // Token::OpenBrace => block(this),
1163        Token::ColonColon => set_goto_label(this)?,
1164        Token::Goto => goto_statement(this)?,
1165        Token::SemiColon => {
1166            this.eat();
1167            // TODO ???
1168        }
1169        // Token::End => {
1170        //     // this.eat();
1171        //     // TODO ???
1172        // }
1173        _ => expression_statement(this)?,
1174    }
1175    Ok(())
1176}
1177
1178fn block(this: &mut Compiler) -> Catch {
1179    devnote!(this "block");
1180    build_block_until_then_eat!(this, End);
1181
1182    Ok(())
1183}
1184
1185/** lower scope depth */
1186fn begin_scope(this: &mut Compiler) {
1187    this.scope_depth += 1;
1188}
1189
1190/** Descend into a function's scope and start a new upvalue vec representing required values a level above us */
1191fn begin_functional_scope(this: &mut Compiler) {
1192    this.functional_depth += 1;
1193    this.up_values.push(vec![]);
1194    let cumulative: usize = this.local_functional_offset.iter().sum();
1195    this.local_functional_offset
1196        .push(this.local_count + cumulative - 1);
1197    this.local_offset.push(this.local_count);
1198    this.local_count = 1;
1199}
1200
1201/** raise scope depth and dump lowest locals off the imaginary stack */
1202fn end_scope(this: &mut Compiler, skip_code: bool) {
1203    this.scope_depth -= 1;
1204
1205    let mut last_was_pop = true;
1206    let mut count = 0;
1207    let mut v = vec![];
1208    while !this.locals.is_empty() && this.locals.last().unwrap().depth > this.scope_depth {
1209        let l = this.locals.pop().unwrap();
1210        this.local_count -= 1;
1211        if l.is_captured {
1212            if last_was_pop {
1213                v.push(count);
1214                count = 0;
1215            }
1216            last_was_pop = false;
1217            count += 1;
1218        } else {
1219            if !last_was_pop {
1220                v.push(count);
1221                count = 0;
1222            }
1223            last_was_pop = true;
1224            count += 1;
1225        }
1226    }
1227    if count > 0 {
1228        v.push(count);
1229    }
1230    // if we're not dealing with upvalues and we're skipping code due to functional scope our stack will get moved off anyway
1231    if skip_code {
1232        //&& v.len() <= 1 {
1233        return;
1234    }
1235
1236    // index 0 is always OP_POPS but could be count of 0 if the first local is captured. Otherwise we can safely stagger even as pop, odds as close
1237    v.iter().enumerate().for_each(|(i, c)| {
1238        if i % 2 == 0 {
1239            this.emit_at(OpCode::POPS(*c));
1240        } else {
1241            this.emit_at(OpCode::CLOSE_UPVALUES(*c));
1242        }
1243    });
1244}
1245
1246/** raise functional depth */
1247fn end_functional_scope(this: &mut Compiler) -> Vec<UpLocal> {
1248    this.functional_depth -= 1;
1249    this.local_functional_offset.pop();
1250    this.local_count = match this.local_offset.pop() {
1251        Some(v) => v,
1252        None => 1,
1253    };
1254
1255    this.up_values.pop().unwrap()
1256}
1257
1258fn if_statement(this: &mut Compiler) -> Catch {
1259    devnote!(this "if_statement");
1260    this.eat();
1261    expression(this, false)?;
1262    expect_token!(this Then);
1263    let skip_if = this.emit_index(OpCode::POP_AND_GOTO_IF_FALSE(0));
1264    scope_and_block_until!(this, End | Else | ElseIf);
1265    // this.emit_at(OpCode::POP); // pop the if compare again as we skipped the pop from before
1266    match this.peek()? {
1267        Token::Else => {
1268            this.eat();
1269            let skip_else = this.emit_index(OpCode::FORWARD(0));
1270            this.patch(skip_if)?; // patch to fo AFTER the forward so we actually run the else block
1271            scope_and_block_until!(this, End);
1272            this.patch(skip_else)?;
1273            expect_token!(this End);
1274        }
1275        Token::ElseIf => {
1276            this.eat();
1277            // this.emit_at(OpCode::POP);
1278            this.patch(skip_if)?;
1279            if_statement(this)?;
1280        }
1281        _ => {
1282            this.patch(skip_if)?;
1283        }
1284    }
1285    Ok(())
1286}
1287
1288fn while_statement(this: &mut Compiler) -> Catch {
1289    devnote!(this "while_statement");
1290    this.eat();
1291    let loop_start = this.get_chunk_size();
1292    expression(this, false)?;
1293    expect_token!(this Do);
1294    let exit_jump = this.emit_index(OpCode::POP_AND_GOTO_IF_FALSE(0));
1295    build_block_until_then_eat!(this, End);
1296    this.emit_rewind(loop_start);
1297    this.patch(exit_jump)?;
1298    Ok(())
1299}
1300
1301/**
1302 * Put iterator, start, and either step expression or 1 constant on to stack.
1303 * Evaluate if iterator is less than or equal to end value, if not run block and push iterator to that block's stack
1304 * At end of block increment iterator by step value and rewind
1305 * Re-evaluate and if iterator is greater than end value, forward to immediately after end of block
1306 */
1307fn for_statement(this: &mut Compiler) -> Catch {
1308    devnote!(this "for_statement");
1309    this.eat();
1310    let pair = this.pop();
1311    let t = pair.0?;
1312    if let Token::Identifier(ident) = t {
1313        // let offset = this.local_functional_offset[this.functional_depth - 1];
1314        let iterator = add_local_placeholder(this)?; // reserve iterator with placeholder
1315        expect_token!(this Assign);
1316        add_local_placeholder(this)?; // reserve end value with placeholder
1317        add_local_placeholder(this)?; // reserve step value with placeholder
1318        expression(this, false)?; // expression for iterator
1319        expect_token!(this Comma);
1320        expression(this, false)?; // expression for end value
1321
1322        // let exit_jump = this.emit_index(OpCode::GOTO_IF_FALSE(0));
1323        // this.emit_at(OpCode::POP);
1324        // either we have an expression for the step or we set it to 1i
1325        if let Token::Comma = this.peek()? {
1326            this.eat();
1327            expression(this, false)?;
1328        } else {
1329            this.constant_at(Value::Integer(1))
1330        };
1331        let for_start = this.emit_index(OpCode::FOR_NUMERIC(0));
1332        // this.emit_at(OpCode::GET_LOCAL { index: iterator });
1333        // let loop_start = this.get_chunk_size();
1334        // compare iterator to end value
1335        // this.emit_at(OpCode::GET_LOCAL { index: comparison });
1336        // this.emit_at(OpCode::EQUAL);
1337        // let exit_jump = this.emit_index(OpCode::GOTO_IF_TRUE(0));
1338        // this.emit_at(OpCode::POP);
1339        expect_token!(this Do);
1340        begin_scope(this);
1341        add_local(this, ident)?; // we add the local inside the scope which was actually added on by the for opcode already
1342        build_block_until_then_eat!(this, End);
1343        end_scope(this, false);
1344
1345        this.emit_at(OpCode::INCREMENT { index: iterator });
1346        this.emit_rewind(for_start);
1347        this.patch(for_start)?;
1348        this.force_stack_pop(3);
1349        Ok(())
1350    } else {
1351        Err(this.error_at(SiltError::ExpectedLocalIdentifier))
1352    }
1353}
1354
1355/**
1356 * We run closure and if value is not nil we set that to iterator and push onto blocks scope, when we hit end we rewind and re-eval
1357 * If the for's iterator is nil we forward to end of do block and pop off the iterator
1358 */
1359fn generic_for_statement() {}
1360
1361fn return_statement(this: &mut Compiler) -> Catch {
1362    devnote!(this "return_statement");
1363    this.eat();
1364    if let Token::End | Token::Else | Token::ElseIf | Token::SemiColon | Token::EOF = this.peek()? {
1365        this.emit_at(OpCode::NIL);
1366    } else {
1367        expression(this, false)?;
1368    }
1369    this.emit_at(OpCode::RETURN);
1370    Ok(())
1371}
1372
1373fn set_goto_label(this: &mut Compiler) -> Catch {
1374    devnote!(this "goto_label");
1375    this.eat();
1376    let token = this.pop().0?;
1377    if let Token::Identifier(ident) = token {
1378        this.labels.insert(*ident, this.get_chunk_size());
1379    } else {
1380        return Err(this.error_at(SiltError::ExpectedLabelIdentifier));
1381    }
1382    Ok(())
1383}
1384
1385fn goto_statement(this: &mut Compiler) -> Catch {
1386    devnote!(this "goto_statement");
1387    this.eat();
1388    let token = this.pop().0?;
1389    if let Token::Identifier(ident) = token {
1390        resolve_goto(this, &*ident, this.get_chunk_size(), None)?;
1391        // match this.labels.get(ident) {
1392        //     Some(i) => {
1393        //         let c = this.chunk.code.len();
1394        //         let o = *i;
1395        //         if c > o {
1396        //             let offset = c - o;
1397        //             if offset > u16::MAX as usize {
1398        //                 return Err(this.error_at(SiltError::TooManyOperations));
1399        //             }
1400        //             this.emit_at(OpCode::REWIND(offset as u16));
1401        //         } else {
1402        //             let offset = o - c;
1403        //             if offset > u16::MAX as usize {
1404        //                 return Err(this.error_at(SiltError::TooManyOperations));
1405        //             }
1406        //             this.emit_at(OpCode::FORWARD(offset as u16));
1407        //         }
1408        //     }
1409        //     None => {
1410        //         let index = this.emit_index(OpCode::FORWARD(0));
1411        //         this.pending_gotos.push((ident, index));
1412        //         // this.labels.insert(*ident, index);
1413        //     }
1414        // }
1415    } else {
1416        return Err(this.error_at(SiltError::ExpectedGotoIdentifier));
1417    }
1418
1419    // n end_scope(this: &mut Compiler) {
1420    //     this.scope_depth -= 1;
1421    //     let mut i = 0;
1422    //     while !this.locals.is_empty() && this.locals.last().unwrap().depth > this.scope_depth {
1423    //         this.locals.pop();
1424    //         i += 1;
1425    //     }
1426    //     this.emit_at(OpCode::POPN(i));
1427    // }
1428
1429    Ok(())
1430}
1431
1432fn resolve_goto(
1433    this: &mut Compiler,
1434    ident: &str,
1435    op_count: usize,
1436    replace: Option<(usize, Location)>,
1437) -> Catch {
1438    match this.labels.get(ident) {
1439        Some(i) => {
1440            let c = op_count;
1441            let o = *i;
1442            let code = if c > o {
1443                let offset = c - o;
1444                if offset > u16::MAX as usize {
1445                    return Err(this.error_at(SiltError::TooManyOperations));
1446                }
1447                OpCode::REWIND(offset as u16)
1448            } else {
1449                let offset = o - c;
1450                if offset > u16::MAX as usize {
1451                    return Err(this.error_at(SiltError::TooManyOperations));
1452                }
1453                OpCode::FORWARD(offset as u16)
1454            };
1455
1456            match replace {
1457                Some((i, _)) => {
1458                    this.get_chunk_mut().code[i] = code;
1459                }
1460                None => {
1461                    this.emit_at(code);
1462                }
1463            }
1464        }
1465        None => match replace {
1466            Some((i, location)) => {
1467                return Err(this.error_syntax(SiltError::UndefinedLabel(ident.to_owned()), location))
1468            }
1469            None => {
1470                let index = this.emit_index(OpCode::FORWARD(0));
1471                this.pending_gotos
1472                    .push((ident.to_owned(), index, this.current_location));
1473            } // this.labels.insert(*ident, index);
1474        },
1475    };
1476    Ok(())
1477}
1478
1479fn final_resolve_goto(this: &mut Compiler) {
1480    this.pending_gotos
1481        .iter()
1482        .for_each(|(ident, index, location)| {});
1483}
1484
1485fn goto_scope_skip(this: &mut Compiler) {
1486    if this.locals.is_empty() {
1487        return;
1488    }
1489    let mut i = 0;
1490    this.locals
1491        .iter()
1492        .rev()
1493        .take_while(|l| l.depth > this.scope_depth)
1494        .for_each(|_| {
1495            i += 1;
1496        });
1497
1498    this.emit_at(OpCode::POPS(i));
1499}
1500
1501fn expression(this: &mut Compiler, skip_step: bool) -> Catch {
1502    devnote!(this "expression");
1503    this.parse_precedence(Precedence::Assignment, skip_step)?;
1504    Ok(())
1505}
1506
1507fn next_expression(this: &mut Compiler) -> Catch {
1508    devnote!(this "next_expression");
1509    this.eat();
1510    expression(this, false)?;
1511    Ok(())
1512}
1513
1514fn expression_statement(this: &mut Compiler) -> Catch {
1515    devnote!(this "expression_statement");
1516    expression(this, false)?;
1517    if this.override_pop {
1518        this.override_pop = false;
1519    } else {
1520        this.emit_at(OpCode::POP);
1521    }
1522    devnote!(this "expression_statement end");
1523    Ok(())
1524}
1525
1526fn variable(this: &mut Compiler, can_assign: bool) -> Catch {
1527    devnote!(this "variable");
1528    // let t = this.previous.clone();
1529    // let ident = if let Token::Identifier(ident) = t.0 {
1530    //     this.identifer_constant(ident)
1531    // } else {
1532    //     unreachable!()
1533    // };
1534    // if let Some(Ok((Token::Assign, _))) = this.peek() {
1535    //     this.advance();
1536    //     next_expression(this);
1537    //     this.emit(OpCode::DEFINE_GLOBAL { constant: ident }, t.1);
1538    // } else {
1539    //     this.emit(OpCode::LITERAL { dest: ident, literal: ident }, t.1);
1540    // }
1541
1542    named_variable(this, can_assign, false)?;
1543    Ok(())
1544}
1545
1546fn named_variable(this: &mut Compiler, can_assign: bool, mut local: bool) -> Catch {
1547    devnote!(this "named_variables");
1548    let t = this.copy_store()?;
1549
1550    // declare shortcut only valid if we're above scope 0 otherwise it's redundant
1551    // TODO should we send a warning that 0 scoped declares are redundant?
1552    if this.scope_depth > 0
1553        && if let Token::Op(Operator::ColonEquals) = this.peek()? {
1554            true
1555        } else {
1556            false
1557        }
1558    {
1559        if let Token::Identifier(ident) = t {
1560            // short declare
1561            add_local(this, ident)?;
1562            this.override_pop = true;
1563            this.eat();
1564            expression(this, false)?;
1565        } else {
1566            unreachable!()
1567        }
1568        return Ok(());
1569    }
1570
1571    //normal assigment
1572    let (setter, getter) = if let Token::Identifier(ident) = t {
1573        devout!("assigning to identifier: {}", ident);
1574        // TODO currently this mechanism searches the entire local stack to determine local and then up values,  ideally we check up values first once we raise out of the functional scope instead of continuing to walk the local stack, but this will work for now.
1575        match resolve_local(this, &ident) {
1576            Some((i, is_up)) => {
1577                if is_up {
1578                    (
1579                        OpCode::SET_UPVALUE { index: i },
1580                        OpCode::GET_UPVALUE { index: i },
1581                    )
1582                } else {
1583                    (
1584                        OpCode::SET_LOCAL { index: i },
1585                        OpCode::GET_LOCAL { index: i },
1586                    )
1587                }
1588            }
1589            None => {
1590                let ident = this.identifer_constant(ident);
1591                // add_upvalue(this, ident, this.scope_depth);
1592                (
1593                    OpCode::SET_GLOBAL { constant: ident },
1594                    OpCode::GET_GLOBAL { constant: ident },
1595                )
1596            }
1597        }
1598    } else {
1599        unreachable!()
1600    };
1601
1602    devout!("setter: {}, getter: {}", setter, getter);
1603
1604    /*
1605     * normally:
1606     * expression for value
1607     * set_var id
1608     *
1609     * with table:
1610     * push table ref onto stack
1611     * expression for index OR constant for index
1612     * repeat for each chained index and remember count
1613     * expression for value
1614     * set_table with depth = index count
1615     *
1616     *
1617     */
1618    match this.peek()? {
1619        Token::Assign => {
1620            if can_assign {
1621                this.eat();
1622                expression(this, false)?;
1623                this.emit_at(setter);
1624            } else {
1625                this.emit_at(getter);
1626            }
1627        }
1628        Token::OpenBracket | Token::Dot => {
1629            this.emit_at(getter);
1630            let count = table_indexer(this)? as u8;
1631            if let Token::Assign = this.peek()? {
1632                this.eat();
1633                expression(this, false)?;
1634                this.emit_at(OpCode::TABLE_SET { depth: count });
1635                // override statement end pop because instruction takes care of it
1636                this.override_pop = true;
1637            } else {
1638                this.emit_at(OpCode::TABLE_GET { depth: count });
1639            }
1640        }
1641        _ => this.emit_at(getter),
1642    }
1643
1644    // if can_assign
1645    //     && if let Token::Assign = this.peek()? {
1646    //         true
1647    //     } else {
1648    //         false
1649    //     }
1650    // {
1651    //     this.eat();
1652    //     expression(this, false)?;
1653    //     this.emit_at(setter);
1654    // } else {
1655    //     this.emit_at(getter);
1656    // }
1657
1658    // if let &Token::Assign = this.get_current()? {
1659    //     let loc = this.current_location;
1660    //     expression(this, false)?;
1661    //     this.emit(OpCode::DEFINE_GLOBAL { constant: ident }, loc);
1662    // } else {
1663    //     this.emit_at(OpCode::GET_GLOBAL { constant: ident });
1664    // }
1665    Ok(())
1666}
1667
1668fn grouping(this: &mut Compiler, _can_assign: bool) -> Catch {
1669    devnote!(this "grouping");
1670    expression(this, false)?;
1671    //TODO expect
1672    // expect_token!(self, CloseParen, SiltError::UnterminatedParenthesis(0, 0));
1673    // self.consume(TokenType::RightParen, "Expect ')' after expression.");
1674    Ok(())
1675}
1676
1677fn tabulate(this: &mut Compiler, _can_assign: bool) -> Catch {
1678    devnote!(this "tabulate");
1679    this.emit_at(OpCode::NEW_TABLE);
1680    // not immediately closed
1681    if !matches!(this.peek()?, &Token::CloseBrace) {
1682        let mut count = 0;
1683        // check if index provided via brackets or ident, otherwise increment our count to build array at the end
1684        while {
1685            let start_brace = this.current_location;
1686            if match this.peek()? {
1687                Token::Identifier(_) => {
1688                    this.store();
1689                    if let Token::Assign = this.peek()? {
1690                        let ident = this.get_current()?.unwrap_identifier();
1691                        this.emit_identifer_constant_at(ident.clone());
1692                        this.eat();
1693                        true
1694                    } else {
1695                        expression(this, true)?; // we skip the store because the ip is already where it needs to be
1696                        false
1697                    }
1698                }
1699                Token::OpenBracket => {
1700                    this.eat();
1701                    expression(this, false)?;
1702                    expect_token!(
1703                        this,
1704                        CloseBracket,
1705                        this.error_at(SiltError::UnterminatedBracket(start_brace.0, start_brace.1))
1706                    );
1707                    expect_token!(this, Assign, this.error_at(SiltError::ExpectedAssign));
1708                    true
1709                }
1710                _ => {
1711                    expression(this, false)?; // normal store expression
1712                    false
1713                }
1714            } {
1715                expression(this, false)?;
1716                this.emit_at(OpCode::TABLE_INSERT { offset: count });
1717            } else {
1718                count += 1;
1719            }
1720
1721            match this.peek()? {
1722                Token::Comma => {
1723                    this.eat();
1724                    true
1725                }
1726                Token::CloseBrace => false,
1727                _ => return Err(this.error_at(SiltError::TableExpectedCommaOrCloseBrace)),
1728            }
1729        } {
1730            // if args >= 255 {
1731            //     return Err(this.error_at(SiltError::TooManyParameters));
1732            // }
1733        }
1734        if count > 0 {
1735            this.emit_at(OpCode::TABLE_BUILD(count));
1736        }
1737    }
1738
1739    expect_token!(
1740        this,
1741        CloseBrace,
1742        this.error_at(SiltError::TableExpectedCommaOrCloseBrace)
1743    );
1744    Ok(())
1745}
1746
1747/** op unary or primary */
1748fn unary(this: &mut Compiler, _can_assign: bool) -> Catch {
1749    devnote!(this "unary");
1750    let t = this.copy_store()?;
1751    // self.expression();
1752
1753    this.parse_precedence(Precedence::Unary, false)?;
1754    match t {
1755        Token::Op(Operator::Sub) => this.emit_at(OpCode::NEGATE),
1756        Token::Op(Operator::Not) => this.emit_at(OpCode::NOT),
1757        Token::Op(Operator::Length) => this.emit_at(OpCode::LENGTH),
1758        _ => {}
1759    }
1760    //     let operator = Self::de_op(self.eat_out());
1761    //     let location = self.get_last_loc();
1762    //     let right = self.unary();
1763    //     Expression::Unary {
1764    //         operator,
1765    //         right: Box::new(right),
1766    //         location,
1767    //     }
1768    // } else {
1769    //     self.anonymous_check()
1770    // }
1771    Ok(())
1772}
1773
1774fn table_indexer(this: &mut Compiler) -> Result<usize, ErrorTuple> {
1775    let mut count = 0;
1776    while match this.peek()? {
1777        Token::OpenBracket => {
1778            this.eat();
1779            expression(this, false)?;
1780            expect_token!(
1781                this,
1782                CloseBracket,
1783                this.error_at(SiltError::UnterminatedBracket(0, 0))
1784            );
1785            true
1786        }
1787        Token::Dot => {
1788            this.eat();
1789            let t = this.pop();
1790            this.current_location = t.1;
1791            let field = t.0?;
1792            devout!("table_indexer: {} p:{}", field, this.peek()?);
1793            if let Token::Identifier(ident) = field {
1794                this.emit_identifer_constant_at(ident);
1795            } else {
1796                return Err(this.error_at(SiltError::ExpectedFieldIdentifier));
1797            }
1798            true
1799        }
1800        _ => false,
1801    } {
1802        count += 1;
1803    }
1804    Ok(count)
1805}
1806
1807fn binary(this: &mut Compiler, _can_assign: bool) -> Catch {
1808    devnote!(this "binary");
1809    let t = this.copy_store()?;
1810    let l = this.current_location;
1811    let rule = Compiler::get_rule(&t);
1812    this.parse_precedence(rule.precedence.next(), false)?;
1813    if let Token::Op(op) = t {
1814        match op {
1815            Operator::Add => this.emit(OpCode::ADD, l),
1816            Operator::Sub => this.emit(OpCode::SUB, l),
1817            Operator::Multiply => this.emit(OpCode::MULTIPLY, l),
1818            Operator::Divide => this.emit(OpCode::DIVIDE, l),
1819
1820            Operator::Concat => this.emit(OpCode::CONCAT, l),
1821
1822            // Operator::Modulus => self.emit(OpCode::MODULUS, t.1),
1823            // Operator::Equal => self.emit(OpCode::EQUAL, t.1),
1824            Operator::Equal => this.emit(OpCode::EQUAL, l),
1825            Operator::NotEqual => this.emit(OpCode::NOT_EQUAL, l),
1826            Operator::Less => this.emit(OpCode::LESS, l),
1827            Operator::LessEqual => this.emit(OpCode::LESS_EQUAL, l),
1828            Operator::Greater => this.emit(OpCode::GREATER, l),
1829            Operator::GreaterEqual => this.emit(OpCode::GREATER_EQUAL, l),
1830
1831            _ => todo!(),
1832        }
1833    }
1834    Ok(())
1835}
1836
1837fn concat(this: &mut Compiler, _can_assign: bool) -> Catch {
1838    devnote!(this "concat_binary");
1839    let t = this.copy_store()?;
1840    let l = this.current_location;
1841    let rule = Compiler::get_rule(&t);
1842    this.parse_precedence(rule.precedence.next(), false)?;
1843
1844    if let Token::Op(op) = t {
1845        match op {
1846            Operator::Concat => this.emit(OpCode::CONCAT, l),
1847            _ => todo!(),
1848        }
1849    }
1850    Ok(())
1851}
1852
1853fn and(this: &mut Compiler, _can_assign: bool) -> Catch {
1854    devnote!(this "and");
1855    let index = this.emit_index(OpCode::GOTO_IF_FALSE(0));
1856    this.emit_at(OpCode::POP);
1857    this.parse_precedence(Precedence::And, false)?;
1858    this.patch(index)?;
1859    Ok(())
1860}
1861
1862fn or(this: &mut Compiler, _can_assign: bool) -> Catch {
1863    devnote!(this "or");
1864
1865    // the goofy way
1866    // let index = this.emit_index(OpCode::GOTO_IF_FALSE(0));
1867    // let final_index = this.emit_index(OpCode::GOTO(0));
1868    // this.patch(index)?;
1869    // this.emit_at(OpCode::POP);
1870    // this.parse_precedence(Precedence::Or, false)?;
1871    // this.patch(final_index)?;
1872
1873    let index = this.emit_index(OpCode::GOTO_IF_TRUE(0));
1874    this.emit_at(OpCode::POP);
1875    this.parse_precedence(Precedence::Or, false)?;
1876    this.patch(index)?;
1877    Ok(())
1878}
1879
1880fn integer(this: &mut Compiler, can_assign: bool) -> Catch {
1881    devnote!(this "integer");
1882    let t = this.copy_store()?;
1883    let value = if let Token::Integer(i) = t {
1884        Value::Integer(i)
1885    } else {
1886        unreachable!()
1887    };
1888    this.constant_at(value);
1889    Ok(())
1890}
1891
1892fn number(this: &mut Compiler, can_assign: bool) -> Catch {
1893    devnote!(this "number");
1894    let t = this.copy_store()?;
1895    let value = if let Token::Number(n) = t {
1896        Value::Number(n)
1897    } else {
1898        unreachable!()
1899    };
1900    this.constant_at(value);
1901    Ok(())
1902}
1903
1904fn string(this: &mut Compiler, can_assign: bool) -> Catch {
1905    devnote!(this "string");
1906    let t = this.copy_store()?;
1907    let value = if let Token::StringLiteral(s) = t {
1908        Value::String(Box::new(s.into_string()))
1909    } else {
1910        unreachable!()
1911    };
1912    this.constant_at(value);
1913    Ok(())
1914}
1915
1916fn literal(this: &mut Compiler, can_assign: bool) -> Catch {
1917    devnote!(this "literal");
1918    let t = this.copy_store()?;
1919    match t {
1920        Token::Nil => this.emit_at(OpCode::NIL),
1921        Token::True => this.emit_at(OpCode::TRUE),
1922        Token::False => this.emit_at(OpCode::FALSE),
1923        _ => unreachable!(),
1924    }
1925    Ok(())
1926}
1927
1928fn call(this: &mut Compiler, can_assign: bool) -> Catch {
1929    devnote!(this "call");
1930    // let t = this.take_store()?;
1931    // let l = this.current_location;
1932    // let rule = Compiler::get_rule(&t);
1933    // this.parse_precedence(rule.precedence.next(), false)?;
1934    // if let Token::OpenParen = t {
1935    //     let arg_count = this.argument_list()?;
1936    //     this.emit(OpCode::CALL { arg_count }, l);
1937    // }
1938    let start = this.current_location;
1939    let arg_count = arguments(this, start)?;
1940    this.emit(OpCode::CALL(arg_count), start);
1941    Ok(())
1942}
1943
1944fn call_table(this: &mut Compiler, can_assign: bool) -> Catch {
1945    todo!();
1946    Ok(())
1947}
1948
1949fn call_string(this: &mut Compiler, can_assign: bool) -> Catch {
1950    todo!();
1951    Ok(())
1952}
1953fn arguments(this: &mut Compiler, start: Location) -> Result<u8, ErrorTuple> {
1954    devnote!(this "arguments");
1955    let mut args = 0;
1956    if !matches!(this.peek()?, &Token::CloseParen) {
1957        while {
1958            expression(this, false)?;
1959            args += 1;
1960            if let &Token::Comma = this.peek()? {
1961                this.eat();
1962                true
1963            } else {
1964                false
1965            }
1966        } {
1967            if args >= 255 {
1968                return Err(this.error_at(SiltError::TooManyParameters));
1969            }
1970        }
1971    }
1972
1973    expect_token!(
1974        this,
1975        CloseParen,
1976        this.error_at(SiltError::UnterminatedParenthesis(start.0, start.1))
1977    );
1978    devout!("arguments count: {}", args);
1979
1980    Ok(args)
1981}
1982
1983fn print(this: &mut Compiler) -> Catch {
1984    devnote!(this "print");
1985    this.eat();
1986    expression(this, false)?;
1987    this.emit_at(OpCode::PRINT);
1988    Ok(())
1989}
1990
1991pub fn void(_this: &mut Compiler, _can_assign: bool) -> Catch {
1992    devnote!(_this "void");
1993    Ok(())
1994}
1995
1996// pub fn invalid(_: &mut Compiler) { // TODO
1997//                                    // this.error(SiltError::InvalidExpression);
1998// }
1999
2000// declare
2001// if var  return declare_staement
2002// return statement
2003// declare_statement
2004// eat identifier
2005// if equal then expresion
2006// otherwise return as nil binary assign
2007
2008// ======
2009// ======
2010// ======
2011// ======
2012
2013// fn assigner(&mut self, ident: Ident) -> Expression {
2014//     let tok = self.eat_out();
2015
2016//     let location = self.get_last_loc();
2017//     match tok {
2018//         Token::Assign => Expression::Assign {
2019//             ident,
2020//             value: Box::new(self.expression()),
2021//             location,
2022//         },
2023//         Token::AddAssign => {
2024//             op_assign!(self, ident, Add)
2025//         }
2026//         Token::SubAssign => {
2027//             op_assign!(self, ident, Sub)
2028//         }
2029//         Token::MultiplyAssign => {
2030//             op_assign!(self, ident, Multiply)
2031//         }
2032//         Token::DivideAssign => {
2033//             op_assign!(self, ident, Divide)
2034//         }
2035//         Token::ModulusAssign => {
2036//             op_assign!(self, ident, Modulus)
2037//         }
2038//         _ => panic!("impossible"), //Statement::Expression(Expression::Variable {ident})
2039//     }
2040// }