mica_language/
codegen.rs

1//! Bytecode generation.
2
3use std::collections::{HashMap, HashSet};
4use std::mem;
5use std::rc::Rc;
6
7use crate::ast::{Ast, NodeId, NodeKind};
8use crate::bytecode::{
9   BuiltinTraits, CaptureKind, Chunk, Environment, Function, FunctionKind, FunctionSignature,
10   Opcode, Opr24, Prototype,
11};
12use crate::common::{Error, ErrorKind, Location, RenderedSignature};
13
14/// Info about a local variable on the stack.
15#[derive(Debug)]
16struct Variable {
17   stack_slot: Opr24,
18   is_captured: bool,
19}
20
21#[derive(Debug, Default)]
22struct Scope {
23   /// Mapping from variable names to stack slots.
24   variables_by_name: HashMap<String, Variable>,
25   allocated_variable_count: u32,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29enum VariablePlace {
30   Global(Opr24),
31   Local(Opr24),
32   Upvalue(Opr24),
33}
34
35/// The kind of a variable allocation.
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37enum VariableAllocation {
38   /// Inherit the allocation from the caller (parameter passing).
39   Inherit,
40   /// Allocate new storage for the variable.
41   Allocate,
42}
43
44/// Local variables, including upvalues.
45#[derive(Default)]
46struct Locals {
47   /// If there is a parent code generator with its own scopes (the current instance is in the
48   /// middle of compiling a closure), this is populated with its Locals.
49   parent: Option<Box<Self>>,
50
51   scopes: Vec<Scope>,
52   /// The next stack slot to be occupied by a variable.
53   local_count: u32,
54   /// The total amount of locals currently allocated. This is used to populate the
55   /// `preallocate_stack_slots` field in chunks, to provide more efficient allocations
56   allocated_local_count: u32,
57
58   /// Variables captured from parent scopes.
59   captures: Vec<CaptureKind>,
60}
61
62impl Locals {
63   /// Creates a new local.
64   fn create_local(
65      &mut self,
66      name: &str,
67      allocation: VariableAllocation,
68   ) -> Result<VariablePlace, ErrorKind> {
69      let slot = self.local_count;
70      let slot = Opr24::new(slot).map_err(|_| ErrorKind::TooManyLocals)?;
71      let scope = self.scopes.last_mut().unwrap();
72      scope.variables_by_name.insert(
73         name.to_owned(),
74         Variable {
75            stack_slot: slot,
76            is_captured: false,
77         },
78      );
79      self.local_count += 1;
80      if allocation == VariableAllocation::Allocate {
81         self.allocated_local_count += 1;
82         scope.allocated_variable_count += 1;
83      }
84      Ok(VariablePlace::Local(slot))
85   }
86
87   fn variables_in_scope_mut(&mut self) -> impl Iterator<Item = (&str, &'_ mut Variable)> {
88      self
89         .scopes
90         .iter_mut()
91         .rev()
92         .flat_map(|scope| scope.variables_by_name.iter_mut().map(|(s, v)| (s.as_str(), v)))
93   }
94
95   /// Returns the index of the given capture.
96   fn capture_index(&mut self, capture: CaptureKind) -> Result<Opr24, ErrorKind> {
97      // Iterating over captures maybe isn't most efficient here but it's not like we have
98      // thousands of them anyways. Unless somebody absolutely crazy starts writing Mica code.
99      // Then all I can say is: I hate you.
100      let index = self.captures.iter().rposition(|c| c.eq(&capture)).unwrap_or_else(|| {
101         let index = self.captures.len();
102         self.captures.push(capture);
103         index
104      });
105      Opr24::try_from(index).map_err(|_| ErrorKind::TooManyCaptures)
106   }
107
108   /// Performs a local variable lookup. This may modify parent Locals and capture upvalues.
109   fn lookup(&mut self, name: &str) -> Result<Option<VariablePlace>, ErrorKind> {
110      // Work inside out: try innermost scopes (own locals) first.
111      for scope in self.scopes.iter().rev() {
112         if let Some(var) = scope.variables_by_name.get(name) {
113            return Ok(Some(VariablePlace::Local(var.stack_slot)));
114         }
115      }
116      // If there isn't a local with the given name, go up a level and look for locals to capture
117      // or existing upvalues.
118      if let Some(parent) = self.parent.as_mut() {
119         if let Some(place) = parent.lookup(name)? {
120            match place {
121               VariablePlace::Local(local_slot) => {
122                  let (_, variable) = parent
123                     .variables_in_scope_mut()
124                     .find(|(_, var)| var.stack_slot == local_slot)
125                     .unwrap();
126                  variable.is_captured = true;
127                  let stack_slot = variable.stack_slot;
128                  let upvalue_index = self.capture_index(CaptureKind::Local(stack_slot))?;
129                  return Ok(Some(VariablePlace::Upvalue(upvalue_index)));
130               }
131               VariablePlace::Upvalue(upvalue_index) => {
132                  let own_index = self.capture_index(CaptureKind::Upvalue(upvalue_index))?;
133                  return Ok(Some(VariablePlace::Upvalue(own_index)));
134               }
135               VariablePlace::Global(_) => unreachable!(),
136            }
137         }
138      }
139      Ok(None)
140   }
141
142   /// Pushes a new scope onto the scope stack.
143   fn push_scope(&mut self) {
144      self.scopes.push(Default::default());
145   }
146
147   /// Pops the topmost scope off the scope stack and frees storage of any variables.
148   fn pop_scope(&mut self) -> Scope {
149      let scope = self.scopes.pop().expect("no scopes left on the stack");
150      self.local_count -= scope.variables_by_name.len() as u32;
151      self.allocated_local_count -= scope.allocated_variable_count;
152      scope
153   }
154}
155
156#[derive(Debug, Default)]
157struct BreakableBlock {
158   /// A list of offsets where `breaks` should be backpatched.
159   breaks: Vec<usize>,
160   start: usize,
161}
162
163#[derive(Debug, Default)]
164struct StructData {
165   /// Mapping from field names to indices.
166   fields: HashMap<Rc<str>, Opr24>,
167   /// The `self` variable. Used in `@field` lookups.
168   receiver: Option<VariablePlace>,
169}
170
171impl StructData {
172   /// Returns the index of the field with the given name, or creates that field if it doesn't
173   /// exist yet.
174   fn get_or_create_field(&mut self, name: &str) -> Result<Opr24, ErrorKind> {
175      if !self.fields.contains_key(name) {
176         let index = Opr24::try_from(self.fields.len()).map_err(|_| ErrorKind::TooManyFields)?;
177         self.fields.insert(Rc::from(name), index);
178         Ok(index)
179      } else {
180         Ok(*self.fields.get(name).unwrap())
181      }
182   }
183
184   /// Returns the index of the field with the given name, or `None` if there is no such field.
185   fn get_field(&self, name: &str) -> Option<Opr24> {
186      self.fields.get(name).copied()
187   }
188}
189
190pub struct CodeGenerator<'e> {
191   env: &'e mut Environment,
192   builtin_traits: &'e BuiltinTraits,
193
194   chunk: Chunk,
195
196   locals: Box<Locals>,
197   breakable_blocks: Vec<BreakableBlock>,
198   struct_data: Option<Box<StructData>>,
199
200   allow_new_fields: bool,
201   is_constructor: bool,
202   assigned_fields: HashSet<Rc<str>>,
203}
204
205impl<'e> CodeGenerator<'e> {
206   /// Constructs a new code generator with an empty chunk.
207   pub fn new(
208      module_name: Rc<str>,
209      env: &'e mut Environment,
210      builtin_traits: &'e BuiltinTraits,
211   ) -> Self {
212      Self {
213         env,
214         chunk: Chunk::new(module_name),
215         builtin_traits,
216
217         locals: Default::default(),
218         breakable_blocks: Vec::new(),
219         struct_data: None,
220
221         allow_new_fields: false,
222         is_constructor: false,
223         assigned_fields: HashSet::new(),
224      }
225   }
226
227   /// Creates a variable. If there is a scope on the stack, the variable is local; otherwise it
228   /// is global.
229   fn create_variable(
230      &mut self,
231      name: &str,
232      allocation: VariableAllocation,
233   ) -> Result<VariablePlace, ErrorKind> {
234      if !self.locals.scopes.is_empty() {
235         let place = self.locals.create_local(name, allocation)?;
236         self.chunk.preallocate_stack_slots =
237            self.chunk.preallocate_stack_slots.max(self.locals.allocated_local_count);
238         Ok(place)
239      } else {
240         let slot = self.env.create_global(name)?;
241         Ok(VariablePlace::Global(slot))
242      }
243   }
244
245   /// Performs a variable lookup. Returns the stack slot of the variable if it exists.
246   /// Otherwise returns `None`.
247   fn lookup_variable(&mut self, name: &str) -> Result<Option<VariablePlace>, ErrorKind> {
248      // Work from the inside out: check innermost local scopes first.
249      if let Some(place) = self.locals.lookup(name)? {
250         return Ok(Some(place));
251      }
252      // Lastly check globals.
253      Ok(self.env.get_global(name).map(VariablePlace::Global))
254   }
255
256   /// Pushes a new scope onto the scope stack.
257   fn push_scope(&mut self) {
258      self.locals.push_scope();
259   }
260
261   /// Pops the topmost scope off the scope stack and frees storage of any variables.
262   fn pop_scope(&mut self) {
263      let scope = self.locals.pop_scope();
264      for variable in scope.variables_by_name.into_values() {
265         if variable.is_captured {
266            self.chunk.emit((Opcode::CloseLocal, variable.stack_slot));
267         }
268      }
269   }
270
271   /// Generates a variable load instruction (GetLocal, GetGlobal, GetUpvalue).
272   fn generate_variable_load(&mut self, variable: VariablePlace) {
273      self.chunk.emit(match variable {
274         VariablePlace::Global(slot) => (Opcode::GetGlobal, slot),
275         VariablePlace::Local(slot) => (Opcode::GetLocal, slot),
276         VariablePlace::Upvalue(slot) => (Opcode::GetUpvalue, slot),
277      });
278   }
279
280   /// Generates a variable assign instruction (AssignLocal, AssignGlobal, AssignUpvalue).
281   fn generate_variable_assign(&mut self, variable: VariablePlace) {
282      self.chunk.emit(match variable {
283         VariablePlace::Global(slot) => (Opcode::AssignGlobal, slot),
284         VariablePlace::Local(slot) => (Opcode::AssignLocal, slot),
285         VariablePlace::Upvalue(slot) => (Opcode::AssignUpvalue, slot),
286      });
287   }
288
289   /// Generates a variable sink instruction (SinkLocal, SinkGlobal, SinkUpvalue).
290   fn generate_variable_sink(&mut self, variable: VariablePlace) {
291      self.chunk.emit(match variable {
292         VariablePlace::Global(slot) => (Opcode::SinkGlobal, slot),
293         VariablePlace::Local(slot) => (Opcode::SinkLocal, slot),
294         VariablePlace::Upvalue(slot) => (Opcode::SinkUpvalue, slot),
295      });
296   }
297
298   /// Pushes a new breakable block.
299   fn push_breakable_block(&mut self) {
300      let start = self.chunk.emit(Opcode::Nop);
301      self.breakable_blocks.push(BreakableBlock {
302         breaks: Vec::new(),
303         start,
304      });
305   }
306
307   /// Pops the topmost breakable block.
308   fn pop_breakable_block(&mut self) {
309      let block = self.breakable_blocks.pop().unwrap();
310      if !block.breaks.is_empty() {
311         self.chunk.patch(block.start, Opcode::EnterBreakableBlock);
312         for jump in block.breaks {
313            // Unwrapping is safe here because if the loop is too large the error was caught already
314            // before `pop_breakable_block` was called.
315            self.chunk.patch(jump, Opcode::jump_forward(jump, self.chunk.len()).unwrap());
316         }
317         self.chunk.emit((Opcode::ExitBreakableBlock, 1));
318      }
319   }
320
321   /// Generates code for a list of nodes. The last node's value is the one left on the stack.
322   ///
323   /// If there are no nodes in the list, this is equivalent to a `nil` literal.
324   fn generate_node_list(&mut self, ast: &Ast, nodes: &[NodeId]) -> Result<(), Error> {
325      if nodes.is_empty() {
326         let _ = self.generate_nil();
327      } else {
328         for (i, &node) in nodes.iter().enumerate() {
329            self.generate_node(
330               ast,
331               node,
332               if i != nodes.len() - 1 {
333                  Expression::Discarded
334               } else {
335                  Expression::Used
336               },
337            )?;
338         }
339      }
340      Ok(())
341   }
342
343   /// Generates code for a nil literal.
344   fn generate_nil(&mut self) -> ExpressionResult {
345      self.chunk.emit(Opcode::PushNil);
346      ExpressionResult::Present
347   }
348
349   /// Generates code for a boolean literal.
350   fn generate_boolean(&mut self, ast: &Ast, node: NodeId) -> ExpressionResult {
351      self.chunk.emit(match ast.kind(node) {
352         NodeKind::True => Opcode::PushTrue,
353         NodeKind::False => Opcode::PushFalse,
354         _ => unreachable!(),
355      });
356      ExpressionResult::Present
357   }
358
359   /// Generates code for a number literal.
360   fn generate_number(&mut self, ast: &Ast, node: NodeId) -> ExpressionResult {
361      self.chunk.emit(Opcode::PushNumber);
362      let number = ast.number(node).unwrap();
363      self.chunk.emit_number(number);
364      ExpressionResult::Present
365   }
366
367   /// Generates code for a string literal.
368   fn generate_string(&mut self, ast: &Ast, node: NodeId) -> ExpressionResult {
369      self.chunk.emit(Opcode::PushString);
370      let string = ast.string(node).unwrap();
371      self.chunk.emit_string(string);
372      ExpressionResult::Present
373   }
374
375   /// Generates code for a unary operator.
376   fn generate_unary(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
377      let (left, _) = ast.node_pair(node);
378      self.generate_node(ast, left, Expression::Used)?;
379      match ast.kind(node) {
380         NodeKind::Negate => self.chunk.emit(Opcode::Negate),
381         NodeKind::Not => self.chunk.emit(Opcode::Not),
382         _ => unreachable!(),
383      };
384      Ok(ExpressionResult::Present)
385   }
386
387   /// Generates code for a binary operator.
388   fn generate_binary(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
389      let (left, right) = ast.node_pair(node);
390      self.generate_node(ast, left, Expression::Used)?;
391      self.generate_node(ast, right, Expression::Used)?;
392      match ast.kind(node) {
393         NodeKind::Negate => self.chunk.emit(Opcode::Negate),
394
395         NodeKind::Add => self.chunk.emit(Opcode::Add),
396         NodeKind::Subtract => self.chunk.emit(Opcode::Subtract),
397         NodeKind::Multiply => self.chunk.emit(Opcode::Multiply),
398         NodeKind::Divide => self.chunk.emit(Opcode::Divide),
399
400         NodeKind::Equal => self.chunk.emit(Opcode::Equal),
401         NodeKind::NotEqual => {
402            self.chunk.emit(Opcode::Equal);
403            self.chunk.emit(Opcode::Not)
404         }
405         NodeKind::Less => self.chunk.emit(Opcode::Less),
406         NodeKind::LessEqual => self.chunk.emit(Opcode::LessEqual),
407         NodeKind::Greater => {
408            self.chunk.emit(Opcode::Swap);
409            self.chunk.emit(Opcode::Less)
410         }
411         NodeKind::GreaterEqual => {
412            self.chunk.emit(Opcode::Swap);
413            self.chunk.emit(Opcode::LessEqual)
414         }
415         _ => unreachable!(),
416      };
417      Ok(ExpressionResult::Present)
418   }
419
420   /// Generates code for a variable lookup.
421   fn generate_variable(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
422      let name = ast.string(node).unwrap();
423      if let Some(variable) = self.lookup_variable(name).map_err(|kind| ast.error(node, kind))? {
424         self.generate_variable_load(variable);
425         Ok(ExpressionResult::Present)
426      } else {
427         Err(ast.error(node, ErrorKind::VariableDoesNotExist(name.to_owned())))
428      }
429   }
430
431   /// Generates code for a field lookup.
432   fn generate_field(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
433      let (name, _) = ast.node_pair(node);
434      let name = ast.string(name).unwrap();
435      let struct_data = self
436         .struct_data
437         .as_deref()
438         .ok_or_else(|| ast.error(node, ErrorKind::FieldOutsideOfImpl))?;
439      let field_id = struct_data
440         .get_field(name)
441         .ok_or_else(|| ast.error(node, ErrorKind::FieldDoesNotExist(Rc::clone(name))))?;
442      // Unwrapping is OK here because fields are not allowed outside of functions, and each
443      // function with `StructData` passed in assigns to `receiver` at the start of its
444      // code generation.
445      let receiver = struct_data.receiver.unwrap();
446      self.generate_variable_load(receiver);
447      self.chunk.emit((Opcode::GetField, field_id));
448      Ok(ExpressionResult::Present)
449   }
450
451   /// Generates code for destructuring a pattern.
452   ///
453   /// The generated code assumes there's a value to destructure at the top of the stack (called the
454   /// *scrutinee*.)
455   fn generate_pattern_destructuring(&mut self, ast: &Ast, node: NodeId) -> Result<(), Error> {
456      match ast.kind(node) {
457         NodeKind::Identifier => {
458            let name = ast.string(node).unwrap();
459            let variable = self
460               .create_variable(name, VariableAllocation::Allocate)
461               .map_err(|kind| ast.error(node, kind))?;
462            self.generate_variable_sink(variable);
463         }
464         _ => return Err(ast.error(node, ErrorKind::InvalidPattern)),
465      }
466      Ok(())
467   }
468
469   /// Generates code for an assignment.
470   fn generate_assignment(
471      &mut self,
472      ast: &Ast,
473      node: NodeId,
474      result: Expression,
475   ) -> Result<ExpressionResult, Error> {
476      let (target, value) = ast.node_pair(node);
477      self.generate_node(ast, value, Expression::Used)?;
478
479      match ast.kind(target) {
480         NodeKind::Identifier => {
481            let name = ast.string(target).unwrap();
482            let variable = if let Some(slot) =
483               self.lookup_variable(name).map_err(|kind| ast.error(target, kind))?
484            {
485               slot
486            } else {
487               self
488                  .create_variable(name, VariableAllocation::Allocate)
489                  .map_err(|kind| ast.error(node, kind))?
490            };
491            match result {
492               Expression::Used => self.generate_variable_assign(variable),
493               Expression::Discarded => self.generate_variable_sink(variable),
494            }
495         }
496         NodeKind::Field => {
497            let (name, _) = ast.node_pair(target);
498            let name = ast.string(name).unwrap();
499            if let Some(struct_data) = self.struct_data.as_mut() {
500               let field = if self.allow_new_fields {
501                  struct_data.get_or_create_field(name).map_err(|kind| ast.error(node, kind))?
502               } else {
503                  struct_data.get_field(name).ok_or_else(|| {
504                     ast.error(target, ErrorKind::FieldDoesNotExist(Rc::clone(name)))
505                  })?
506               };
507               // Unwrapping is OK here because `receiver` is assigned at the start of each function
508               // in an `impl` block.
509               let receiver = struct_data.receiver.unwrap();
510               self.generate_variable_load(receiver);
511               self.chunk.emit(match result {
512                  Expression::Used => (Opcode::AssignField, field),
513                  Expression::Discarded => (Opcode::SinkField, field),
514               });
515            } else {
516               return Err(ast.error(target, ErrorKind::FieldOutsideOfImpl));
517            }
518            // In constructors, we need to keep track of which fields were assigned to report
519            // errors about missing field values.
520            if self.is_constructor && !self.allow_new_fields {
521               self.assigned_fields.insert(Rc::clone(name));
522            }
523         }
524         _ => return Err(ast.error(target, ErrorKind::InvalidAssignment)),
525      }
526
527      Ok(match result {
528         Expression::Discarded => ExpressionResult::Absent,
529         Expression::Used => ExpressionResult::Present,
530      })
531   }
532
533   /// Generates code for a list literal.
534   fn generate_list(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
535      let children = ast.children(node).unwrap();
536      let len =
537         Opr24::try_from(children.len()).map_err(|_| ast.error(node, ErrorKind::ListIsTooLong))?;
538      for &child in children {
539         self.generate_node(ast, child, Expression::Used)?;
540      }
541      self.chunk.emit((Opcode::CreateList, len));
542      Ok(ExpressionResult::Present)
543   }
544
545   /// Generates code for a dict literal.
546   fn generate_dict(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
547      let children = ast.children(node).unwrap();
548      let len =
549         Opr24::try_from(children.len()).map_err(|_| ast.error(node, ErrorKind::DictIsTooLarge))?;
550      for &child in children {
551         let (key, value) = ast.node_pair(child);
552         self.generate_node(ast, key, Expression::Used)?;
553         self.generate_node(ast, value, Expression::Used)?;
554      }
555      self.chunk.emit((Opcode::CreateDict, len));
556      Ok(ExpressionResult::Present)
557   }
558
559   /// Generates code for a `do..end` expression.
560   fn generate_do(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
561      let children = ast.children(node).unwrap();
562      self.push_scope();
563      self.generate_node_list(ast, children)?;
564      self.pop_scope();
565      Ok(ExpressionResult::Present)
566   }
567
568   /// Generates code for an `if..elif..else..end` expression.
569   fn generate_if(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
570      let branches = ast.children(node).unwrap();
571      let mut jumps_to_end = Vec::new();
572
573      for (i, &branch) in branches.iter().enumerate() {
574         // We need to discard the previous branch's condition (if there was a previous branch).
575         if i > 0 {
576            self.chunk.emit(Opcode::Discard);
577         }
578
579         let then = ast.children(branch).unwrap();
580         match ast.kind(branch) {
581            NodeKind::IfBranch => {
582               // Generate the condition.
583               let (condition, _) = ast.node_pair(branch);
584               self.push_scope();
585               self.generate_node(ast, condition, Expression::Used)?;
586               // Generate a Nop that is later backpatched with a ConditionalJumpForward.
587               let jump = self.chunk.emit(Opcode::Nop);
588               self.chunk.emit(Opcode::Discard); // The condition has to be discarded.
589               self.generate_node_list(ast, then)?;
590               self.pop_scope();
591               let jump_to_end = self.chunk.emit(Opcode::Nop);
592               jumps_to_end.push(jump_to_end);
593               self.chunk.patch(
594                  jump,
595                  Opcode::jump_forward_if_falsy(jump, self.chunk.len())
596                     .map_err(|_| ast.error(branch, ErrorKind::IfBranchTooLarge))?,
597               );
598            }
599
600            NodeKind::ElseBranch => {
601               self.push_scope();
602               self.generate_node_list(ast, then)?;
603               self.pop_scope();
604            }
605
606            _ => unreachable!(),
607         }
608      }
609
610      // If there was no `else` branch, we need to patch in an implicit one that returns `nil`.
611      if ast.kind(*branches.last().unwrap()) != NodeKind::ElseBranch {
612         self.chunk.emit(Opcode::Discard);
613         self.chunk.emit(Opcode::PushNil);
614      }
615
616      // Backpatch all jumps to end with an unconditional jump forward.
617      for jump in jumps_to_end {
618         self.chunk.patch(
619            jump,
620            Opcode::jump_forward(jump, self.chunk.len())
621               .map_err(|_| ast.error(node, ErrorKind::IfExpressionTooLarge))?,
622         );
623      }
624
625      Ok(ExpressionResult::Present)
626   }
627
628   /// Generates code for an `and` infix operator.
629   fn generate_and(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
630      let (left, right) = ast.node_pair(node);
631      self.push_scope();
632      self.generate_node(ast, left, Expression::Used)?;
633      let jump_past_right = self.chunk.emit(Opcode::Nop);
634      self.chunk.emit(Opcode::Discard);
635      self.generate_node(ast, right, Expression::Used)?;
636      self.chunk.patch(
637         jump_past_right,
638         Opcode::jump_forward_if_falsy(jump_past_right, self.chunk.len())
639            .map_err(|_| ast.error(node, ErrorKind::OperatorRhsTooLarge))?,
640      );
641      self.pop_scope();
642      Ok(ExpressionResult::Present)
643   }
644
645   /// Generates code for an `or` infix operator.
646   fn generate_or(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
647      let (left, right) = ast.node_pair(node);
648      self.push_scope();
649      self.generate_node(ast, left, Expression::Used)?;
650      let jump_past_right = self.chunk.emit(Opcode::Nop);
651      self.chunk.emit(Opcode::Discard);
652      self.generate_node(ast, right, Expression::Used)?;
653      self.chunk.patch(
654         jump_past_right,
655         Opcode::jump_forward_if_truthy(jump_past_right, self.chunk.len())
656            .map_err(|_| ast.error(node, ErrorKind::OperatorRhsTooLarge))?,
657      );
658      self.pop_scope();
659      Ok(ExpressionResult::Present)
660   }
661
662   fn generate_conditional_loop(
663      &mut self,
664      ast: &Ast,
665      node: NodeId,
666      generate_condition: &dyn Fn(&mut CodeGenerator<'_>) -> Result<(), Error>,
667      generate_body: &dyn Fn(&mut CodeGenerator<'_>) -> Result<(), Error>,
668   ) -> Result<(), Error> {
669      // The outer scope, so that variables can be declared in the condition.
670      self.push_scope();
671      // The breakable block.
672      self.push_breakable_block();
673
674      let start = self.chunk.len();
675      generate_condition(self)?;
676      let jump_to_end = self.chunk.emit(Opcode::Nop);
677      // Discard the condition if it's true.
678      self.chunk.emit(Opcode::Discard);
679
680      generate_body(self)?;
681      // While loops don't yield a value.
682      self.chunk.emit(Opcode::Discard);
683
684      self.chunk.emit(
685         Opcode::jump_backward(self.chunk.len(), start)
686            .map_err(|_| ast.error(node, ErrorKind::LoopTooLarge))?,
687      );
688      self.chunk.patch(
689         jump_to_end,
690         Opcode::jump_forward_if_falsy(jump_to_end, self.chunk.len())
691            .map_err(|_| ast.error(node, ErrorKind::LoopTooLarge))?,
692      );
693      // Discard the condition if it's false.
694      self.chunk.emit(Opcode::Discard);
695
696      // Because loops are expressions, they must produce a value. That value is `nil`.
697      self.chunk.emit(Opcode::PushNil);
698
699      // `break`s produce a value (or `nil` by default), so we need to jump over the
700      // fallback `PushNil`.
701      self.pop_breakable_block();
702      self.pop_scope();
703
704      Ok(())
705   }
706
707   /// Generates code for a `while..do..end` loop.
708   fn generate_while(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
709      let (condition, _) = ast.node_pair(node);
710      let body = ast.children(node).unwrap();
711
712      self.generate_conditional_loop(
713         ast,
714         node,
715         &|generator| generator.generate_node(ast, condition, Expression::Used),
716         &|generator| generator.generate_node_list(ast, body),
717      )?;
718
719      Ok(ExpressionResult::Present)
720   }
721
722   /// Generates code for a `for` loop.
723   fn generate_for(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
724      let (binding, iterator) = ast.node_pair(node);
725      let body = ast.children(node).unwrap();
726
727      self.push_scope();
728
729      let iterator_var = self
730         .create_variable("<iterator>", VariableAllocation::Allocate)
731         .map_err(|kind| ast.error(iterator, kind))?;
732      self.generate_node(ast, iterator, Expression::Used)?;
733      self.generate_variable_sink(iterator_var);
734
735      self.generate_conditional_loop(
736         ast,
737         node,
738         &|generator| {
739            generator.generate_variable_load(iterator_var);
740            generator.chunk.emit((
741               Opcode::CallMethod,
742               Opr24::pack((generator.builtin_traits.iterator_has_next, 1)),
743            ));
744            Ok(())
745         },
746         &|generator| {
747            generator.generate_variable_load(iterator_var);
748            generator.chunk.emit((
749               Opcode::CallMethod,
750               Opr24::pack((generator.builtin_traits.iterator_next, 1)),
751            ));
752            generator.generate_pattern_destructuring(ast, binding)?;
753            generator.generate_node_list(ast, body)?;
754            Ok(())
755         },
756      )?;
757
758      self.pop_scope();
759
760      Ok(ExpressionResult::Present)
761   }
762
763   /// Generates a `break` expression.
764   fn generate_break(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
765      let (right, _) = ast.node_pair(node);
766      if right != NodeId::EMPTY {
767         self.generate_node(ast, right, Expression::Used)?;
768      } else {
769         let _ = self.generate_nil();
770      }
771      let jump = self.chunk.emit(Opcode::Nop);
772      if let Some(block) = self.breakable_blocks.last_mut() {
773         block.breaks.push(jump);
774      } else {
775         return Err(ast.error(node, ErrorKind::BreakOutsideOfLoop));
776      }
777      Ok(ExpressionResult::NoReturn)
778   }
779
780   /// Generates code for a function call.
781   fn generate_call(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
782      let (function, _) = ast.node_pair(node);
783      match ast.kind(function) {
784         // Method calls need special treatment.
785         NodeKind::Dot => {
786            let (receiver, name) = ast.node_pair(function);
787            if ast.kind(name) != NodeKind::Identifier {
788               return Err(ast.error(name, ErrorKind::InvalidMethodName));
789            }
790            let name = ast.string(name).unwrap();
791
792            // Generate the receiver and arguments.
793            self.generate_node(ast, receiver, Expression::Used)?;
794            let arguments = ast.children(node).unwrap();
795            for &argument in arguments {
796               self.generate_node(ast, argument, Expression::Used)?;
797            }
798
799            // Construct the call.
800            let arity: u8 = (1 + arguments.len())
801               // ↑ Add 1 for the receiver, which is also an argument.
802               .try_into()
803               .map_err(|_| ast.error(node, ErrorKind::TooManyArguments))?;
804            let signature = FunctionSignature::new(Rc::clone(name), arity as u16);
805            let method_index =
806               self.env.get_method_index(&signature).map_err(|kind| ast.error(node, kind))?;
807            self.chunk.emit((Opcode::CallMethod, Opr24::pack((method_index, arity))));
808         }
809         _ => {
810            self.generate_node(ast, function, Expression::Used)?;
811            let arguments = ast.children(node).unwrap();
812            for &argument in arguments {
813               self.generate_node(ast, argument, Expression::Used)?;
814            }
815            self.chunk.emit((
816               Opcode::Call,
817               Opr24::try_from(arguments.len())
818                  .map_err(|_| ast.error(node, ErrorKind::TooManyArguments))?,
819            ));
820         }
821      }
822      Ok(ExpressionResult::Present)
823   }
824
825   /// Generates code for a bare dot call (without parentheses).
826   fn generate_dot(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
827      let (left, method) = ast.node_pair(node);
828      self.generate_node(ast, left, Expression::Used)?;
829
830      if ast.kind(method) != NodeKind::Identifier {
831         return Err(ast.error(method, ErrorKind::InvalidMethodName));
832      }
833      let signature = FunctionSignature::new(Rc::clone(ast.string(method).unwrap()), 1);
834      let method_index =
835         self.env.get_method_index(&signature).map_err(|kind| ast.error(node, kind))?;
836      self.chunk.emit((Opcode::CallMethod, Opr24::pack((method_index, 1))));
837
838      Ok(ExpressionResult::Present)
839   }
840
841   fn generate_function(
842      &mut self,
843      ast: &Ast,
844      node: NodeId,
845      GenerateFunctionOptions { name, call_conv }: GenerateFunctionOptions,
846   ) -> Result<GeneratedFunction, Error> {
847      let (head, body) = ast.node_pair(node);
848      let (_, parameters) = ast.node_pair(head);
849      let parameter_list = ast.children(parameters).unwrap();
850
851      let mut generator = CodeGenerator::new(
852         Rc::clone(&self.chunk.module_name),
853         self.env,
854         self.builtin_traits,
855      );
856      // NOTE: Hopefully the allocation from this mem::take gets optimized out.
857      generator.locals.parent = Some(mem::take(&mut self.locals));
858      if call_conv.has_field_access() {
859         generator.struct_data = self.struct_data.take();
860         generator.allow_new_fields = call_conv.allow_new_fields();
861      }
862      generator.is_constructor = call_conv.is_constructor();
863
864      // Push a scope to start creating local variables.
865      generator.push_scope();
866      // Create local variables for all the parameters.
867      // Note that in bare functions, the function itself acts as the `self` parameter.
868      let receiver = if call_conv.has_visible_self() {
869         let receiver = generator.create_variable("self", VariableAllocation::Inherit).unwrap();
870         if let Some(struct_data) = generator.struct_data.as_deref_mut() {
871            struct_data.receiver = Some(receiver);
872         }
873         receiver
874      } else {
875         generator.create_variable("<receiver>", VariableAllocation::Inherit).unwrap()
876      };
877      for &parameter in parameter_list {
878         let parameter_name = ast.string(parameter).unwrap();
879         generator
880            .create_variable(parameter_name, VariableAllocation::Inherit)
881            .map_err(|kind| ast.error(parameter, kind))?;
882      }
883
884      // In constructors, we have to create `self` explicitly.
885      let create_struct = if call_conv.is_constructor() {
886         generator.generate_variable_load(receiver);
887         let instruction = generator.chunk.emit(Opcode::Nop);
888         let receiver = generator
889            .create_variable("self", VariableAllocation::Allocate)
890            .map_err(|kind| ast.error(node, kind))?;
891         generator.generate_variable_assign(receiver);
892         generator.chunk.emit(Opcode::Discard);
893         generator.struct_data.as_deref_mut().unwrap().receiver = Some(receiver);
894         Some(instruction)
895      } else {
896         None
897      };
898
899      // Generate the body.
900      generator.generate_node(ast, body, Expression::Used)?;
901
902      // If we're in a constructor we have to backpatch the `CreateStruct` instruction with the
903      // number of fields.
904      if let Some(create_struct) = create_struct {
905         let field_count = generator.struct_data.as_ref().unwrap().fields.len();
906         let field_count = Opr24::try_from(field_count)
907            .map_err(|_| ast.error(ast.node_pair(parameters).0, ErrorKind::TooManyFields))?;
908         generator.chunk.patch(create_struct, (Opcode::CreateStruct, field_count));
909         // We also have to discard whatever was at the top of the stack at the moment and
910         // return the struct we constructed.
911         generator.chunk.emit(Opcode::Discard);
912         let receiver = generator.struct_data.as_ref().unwrap().receiver.unwrap();
913         generator.generate_variable_load(receiver);
914      }
915      // If we're in a constructor, we also have to check if all fields were assigned.
916      if call_conv.is_constructor() && !call_conv.allow_new_fields() {
917         let struct_data = generator.struct_data.as_ref().unwrap();
918         let missing: Vec<_> = struct_data
919            .fields
920            .keys()
921            .filter(|field| !generator.assigned_fields.contains(*field))
922            .cloned()
923            .collect();
924         if !missing.is_empty() {
925            return Err(ast.error(node, ErrorKind::MissingFields(missing)));
926         }
927      }
928
929      // Finish generating the chunk by inserting a `Return` opcode.
930      generator.pop_scope();
931      generator.chunk.emit(Opcode::Return);
932
933      // Take back what was taken from the parent generator.
934      self.locals = generator.locals.parent.take().unwrap();
935      if call_conv.has_field_access() {
936         self.struct_data = generator.struct_data;
937      }
938
939      // Construct the function.
940      let parameter_count = u16::try_from(parameter_list.len())
941         .map_err(|_| ast.error(parameters, ErrorKind::TooManyParameters))?;
942      let function = Function {
943         name,
944         parameter_count: Some(parameter_count),
945         kind: FunctionKind::Bytecode {
946            chunk: Rc::new(generator.chunk),
947            captured_locals: generator.locals.captures,
948         },
949         hidden_in_stack_traces: false,
950      };
951      let function_id = self.env.create_function(function).map_err(|kind| ast.error(node, kind))?;
952
953      Ok(GeneratedFunction {
954         id: function_id,
955         parameter_count,
956      })
957   }
958
959   /// Ensures that a `Func` node is a valid bare function - without a kind, and with a body.
960   fn ensure_valid_bare_function(ast: &Ast, node: NodeId) -> Result<(), Error> {
961      let (head, body) = ast.node_pair(node);
962      let (_name, parameters) = ast.node_pair(head);
963
964      let function_kind = ast.node_pair(parameters).0;
965      if function_kind != NodeId::EMPTY {
966         return Err(ast.error(function_kind, ErrorKind::FunctionKindOutsideImpl));
967      }
968      if body == NodeId::EMPTY {
969         return Err(ast.error(node, ErrorKind::MissingFunctionBody));
970      }
971      Ok(())
972   }
973
974   /// Generates code for a bare function declaration.
975   fn generate_function_declaration(
976      &mut self,
977      ast: &Ast,
978      node: NodeId,
979   ) -> Result<ExpressionResult, Error> {
980      Self::ensure_valid_bare_function(ast, node)?;
981
982      let (head, _) = ast.node_pair(node);
983      let (name_node, _) = ast.node_pair(head);
984      let name = ast.string(name_node).unwrap();
985
986      // Create the variable before compiling the function, to allow for recursion.
987      let variable = self
988         .create_variable(name, VariableAllocation::Allocate)
989         .map_err(|kind| ast.error(name_node, kind))?;
990
991      let function = self.generate_function(
992         ast,
993         node,
994         GenerateFunctionOptions {
995            name: Rc::clone(name),
996            call_conv: FunctionCallConv::Bare,
997         },
998      )?;
999
1000      self.chunk.emit((Opcode::CreateClosure, function.id));
1001      self.generate_variable_sink(variable);
1002
1003      Ok(ExpressionResult::Absent)
1004   }
1005
1006   /// Generates code for a function expression.
1007   fn generate_function_expression(
1008      &mut self,
1009      ast: &Ast,
1010      node: NodeId,
1011   ) -> Result<ExpressionResult, Error> {
1012      Self::ensure_valid_bare_function(ast, node)?;
1013
1014      let function = self.generate_function(
1015         ast,
1016         node,
1017         GenerateFunctionOptions {
1018            name: Rc::from("<anonymous>"),
1019            call_conv: FunctionCallConv::Bare,
1020         },
1021      )?;
1022
1023      self.chunk.emit((Opcode::CreateClosure, function.id));
1024      Ok(ExpressionResult::Present)
1025   }
1026
1027   /// Generates code for a `return` expression.
1028   fn generate_return(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
1029      let (value, _) = ast.node_pair(node);
1030      // Unlike breaking out of a loop, returning is super simple, as it implies that all locals
1031      // are taken off the stack.
1032      if value == NodeId::EMPTY {
1033         let _ = self.generate_nil();
1034      } else {
1035         self.generate_node(ast, value, Expression::Used)?;
1036      }
1037      self.chunk.emit(Opcode::Return);
1038      Ok(ExpressionResult::NoReturn)
1039   }
1040
1041   /// Generates code for a struct declaration.
1042   fn generate_struct(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
1043      let (name, _) = ast.node_pair(node);
1044      let name = ast.string(name).unwrap();
1045
1046      self.chunk.emit(Opcode::CreateType);
1047      self.chunk.emit_string(name);
1048      let variable = self
1049         .create_variable(name, VariableAllocation::Allocate)
1050         .map_err(|kind| ast.error(node, kind))?;
1051      self.generate_variable_assign(variable);
1052
1053      Ok(ExpressionResult::Present)
1054   }
1055
1056   /// Generates code for an `impl` block.
1057   fn generate_impl(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
1058      let (implementee, _) = ast.node_pair(node);
1059      let items = ast.children(node).unwrap();
1060
1061      // Push the implementee onto the stack first. Implemented traits follow.
1062      self.generate_node(ast, implementee, Expression::Used)?;
1063
1064      // There's no need to save any old struct data because `impl` blocks don't nest freely.
1065      // Yes, you can create an `impl` block in a function inside this `impl` block, but that
1066      // function is handled by a different generator.
1067      self.struct_data = Some(Box::new(StructData::default()));
1068
1069      let mut proto = Prototype::default();
1070      let mut state = ImplGenerationState {
1071         proto: &mut proto,
1072         has_constructor: false,
1073         trait_index: None,
1074      };
1075      for &node in items {
1076         self.generate_impl_item(ast, node, &mut state, true)?;
1077      }
1078
1079      let proto_id = self.env.create_prototype(proto).map_err(|kind| ast.error(node, kind))?;
1080      self.chunk.emit((Opcode::Implement, proto_id));
1081
1082      self.struct_data = None;
1083
1084      Ok(ExpressionResult::Present)
1085   }
1086
1087   /// Generates code for a single item in an `impl` block.
1088   fn generate_impl_item(
1089      &mut self,
1090      ast: &Ast,
1091      node: NodeId,
1092      state: &mut ImplGenerationState,
1093      allow_as: bool,
1094   ) -> Result<(), Error> {
1095      match ast.kind(node) {
1096         NodeKind::Func => {
1097            let (head, _) = ast.node_pair(node);
1098            let (name_node, parameters) = ast.node_pair(head);
1099            if ast.kind(name_node) != NodeKind::Identifier {
1100               return Err(ast.error(node, ErrorKind::MissingMethodName));
1101            }
1102            let name = Rc::clone(ast.string(name_node).unwrap());
1103            let (kind, _) = ast.node_pair(parameters);
1104
1105            let call_conv = match ast.kind(kind) {
1106               NodeKind::Empty => FunctionCallConv::Instance,
1107               NodeKind::Static => FunctionCallConv::Static,
1108               NodeKind::Constructor => {
1109                  let allow_new_fields = !state.has_constructor;
1110                  state.has_constructor = true;
1111                  FunctionCallConv::Constructor { allow_new_fields }
1112               }
1113               _ => unreachable!(),
1114            };
1115            let function = self.generate_function(
1116               ast,
1117               node,
1118               GenerateFunctionOptions {
1119                  name: Rc::clone(&name),
1120                  call_conv,
1121               },
1122            )?;
1123
1124            if let Some(trait_index) = state.trait_index {
1125               // For trait instance methods, method ID resolution is performed at runtime.
1126               let key = (Rc::clone(&name), 1 + function.parameter_count, trait_index);
1127               if state.proto.trait_instance.insert(key, function.id).is_some() {
1128                  return Err(ast.error(
1129                     name_node,
1130                     ErrorKind::MethodAlreadyImplemented(RenderedSignature {
1131                        name,
1132                        arity: Some(function.parameter_count),
1133                        // Note that we do not have a way of knowing the actual name of the trait,
1134                        // so we simply don't display it.
1135                        trait_name: None,
1136                     }),
1137                  ));
1138               }
1139            } else {
1140               // For regular instance methods, method ID resolution is performed during
1141               // compilation.
1142               let signature = FunctionSignature::new(name, 1 + function.parameter_count);
1143               let method_id =
1144                  self.env.get_method_index(&signature).map_err(|kind| ast.error(node, kind))?;
1145
1146               let map = match ast.kind(kind) {
1147                  NodeKind::Empty => &mut state.proto.instance,
1148                  NodeKind::Static | NodeKind::Constructor => &mut state.proto.statics,
1149                  _ => unreachable!(),
1150               };
1151               if map.insert(method_id, function.id).is_some() {
1152                  return Err(ast.error(
1153                     name_node,
1154                     ErrorKind::MethodAlreadyImplemented(RenderedSignature {
1155                        name: signature.name,
1156                        arity: Some(function.parameter_count),
1157                        trait_name: None,
1158                     }),
1159                  ));
1160               }
1161            }
1162         }
1163
1164         NodeKind::ImplAs => {
1165            if !allow_as {
1166               return Err(ast.error(node, ErrorKind::AsCannotNest));
1167            }
1168            let (trait_expr, _) = ast.node_pair(node);
1169            let as_items = ast.children(node).unwrap();
1170            self.generate_node(ast, trait_expr, Expression::Used)?;
1171            let trait_index = state.proto.implemented_trait_count;
1172            state.proto.implemented_trait_count = state
1173               .proto
1174               .implemented_trait_count
1175               .checked_add(1)
1176               .ok_or_else(|| ast.error(node, ErrorKind::TooManyTraitsInImpl))?;
1177            let mut state = ImplGenerationState {
1178               proto: state.proto,
1179               trait_index: Some(trait_index),
1180               ..*state
1181            };
1182            for &item in as_items {
1183               self.generate_impl_item(ast, item, &mut state, false)?;
1184            }
1185         }
1186
1187         // NB: If other item types are allowed, don't forget to change the error message for
1188         // InvalidImplItem.
1189         _ => return Err(ast.error(node, ErrorKind::InvalidImplItem)),
1190      }
1191
1192      Ok(())
1193   }
1194
1195   /// Generates code for a trait definition.
1196   fn generate_trait(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
1197      let (trait_name, _) = ast.node_pair(node);
1198      let trait_name = ast.string(trait_name).unwrap();
1199      let items = ast.children(node).unwrap();
1200
1201      let mut builder = TraitBuilder::new(self.env, Some(&self.chunk), Rc::clone(trait_name))
1202         .map_err(|e| ast.error(node, e))?;
1203
1204      for &item in items {
1205         match ast.kind(item) {
1206            NodeKind::Func => {
1207               let (head, body) = ast.node_pair(item);
1208               let (name, params) = ast.node_pair(head);
1209               if body != NodeId::EMPTY {
1210                  return Err(ast.error(body, ErrorKind::TraitMethodCannotHaveBody));
1211               }
1212               if name == NodeId::EMPTY {
1213                  return Err(ast.error(head, ErrorKind::MissingMethodName));
1214               }
1215               if ast.node_pair(params).0 != NodeId::EMPTY {
1216                  return Err(ast.error(head, ErrorKind::FunctionKindInTrait));
1217               }
1218
1219               let _method_id = builder
1220                  .add_method(
1221                     Rc::clone(ast.string(name).unwrap()),
1222                     u16::try_from(ast.len(params).unwrap())
1223                        .map_err(|_| ast.error(item, ErrorKind::TooManyParameters))?,
1224                  )
1225                  .map_err(|e| ast.error(item, e))?;
1226            }
1227            _ => return Err(ast.error(item, ErrorKind::InvalidTraitItem)),
1228         }
1229      }
1230
1231      let (trait_id, _) = builder.build();
1232
1233      self.chunk.emit((Opcode::CreateTrait, trait_id));
1234      let variable = self
1235         .create_variable(trait_name, VariableAllocation::Allocate)
1236         .map_err(|k| ast.error(node, k))?;
1237      self.generate_variable_assign(variable);
1238
1239      Ok(ExpressionResult::Present)
1240   }
1241
1242   /// Generates code for a valid expression node.
1243   ///
1244   /// Nodes that are not valid expressions cause a panic.
1245   fn generate_node(&mut self, ast: &Ast, node: NodeId, expr: Expression) -> Result<(), Error> {
1246      let previous_codegen_location = self.chunk.codegen_location;
1247      self.chunk.codegen_location = ast.location(node);
1248      let result = match ast.kind(node) {
1249         NodeKind::Empty => panic!("empty nodes must never be generated"),
1250
1251         NodeKind::Nil => self.generate_nil(),
1252         NodeKind::False | NodeKind::True => self.generate_boolean(ast, node),
1253         NodeKind::Number => self.generate_number(ast, node),
1254         NodeKind::String => self.generate_string(ast, node),
1255
1256         NodeKind::Identifier => self.generate_variable(ast, node)?,
1257
1258         NodeKind::List => self.generate_list(ast, node)?,
1259         NodeKind::Dict => self.generate_dict(ast, node)?,
1260
1261         NodeKind::Negate | NodeKind::Not => self.generate_unary(ast, node)?,
1262
1263         | NodeKind::Add
1264         | NodeKind::Subtract
1265         | NodeKind::Multiply
1266         | NodeKind::Divide
1267         | NodeKind::Equal
1268         | NodeKind::NotEqual
1269         | NodeKind::Less
1270         | NodeKind::Greater
1271         | NodeKind::LessEqual
1272         | NodeKind::GreaterEqual => self.generate_binary(ast, node)?,
1273
1274         NodeKind::And => self.generate_and(ast, node)?,
1275         NodeKind::Or => self.generate_or(ast, node)?,
1276
1277         NodeKind::Assign => self.generate_assignment(ast, node, expr)?,
1278         NodeKind::Dot => self.generate_dot(ast, node)?,
1279         NodeKind::Field => self.generate_field(ast, node)?,
1280
1281         NodeKind::Main => {
1282            self.generate_node_list(ast, ast.children(node).unwrap())?;
1283            ExpressionResult::Present
1284         }
1285
1286         NodeKind::Do => self.generate_do(ast, node)?,
1287         NodeKind::If => self.generate_if(ast, node)?,
1288         NodeKind::While => self.generate_while(ast, node)?,
1289         NodeKind::For => self.generate_for(ast, node)?,
1290         NodeKind::Break => self.generate_break(ast, node)?,
1291
1292         NodeKind::Func => {
1293            let (head, _) = ast.node_pair(node);
1294            let (name, _) = ast.node_pair(head);
1295            if name != NodeId::EMPTY {
1296               self.generate_function_declaration(ast, node)?
1297            } else {
1298               self.generate_function_expression(ast, node)?
1299            }
1300         }
1301         NodeKind::Call => self.generate_call(ast, node)?,
1302         NodeKind::Return => self.generate_return(ast, node)?,
1303
1304         NodeKind::Struct => self.generate_struct(ast, node)?,
1305         NodeKind::Impl => self.generate_impl(ast, node)?,
1306         NodeKind::Trait => self.generate_trait(ast, node)?,
1307         NodeKind::ImplAs => return Err(ast.error(node, ErrorKind::AsOutsideOfImpl)),
1308
1309         | NodeKind::DictPair
1310         | NodeKind::IfBranch
1311         | NodeKind::ElseBranch
1312         | NodeKind::FunctionHead
1313         | NodeKind::Parameters
1314         | NodeKind::Static
1315         | NodeKind::Constructor => {
1316            unreachable!("AST implementation detail")
1317         }
1318      };
1319      match (result, expr) {
1320         (ExpressionResult::Absent, Expression::Used) => {
1321            let _ = self.generate_nil();
1322         }
1323         (ExpressionResult::Present, Expression::Discarded) => {
1324            let _ = self.chunk.emit(Opcode::Discard);
1325         }
1326         _ => (),
1327      }
1328      self.chunk.codegen_location = previous_codegen_location;
1329      Ok(())
1330   }
1331
1332   /// Generates code for the given AST.
1333   pub fn generate(mut self, ast: &Ast, root_node: NodeId) -> Result<Rc<Chunk>, Error> {
1334      self.generate_node(ast, root_node, Expression::Used)?;
1335      self.chunk.emit(Opcode::Halt);
1336      Ok(Rc::new(self.chunk))
1337   }
1338}
1339
1340/// The calling convention of a function.
1341#[derive(Debug, Clone, Copy)]
1342enum FunctionCallConv {
1343   /// A bare function: `self` is invisible, fields cannot be assigned.
1344   Bare,
1345   /// A static function: `self` is visible, fields cannot be assigned.
1346   Static,
1347   /// An instance function: `self` is visible, fields can be assigned but not created.
1348   Instance,
1349   /// A constructor: `self` is created from scratch, fields can created if `allow_new_fields` is
1350   /// true.
1351   Constructor { allow_new_fields: bool },
1352}
1353
1354impl FunctionCallConv {
1355   fn has_field_access(&self) -> bool {
1356      matches!(self, Self::Instance | Self::Constructor { .. })
1357   }
1358
1359   fn has_visible_self(&self) -> bool {
1360      // Note that `Constructor` does not have a visible `self`, because it's an allocated local
1361      // rather than inherited.
1362      matches!(self, Self::Static | Self::Instance)
1363   }
1364
1365   fn is_constructor(&self) -> bool {
1366      matches!(self, Self::Constructor { .. })
1367   }
1368
1369   fn allow_new_fields(&self) -> bool {
1370      matches!(
1371         self,
1372         Self::Constructor {
1373            allow_new_fields: true
1374         }
1375      )
1376   }
1377}
1378
1379struct GenerateFunctionOptions {
1380   name: Rc<str>,
1381   call_conv: FunctionCallConv,
1382}
1383
1384struct GeneratedFunction {
1385   id: Opr24,
1386   parameter_count: u16,
1387}
1388
1389/// What kind of expression to generate in this place.
1390#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1391enum Expression {
1392   /// Discard the result.
1393   Discarded,
1394   /// Use the result.
1395   Used,
1396}
1397
1398#[must_use]
1399#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1400enum ExpressionResult {
1401   /// The generated code leaves a value on the stack.
1402   Present,
1403   /// The generated code does not generate a value.
1404   Absent,
1405   /// The generated code does not return to the original place and unwinds the stack.
1406   NoReturn,
1407}
1408
1409/// The state of generating an `impl` block.
1410struct ImplGenerationState<'p> {
1411   proto: &'p mut Prototype,
1412   has_constructor: bool,
1413   trait_index: Option<u16>,
1414}
1415
1416pub struct TraitBuilder<'b> {
1417   pub env: &'b mut Environment,
1418   parent_chunk: Option<&'b Chunk>,
1419   trait_id: Opr24,
1420   required_methods: HashSet<u16>,
1421   shims: Vec<(u16, Opr24)>,
1422}
1423
1424impl<'b> TraitBuilder<'b> {
1425   pub fn new(
1426      env: &'b mut Environment,
1427      parent_chunk: Option<&'b Chunk>,
1428      name: Rc<str>,
1429   ) -> Result<Self, ErrorKind> {
1430      let trait_id = env.create_trait(name)?;
1431      Ok(Self {
1432         env,
1433         parent_chunk,
1434         trait_id,
1435         required_methods: HashSet::new(),
1436         shims: vec![],
1437      })
1438   }
1439
1440   /// Generates the *shim* for a trait method. The shim is responsible for calling the actual
1441   /// method.
1442   fn generate_method_shim(
1443      &mut self,
1444      trait_name: &str,
1445      method_id: u16,
1446      method_signature: &FunctionSignature,
1447   ) -> Result<Opr24, ErrorKind> {
1448      let arity = method_signature.arity.unwrap() as u8;
1449
1450      let (module_name, codegen_location) = if let Some(parent_chunk) = self.parent_chunk {
1451         (
1452            Rc::clone(&parent_chunk.module_name),
1453            parent_chunk.codegen_location,
1454         )
1455      } else {
1456         (Rc::from("FFI"), Location::UNINIT)
1457      };
1458
1459      let mut chunk = Chunk::new(module_name);
1460      chunk.codegen_location = codegen_location;
1461      chunk.emit((Opcode::CallMethod, Opr24::pack((method_id, arity as u8))));
1462      chunk.emit(Opcode::Return);
1463
1464      let shim_name = Rc::from(format!(
1465         "trait {trait_name}.{} <shim>",
1466         method_signature.name
1467      ));
1468      let chunk = Rc::new(chunk);
1469      let function_id = self.env.create_function(Function {
1470         name: shim_name,
1471         parameter_count: method_signature.arity,
1472         kind: FunctionKind::Bytecode {
1473            chunk,
1474            captured_locals: vec![],
1475         },
1476         hidden_in_stack_traces: true,
1477      })?;
1478
1479      Ok(function_id)
1480   }
1481
1482   /// Adds a function into the trait and returns its method ID and function ID.
1483   ///
1484   /// The arity does not include the `self` parameter.
1485   pub fn add_method(&mut self, name: Rc<str>, arity: u16) -> Result<u16, ErrorKind> {
1486      let trait_name = Rc::clone(&self.env.get_trait(self.trait_id).unwrap().name);
1487      let signature = FunctionSignature {
1488         name,
1489         arity: Some(arity.checked_add(1).ok_or(ErrorKind::TooManyParameters)?),
1490         trait_id: Some(self.trait_id),
1491      };
1492      let method_id = self.env.get_method_index(&signature)?;
1493
1494      let shim_signature = FunctionSignature {
1495         // Add 2 for the receiving trait and self.
1496         arity: Some(arity.checked_add(2).ok_or(ErrorKind::TooManyParameters)?),
1497         trait_id: None,
1498         ..signature.clone()
1499      };
1500      let shim_method_id = self.env.get_method_index(&shim_signature)?;
1501      let shim_function_id = self.generate_method_shim(&trait_name, method_id, &signature)?;
1502      self.shims.push((shim_method_id, shim_function_id));
1503
1504      if !self.required_methods.insert(method_id) {
1505         return Err(ErrorKind::TraitAlreadyHasMethod(RenderedSignature {
1506            name: signature.name,
1507            arity: signature.arity,
1508            // Do not duplicate the trait name in the error message.
1509            trait_name: None,
1510         }));
1511      }
1512
1513      Ok(method_id)
1514   }
1515
1516   /// Finishes building the trait, returns its trait ID, and gives back the mutable reference to
1517   /// the environment.
1518   pub fn build(self) -> (Opr24, &'b mut Environment) {
1519      let prototype = self.env.get_trait_mut(self.trait_id).unwrap();
1520      prototype.required = self.required_methods;
1521      prototype.shims = self.shims;
1522      (self.trait_id, self.env)
1523   }
1524}