1use 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#[derive(Debug)]
16struct Variable {
17 stack_slot: Opr24,
18 is_captured: bool,
19}
20
21#[derive(Debug, Default)]
22struct Scope {
23 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37enum VariableAllocation {
38 Inherit,
40 Allocate,
42}
43
44#[derive(Default)]
46struct Locals {
47 parent: Option<Box<Self>>,
50
51 scopes: Vec<Scope>,
52 local_count: u32,
54 allocated_local_count: u32,
57
58 captures: Vec<CaptureKind>,
60}
61
62impl Locals {
63 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 fn capture_index(&mut self, capture: CaptureKind) -> Result<Opr24, ErrorKind> {
97 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 fn lookup(&mut self, name: &str) -> Result<Option<VariablePlace>, ErrorKind> {
110 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 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 fn push_scope(&mut self) {
144 self.scopes.push(Default::default());
145 }
146
147 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 breaks: Vec<usize>,
160 start: usize,
161}
162
163#[derive(Debug, Default)]
164struct StructData {
165 fields: HashMap<Rc<str>, Opr24>,
167 receiver: Option<VariablePlace>,
169}
170
171impl StructData {
172 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 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 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 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 fn lookup_variable(&mut self, name: &str) -> Result<Option<VariablePlace>, ErrorKind> {
248 if let Some(place) = self.locals.lookup(name)? {
250 return Ok(Some(place));
251 }
252 Ok(self.env.get_global(name).map(VariablePlace::Global))
254 }
255
256 fn push_scope(&mut self) {
258 self.locals.push_scope();
259 }
260
261 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 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 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 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 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 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 self.chunk.patch(jump, Opcode::jump_forward(jump, self.chunk.len()).unwrap());
316 }
317 self.chunk.emit((Opcode::ExitBreakableBlock, 1));
318 }
319 }
320
321 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 fn generate_nil(&mut self) -> ExpressionResult {
345 self.chunk.emit(Opcode::PushNil);
346 ExpressionResult::Present
347 }
348
349 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let (condition, _) = ast.node_pair(branch);
584 self.push_scope();
585 self.generate_node(ast, condition, Expression::Used)?;
586 let jump = self.chunk.emit(Opcode::Nop);
588 self.chunk.emit(Opcode::Discard); 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 ast.kind(*branches.last().unwrap()) != NodeKind::ElseBranch {
612 self.chunk.emit(Opcode::Discard);
613 self.chunk.emit(Opcode::PushNil);
614 }
615
616 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 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 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 self.push_scope();
671 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 self.chunk.emit(Opcode::Discard);
679
680 generate_body(self)?;
681 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 self.chunk.emit(Opcode::Discard);
695
696 self.chunk.emit(Opcode::PushNil);
698
699 self.pop_breakable_block();
702 self.pop_scope();
703
704 Ok(())
705 }
706
707 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 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 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 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 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 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 let arity: u8 = (1 + arguments.len())
801 .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 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 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 generator.push_scope();
866 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 ¶meter 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 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 generator.generate_node(ast, body, Expression::Used)?;
901
902 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 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 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 generator.pop_scope();
931 generator.chunk.emit(Opcode::Return);
932
933 self.locals = generator.locals.parent.take().unwrap();
935 if call_conv.has_field_access() {
936 self.struct_data = generator.struct_data;
937 }
938
939 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 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 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 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 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 fn generate_return(&mut self, ast: &Ast, node: NodeId) -> Result<ExpressionResult, Error> {
1029 let (value, _) = ast.node_pair(node);
1030 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 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 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 self.generate_node(ast, implementee, Expression::Used)?;
1063
1064 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 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 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 trait_name: None,
1136 }),
1137 ));
1138 }
1139 } else {
1140 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 _ => return Err(ast.error(node, ErrorKind::InvalidImplItem)),
1190 }
1191
1192 Ok(())
1193 }
1194
1195 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 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 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#[derive(Debug, Clone, Copy)]
1342enum FunctionCallConv {
1343 Bare,
1345 Static,
1347 Instance,
1349 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1391enum Expression {
1392 Discarded,
1394 Used,
1396}
1397
1398#[must_use]
1399#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1400enum ExpressionResult {
1401 Present,
1403 Absent,
1405 NoReturn,
1407}
1408
1409struct 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 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 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 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 trait_name: None,
1510 }));
1511 }
1512
1513 Ok(method_id)
1514 }
1515
1516 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}