1mod card;
4mod compilation_error;
5mod compile_options;
6mod function;
7mod module;
8
9mod function_ir;
10#[cfg(test)]
11mod tests;
12
13use crate::{
14 bytecode::{encode_str, write_to_vec},
15 collections::{handle_table::Handle, hash_map::CaoHashMap},
16 compiled_program::{CaoCompiledProgram, Label},
17 prelude::Trace,
18 Instruction, VariableId,
19};
20use core::slice;
21use std::borrow::Cow;
22use std::convert::TryFrom;
23use std::fmt::Debug;
24use std::mem;
25use std::{convert::TryInto, str::FromStr};
26
27pub use card::*;
28pub use compilation_error::*;
29pub use compile_options::*;
30pub use function::*;
31pub use module::*;
32
33use self::function_ir::FunctionIr;
34
35pub type CompilationResult<T> = Result<T, CompilationError>;
36
37pub(crate) type FunctionSlice<'a> = &'a [FunctionIr];
41pub(crate) type NameSpace = smallvec::SmallVec<[Box<str>; 1]>;
42pub(crate) type ImportsIr = std::collections::HashMap<String, String>;
43pub(crate) type Locals<'a> = arrayvec::ArrayVec<Local<'a>, 255>;
44type Upvalues = arrayvec::ArrayVec<Upvalue, 255>;
45
46pub struct Compiler<'a> {
47 options: CompileOptions,
48 program: CaoCompiledProgram,
49 next_var: VariableId,
50
51 jump_table: CaoHashMap<String, FunctionMeta>,
53
54 current_namespace: Cow<'a, NameSpace>,
55 current_imports: Cow<'a, ImportsIr>,
56 locals: Vec<Locals<'a>>,
57 upvalues: Vec<Upvalues>,
58 scope_depth: Vec<i32>,
59 current_index: CardIndex,
60 function_id: usize,
61}
62
63#[derive(Debug, Clone, Copy)]
64struct FunctionMeta {
65 pub hash_key: Handle,
66 pub arity: u32,
68}
69
70#[derive(Debug)]
72pub(crate) struct Local<'a> {
73 pub name: &'a str,
74 pub depth: i32,
75 pub captured: bool,
76}
77
78pub fn compile(
79 compilation_unit: CaoProgram,
80 compile_options: impl Into<Option<CompileOptions>>,
81) -> CompilationResult<CaoCompiledProgram> {
82 let options = compile_options.into().unwrap_or_default();
83 let compilation_unit = compilation_unit
84 .into_ir_stream(options.recursion_limit)
85 .map_err(|err| CompilationError::with_loc(err, Trace::default()))?;
86
87 let mut compiler = Compiler::new();
88 compiler.compile(&compilation_unit, options)
89}
90
91impl<'a> Default for Compiler<'a> {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97enum Variable {
98 Global,
99 Local(usize),
100 Upvalue(usize),
102}
103
104#[derive(Default, Clone, Copy, Debug)]
105struct Upvalue {
106 is_local: bool,
107 index: u8,
108}
109
110impl<'a> Compiler<'a> {
111 pub fn new() -> Self {
112 Compiler {
113 options: Default::default(),
114 program: CaoCompiledProgram::default(),
115 next_var: VariableId(0),
116 jump_table: Default::default(),
117 current_namespace: Default::default(),
118 locals: vec![Default::default()],
119 upvalues: vec![Default::default()],
120 scope_depth: vec![0],
121 current_index: CardIndex::default(),
122 current_imports: Default::default(),
123 function_id: 0,
124 }
125 }
126
127 fn trace(&self) -> Trace {
128 Trace {
129 namespace: self.current_namespace.clone().into_owned(),
130 index: self.current_index.clone(),
131 }
132 }
133
134 pub fn compile(
135 &mut self,
136 compilation_unit: FunctionSlice<'a>,
137 compile_options: CompileOptions,
138 ) -> CompilationResult<CaoCompiledProgram> {
139 self.options = compile_options;
140 if compilation_unit.is_empty() {
141 return Err(CompilationError::with_loc(
142 CompilationErrorPayload::EmptyProgram,
143 self.trace(),
144 ));
145 }
146 self.program = CaoCompiledProgram::default();
147 self.next_var = VariableId(0);
148 self.compile_stage_1(compilation_unit)?;
149 self.compile_stage_2(compilation_unit)?;
150
151 self.current_imports = Default::default();
152 self.push_instruction(Instruction::Exit);
154 Ok(mem::take(&mut self.program))
155 }
156
157 fn error(&self, pl: CompilationErrorPayload) -> CompilationError {
158 CompilationError::with_loc(pl, self.trace())
159 }
160
161 fn compile_stage_1(&mut self, compilation_unit: FunctionSlice) -> CompilationResult<()> {
163 let mut num_cards = 0usize;
164 for n in compilation_unit.iter() {
165 num_cards += n.cards.len();
166 self.add_function(n)?;
167 }
168
169 self.program.labels.0.reserve(num_cards).expect("reserve");
170 Ok(())
171 }
172
173 fn add_function(&mut self, n: &FunctionIr) -> CompilationResult<()> {
174 let metadata = FunctionMeta {
175 hash_key: n.handle,
176 arity: n.arguments.len() as u32,
177 };
178 if self.jump_table.contains(n.name.as_ref()) {
179 return Err(self.error(CompilationErrorPayload::DuplicateName(n.name.to_string())));
180 }
181 self.jump_table.insert(n.full_name(), metadata).unwrap();
182 Ok(())
183 }
184
185 fn compile_stage_2(&mut self, compilation_unit: FunctionSlice<'a>) -> CompilationResult<()> {
187 let mut functions = compilation_unit.iter();
188
189 if let Some(main_function) = functions.next() {
190 let il = main_function.function_index;
191 let len: u32 = match main_function.cards.len().try_into() {
192 Ok(i) => i,
193 Err(_) => return Err(self.error(CompilationErrorPayload::TooManyCards(il))),
194 };
195 self.current_index = CardIndex::new(il, 0);
196 self.scope_begin();
197 self.process_function(main_function)?;
198 self.current_index = CardIndex {
199 function: il,
200 card_index: FunctionCardIndex {
201 indices: smallvec::smallvec![len],
202 },
203 };
204 self.scope_end();
205 self.process_card(&Card::Abort)?;
207 }
208
209 for function in functions {
210 let il = function.function_index;
211 self.current_index = CardIndex::function(il);
212 let nodeid_handle = function.handle;
213 let handle = u32::try_from(self.program.bytecode.len())
214 .expect("bytecode length to fit into 32 bits");
215 self.program
216 .labels
217 .0
218 .insert(nodeid_handle, Label::new(handle))
219 .unwrap();
220
221 self.scope_begin();
222 self.process_function(function)?;
223 self.scope_end();
224 self.push_instruction(Instruction::ScalarNil);
225 self.emit_return()?;
226 }
227
228 Ok(())
229 }
230
231 fn compile_begin(&mut self) {
233 self.function_id += 1;
234 self.locals.push(Default::default());
235 self.upvalues.push(Default::default());
236 self.scope_depth.push(0);
237 }
238
239 fn compile_end(&mut self) {
241 self.function_id -= 1;
242 self.locals.pop();
243 self.upvalues.pop();
244 self.scope_depth.pop();
245 }
246
247 fn scope_begin(&mut self) {
248 *self.scope_depth.last_mut().unwrap() += 1;
249 }
250
251 fn scope_depth(&self) -> i32 {
252 *self.scope_depth.last().unwrap()
253 }
254
255 fn scope_depth_mut(&mut self) -> &mut i32 {
256 self.scope_depth.last_mut().unwrap()
257 }
258
259 fn scope_end(&mut self) {
260 *self.scope_depth_mut() -= 1;
261 let scope_depth = self.scope_depth();
262 let locals = &mut self.locals[self.function_id];
263 while locals
264 .last()
265 .map(|l| l.depth > scope_depth)
266 .unwrap_or(false)
267 {
268 let var = locals.pop().unwrap();
269 if var.captured {
270 self.program.bytecode.push(Instruction::CloseUpvalue as u8);
271 } else {
272 self.program.bytecode.push(Instruction::Pop as u8);
273 }
274 }
275 }
276
277 fn add_local(&mut self, name: &'a str) -> CompilationResult<u32> {
281 self.validate_var_name(name)?;
282 self.add_local_unchecked(name)
283 }
284
285 fn add_upvalue(
286 &mut self,
287 index: u8,
288 is_local: bool,
289 function_id: usize,
290 ) -> CompilationResult<usize> {
291 let upvalues = &mut self.upvalues[function_id];
292 for (i, val) in upvalues.iter().enumerate() {
293 if val.index == index && val.is_local == is_local {
294 return Ok(i);
296 }
297 }
298 let i = upvalues.len();
299 upvalues.push(Upvalue { is_local, index });
300 Ok(i)
301 }
302
303 fn add_local_unchecked(&mut self, name: &'a str) -> CompilationResult<u32> {
304 let depth = self.scope_depth();
305 let locals = self.locals.last_mut().unwrap();
306 let result = locals.len();
307 locals
308 .try_push(Local {
309 name,
310 depth,
311 captured: false,
312 })
313 .map_err(|_| self.error(CompilationErrorPayload::TooManyLocals))?;
314 Ok(result as u32)
315 }
316
317 fn process_function(
318 &mut self,
319 FunctionIr {
320 arguments,
321 cards,
322 namespace,
323 imports,
324 ..
325 }: &'a FunctionIr,
326 ) -> CompilationResult<()> {
327 self.current_namespace = Cow::Borrowed(namespace);
328 self.current_imports = Cow::Borrowed(imports);
329
330 for param in arguments.iter().rev() {
332 self.add_local(param.as_str())?;
333 }
334 for (ic, card) in cards.iter().enumerate() {
335 self.current_index.pop_subindex();
337 self.current_index.push_subindex(ic as u32);
338 self.process_card(card)?;
339 }
340 Ok(())
341 }
342
343 fn emit_return(&mut self) -> CompilationResult<()> {
344 self.push_instruction(Instruction::Return);
345 Ok(())
346 }
347
348 fn encode_if_then(
350 &mut self,
351 skip_instr: Instruction,
352 then: impl FnOnce(&mut Self) -> CompilationResult<()>,
353 ) -> CompilationResult<()> {
354 type Pos = i32;
355 debug_assert!(
356 matches!(
357 skip_instr,
358 Instruction::GotoIfTrue | Instruction::GotoIfFalse
359 ),
360 "invalid skip instruction"
361 );
362 self.push_instruction(skip_instr);
363 let idx = self.program.bytecode.len();
364 write_to_vec(0 as Pos, &mut self.program.bytecode);
365
366 then(self)?;
368
369 unsafe {
370 let ptr = self.program.bytecode.as_mut_ptr().add(idx) as *mut Pos;
371 std::ptr::write_unaligned(ptr, self.program.bytecode.len() as Pos);
372 };
373 Ok(())
374 }
375
376 fn encode_jump(&mut self, function: &str) -> CompilationResult<()> {
377 let to = self.resolve_function(&self.jump_table, function)?;
378 write_to_vec(to.hash_key, &mut self.program.bytecode);
379 write_to_vec(to.arity, &mut self.program.bytecode);
380 Ok(())
381 }
382
383 fn resolve_function<'b>(
385 &self,
386 jump_table: &'b CaoHashMap<String, FunctionMeta>,
387 function: &str,
388 ) -> CompilationResult<&'b FunctionMeta> {
389 let mut to = jump_table.get(function);
391 if to.is_none() {
392 let name = self
396 .current_namespace
397 .iter()
398 .flat_map(|x| [x.as_ref(), "."])
399 .chain(std::iter::once(function))
400 .collect::<String>();
401
402 to = jump_table.get(&name);
403 }
404 if to.is_none() {
405 if let Some((_, alias)) = self
407 .current_imports
408 .iter()
409 .find(|(import, _)| *import == function)
410 {
411 let (super_depth, suffix) = super_depth(alias);
412 let name = self
413 .current_namespace
414 .iter()
415 .take(self.current_namespace.len() - super_depth)
416 .flat_map(|x| [x.as_ref(), "."])
417 .chain(std::iter::once(suffix.unwrap_or(alias)))
418 .collect::<String>();
419
420 to = jump_table.get(&name);
421 }
422 }
423 if to.is_none() {
424 if let Some((prefix, suffix)) = function.split_once('.') {
426 if let Some((_, alias)) = self
427 .current_imports
428 .iter()
429 .find(|(import, _)| *import == prefix)
430 {
431 let (super_depth, s) = super_depth(alias);
433
434 let name = self
435 .current_namespace
436 .iter()
437 .take(self.current_namespace.len() - super_depth)
438 .flat_map(|x| [x.as_ref(), "."])
439 .chain([alias, ".", s.unwrap_or(suffix)].iter().copied())
440 .collect::<String>();
441
442 to = jump_table.get(&name);
443 }
444 }
445 }
446 to.ok_or_else(|| {
447 self.error(CompilationErrorPayload::InvalidJump {
448 dst: function.to_string(),
449 msg: None,
450 })
451 })
452 }
453
454 fn push_str(&mut self, data: &str) {
455 let handle = self.program.data.len() as u32;
456 write_to_vec(handle, &mut self.program.bytecode);
457 encode_str(data, &mut self.program.data);
458 }
459
460 fn resolve_upvalue(&mut self, name: &str, function_id: usize) -> CompilationResult<Variable> {
462 if function_id == 0 {
463 return Ok(Variable::Global);
464 }
465
466 let locals = &mut self.locals[function_id - 1];
467 for (i, local) in locals.iter_mut().enumerate() {
469 if local.name == name {
470 local.captured = true;
471 return self
472 .add_upvalue(i as u8, true, function_id)
473 .map(Variable::Upvalue);
474 }
475 }
476 if function_id == 0 {
477 Ok(Variable::Global)
478 } else {
479 let val = self.resolve_upvalue(name, function_id - 1)?;
480 if let Variable::Upvalue(i) = &val {
481 let i = self.add_upvalue(*i as u8, false, function_id)?;
484 return Ok(Variable::Upvalue(i));
485 }
486 Ok(val)
487 }
488 }
489
490 fn resolve_var(&mut self, name: &str) -> CompilationResult<Variable> {
491 self.validate_var_name(name)?;
492
493 for (i, local) in self.locals[self.function_id].iter_mut().enumerate().rev() {
494 if local.name == name {
495 return Ok(Variable::Local(i));
496 }
497 }
498 self.resolve_upvalue(name, self.function_id)
499 }
500
501 fn process_card(&mut self, card: &'a Card) -> CompilationResult<()> {
502 let card_byte_index = u32::try_from(self.program.bytecode.len())
503 .expect("Expected bytecode length to fit into 32 bits");
504 let nodeid_hash = self.current_index.as_handle();
505 self.program
506 .labels
507 .0
508 .insert(nodeid_hash, Label::new(card_byte_index))
509 .unwrap();
510
511 match card {
512 Card::CompositeCard(comp) => {
513 for (i, card) in comp.cards.iter().enumerate() {
514 self.current_index.push_subindex(i as u32);
515 self.process_card(card)?;
516 self.current_index.pop_subindex()
517 }
518 }
519 Card::ForEach(fe) => {
520 let ForEach {
521 i,
522 k,
523 v,
524 iterable: variable,
525 body,
526 } = fe.as_ref();
527 self.current_index.push_subindex(0);
528 self.process_card(variable)?;
529 self.current_index.pop_subindex();
530
531 self.scope_begin();
532 let loop_var = self.add_local_unchecked("")?;
533 let loop_item = self.add_local_unchecked("")?;
534 let v_index = self.add_local_unchecked("")?;
536 let k_index = self.add_local_unchecked("")?;
537 let i_index = self.add_local_unchecked("")?;
538 self.push_instruction(Instruction::BeginForEach);
539 write_to_vec(loop_var, &mut self.program.bytecode);
540 write_to_vec(loop_item, &mut self.program.bytecode);
541 write_to_vec(i_index, &mut self.program.bytecode);
542 write_to_vec(k_index, &mut self.program.bytecode);
543 write_to_vec(v_index, &mut self.program.bytecode);
544
545 let block_begin = self.program.bytecode.len() as i32;
546 self.push_instruction(Instruction::ForEach);
547 write_to_vec(loop_var, &mut self.program.bytecode);
548 write_to_vec(loop_item, &mut self.program.bytecode);
549 write_to_vec(i_index, &mut self.program.bytecode);
550 write_to_vec(k_index, &mut self.program.bytecode);
551 write_to_vec(v_index, &mut self.program.bytecode);
552 self.encode_if_then(Instruction::GotoIfFalse, |c| {
553 c.scope_begin();
554 if let Some(v) = v {
555 let v = c.add_local(v)?;
556 c.read_local_var(v_index);
557 c.write_local_var(v);
558 }
559 if let Some(k) = k {
560 let k = c.add_local(k)?;
561 c.read_local_var(k_index);
562 c.write_local_var(k);
563 }
564 if let Some(i) = i {
565 let i = c.add_local(i)?;
566 c.read_local_var(i_index);
567 c.write_local_var(i);
568 }
569 c.current_index.push_subindex(1);
570 c.process_card(body)?;
571 c.current_index.pop_subindex();
572 c.scope_end();
573 c.push_instruction(Instruction::Goto);
575 write_to_vec(block_begin, &mut c.program.bytecode);
576 Ok(())
577 })?;
578 self.scope_end();
579 }
580 Card::While(children) => {
581 let [condition, body] = &**children;
582 let block_begin = self.program.bytecode.len() as i32;
583 self.current_index.push_subindex(0);
584 self.process_card(condition)?;
585 self.current_index.pop_subindex();
586 self.current_index.push_subindex(1);
587 self.encode_if_then(Instruction::GotoIfFalse, |c| {
589 c.process_card(body)?;
591 c.push_instruction(Instruction::Goto);
592 write_to_vec(block_begin, &mut c.program.bytecode);
593 Ok(())
594 })?;
595 self.current_index.pop_subindex();
596 }
597 Card::Repeat(rep) => {
598 self.current_index.push_subindex(0);
599 self.compile_subexpr(slice::from_ref(&rep.n))?;
600 self.current_index.pop_subindex();
601 let i = &rep.i;
602 let repeat = &rep.body;
603 self.scope_begin();
604 let loop_n_index = self.add_local_unchecked("")?;
605 let loop_counter_index = self.add_local_unchecked("")?;
606 self.write_local_var(loop_n_index);
607 self.process_card(&Card::ScalarInt(0))?;
609 self.write_local_var(loop_counter_index);
610
611 let block_begin = self.program.bytecode.len() as i32;
612 self.read_local_var(loop_counter_index);
614 self.read_local_var(loop_n_index);
615 self.push_instruction(Instruction::Less);
616 self.encode_if_then(Instruction::GotoIfFalse, |c| {
618 c.scope_begin();
619 if let Some(var) = i {
620 let i_index = c.add_local(var)?;
621 c.read_local_var(loop_counter_index);
622 c.write_local_var(i_index);
623 }
624 c.current_index.push_subindex(1);
625 c.process_card(repeat)?;
626 c.current_index.pop_subindex();
627 c.scope_end();
628 c.process_card(&Card::ScalarInt(1))?;
630 c.read_local_var(loop_counter_index);
631 c.push_instruction(Instruction::Add);
632 c.write_local_var(loop_counter_index);
633 c.push_instruction(Instruction::Goto);
635 write_to_vec(block_begin, &mut c.program.bytecode);
636 Ok(())
637 })?;
638 self.scope_end();
639 }
640 Card::ReadVar(variable) => {
641 self.read_var_card(variable)?;
642 }
643 Card::SetVar(var) => {
644 self.compile_subexpr(slice::from_ref(&var.value))?;
645 let var = var.name.as_str();
646 match var.rsplit_once('.') {
647 Some((read_props, set_prop)) => {
648 self.read_var_card(read_props)?;
649 self.push_instruction(Instruction::StringLiteral);
650 self.push_str(set_prop);
651 self.push_instruction(Instruction::SetProperty);
652 }
653 None => {
654 let index = match self.resolve_var(var)? {
655 Variable::Local(i) => i as u32,
656 Variable::Global => self.add_local(var)?,
657 Variable::Upvalue(i) => {
658 self.write_upvalue(i as u32);
659 return Ok(());
660 }
661 };
662
663 self.write_local_var(index);
664 }
665 }
666 }
667 Card::SetGlobalVar(var) => {
668 self.compile_subexpr(slice::from_ref(&var.value))?;
669 self.push_instruction(Instruction::SetGlobalVar);
670 let variable = var.name.as_str();
671 let next_var = &mut self.next_var;
672 if variable.is_empty() {
673 return Err(self.error(CompilationErrorPayload::EmptyVariable));
674 }
675 let varhash = Handle::from_bytes(variable.as_bytes());
676
677 let id = self
678 .program
679 .variables
680 .ids
681 .entry(varhash)
682 .or_insert_with(move || {
683 let id = *next_var;
684 *next_var = VariableId(id.0 + 1);
685 id
686 });
687 self.program
688 .variables
689 .names
690 .entry(Handle::from_u32(id.0))
691 .or_insert_with(move || variable.to_string());
692 write_to_vec(*id, &mut self.program.bytecode);
693 }
694 Card::IfElse(children) => {
695 let [condition, then_card, else_card] = &**children;
696 self.compile_subexpr(slice::from_ref(condition))?;
697
698 let mut idx = 0;
699 self.current_index.push_subindex(1);
700 self.encode_if_then(Instruction::GotoIfFalse, |c| {
701 c.process_card(then_card)?;
702 c.push_instruction(Instruction::Goto);
704 idx = c.program.bytecode.len();
705 write_to_vec(0xEEFi32, &mut c.program.bytecode);
706 Ok(())
707 })?;
708 self.current_index.pop_subindex();
709 self.current_index.push_subindex(2);
710 self.process_card(else_card)?;
711 self.current_index.pop_subindex();
712 unsafe {
713 let ptr = self.program.bytecode.as_mut_ptr().add(idx) as *mut i32;
714 std::ptr::write_unaligned(ptr, self.program.bytecode.len() as i32);
715 }
716 }
717 Card::IfFalse(jmp) => {
718 let [cond, body] = &**jmp;
719 self.compile_subexpr(slice::from_ref(cond))?;
720 self.current_index.push_subindex(1);
721 self.encode_if_then(Instruction::GotoIfTrue, |c| c.process_card(body))?;
722 self.current_index.pop_subindex();
723 }
724 Card::IfTrue(jmp) => {
725 let [cond, body] = &**jmp;
726 self.compile_subexpr(slice::from_ref(cond))?;
727 self.current_index.push_subindex(1);
728 self.encode_if_then(Instruction::GotoIfFalse, |c| c.process_card(body))?;
729 self.current_index.pop_subindex();
730 }
731 Card::Call(jmp) => {
732 self.compile_subexpr(&jmp.args.0)?;
733 self.push_instruction(Instruction::FunctionPointer);
734 self.encode_jump(jmp.function_name.as_str())?;
735 self.push_instruction(Instruction::CallFunction);
736 }
737 Card::StringLiteral(c) => {
738 self.push_instruction(Instruction::StringLiteral);
739 self.push_str(c.as_str())
740 }
741 Card::CallNative(c) => {
742 self.compile_subexpr(&c.args.0)?;
743 let name = &c.name;
744 let key = Handle::from_str(name.as_str()).unwrap();
745 self.push_instruction(Instruction::CallNative);
746 write_to_vec(key, &mut self.program.bytecode);
747 }
748 Card::ScalarInt(s) => {
749 self.push_instruction(Instruction::ScalarInt);
750 write_to_vec(*s, &mut self.program.bytecode);
751 }
752 Card::ScalarFloat(s) => {
753 self.push_instruction(Instruction::ScalarFloat);
754 write_to_vec(*s, &mut self.program.bytecode);
755 }
756 Card::Function(fname) => {
757 self.push_instruction(Instruction::FunctionPointer);
758 self.encode_jump(fname)?;
759 }
760 Card::Closure(embedded_function) => {
761 self.push_instruction(Instruction::Goto);
765 let goto_index = self.program.bytecode.len();
766 write_to_vec(0xEEFi32, &mut self.program.bytecode);
767
768 self.compile_begin();
769 const CLOSURE_MASK: u64 = 0xEFEFEFEF;
770 let function_handle =
771 self.current_index.as_handle() + Handle::from_u64(CLOSURE_MASK);
772 let arity = embedded_function.arguments.len() as u32;
773 let handle = u32::try_from(self.program.bytecode.len())
774 .expect("bytecode length to fit into 32 bits");
775 self.program
776 .labels
777 .0
778 .insert(function_handle, Label::new(handle))
779 .unwrap();
780
781 self.scope_begin();
783 for param in embedded_function.arguments.iter().rev() {
786 self.add_local(param.as_str())?;
787 }
788 self.compile_subexpr(&embedded_function.cards)?;
789 self.scope_end();
790 self.push_instruction(Instruction::ScalarNil);
791 self.emit_return()?;
792
793 unsafe {
795 let ptr = self.program.bytecode.as_mut_ptr().add(goto_index) as *mut i32;
796 std::ptr::write_unaligned(ptr, self.program.bytecode.len() as i32);
797 }
798
799 self.push_instruction(Instruction::Closure);
802 write_to_vec(function_handle, &mut self.program.bytecode);
803 write_to_vec(arity, &mut self.program.bytecode);
804 let upvalues = std::mem::take(&mut self.upvalues[self.function_id]);
805 for upvalue in upvalues {
806 self.push_instruction(Instruction::CopyLast);
807 self.push_instruction(Instruction::RegisterUpvalue);
808 write_to_vec(upvalue.index, &mut self.program.bytecode);
809 write_to_vec(upvalue.is_local as u8, &mut self.program.bytecode);
810 }
811 self.compile_end();
812 }
813 Card::NativeFunction(fname) => {
814 self.push_instruction(Instruction::NativeFunctionPointer);
815 self.push_str(fname.as_str());
816 }
817 Card::Array(expressions) => {
818 self.push_instruction(Instruction::InitTable);
822 let table_var = self.add_local_unchecked("")?;
823 self.write_local_var(table_var);
824 for (i, card) in expressions.iter().enumerate() {
825 self.push_instruction(Instruction::ScalarNil);
828 self.current_index.push_subindex(i as u32);
829 self.process_card(card)?;
830 self.current_index.pop_subindex();
831 self.read_local_var(table_var);
832 self.push_instruction(Instruction::AppendTable);
833 }
834 self.read_local_var(table_var);
836 }
837 Card::Len(expr) => {
838 self.compile_subexpr(slice::from_ref(expr.card.as_ref()))?;
839 self.push_instruction(Instruction::Len);
840 }
841 Card::Return(expr) => {
842 self.compile_subexpr(slice::from_ref(expr.card.as_ref()))?;
843 self.emit_return()?;
844 }
845 Card::Not(expr) => {
846 self.compile_subexpr(slice::from_ref(expr.card.as_ref()))?;
847 self.push_instruction(Instruction::Not);
848 }
849 Card::Get(expr) => {
850 self.compile_subexpr(expr.as_ref())?;
851 self.push_instruction(Instruction::NthRow);
852 }
853 Card::And(expr) => {
854 self.compile_subexpr(expr.as_ref())?;
855 self.push_instruction(Instruction::And);
856 }
857 Card::Or(expr) => {
858 self.compile_subexpr(expr.as_ref())?;
859 self.push_instruction(Instruction::Or);
860 }
861 Card::Xor(expr) => {
862 self.compile_subexpr(expr.as_ref())?;
863 self.push_instruction(Instruction::Xor);
864 }
865 Card::Equals(expr) => {
866 self.compile_subexpr(expr.as_ref())?;
867 self.push_instruction(Instruction::Equals);
868 }
869 Card::Less(expr) => {
870 self.compile_subexpr(expr.as_ref())?;
871 self.push_instruction(Instruction::Less);
872 }
873 Card::LessOrEq(expr) => {
874 self.compile_subexpr(expr.as_ref())?;
875 self.push_instruction(Instruction::LessOrEq);
876 }
877 Card::NotEquals(expr) => {
878 self.compile_subexpr(expr.as_ref())?;
879 self.push_instruction(Instruction::NotEquals);
880 }
881 Card::Add(expr) => {
882 self.compile_subexpr(expr.as_ref())?;
883 self.push_instruction(Instruction::Add);
884 }
885 Card::Sub(expr) => {
886 self.compile_subexpr(expr.as_ref())?;
887 self.push_instruction(Instruction::Sub);
888 }
889 Card::Mul(expr) => {
890 self.compile_subexpr(expr.as_ref())?;
891 self.push_instruction(Instruction::Mul);
892 }
893 Card::Div(expr) => {
894 self.compile_subexpr(expr.as_ref())?;
895 self.push_instruction(Instruction::Div);
896 }
897 Card::GetProperty(expr) => {
898 self.compile_subexpr(expr.as_ref())?;
899 self.push_instruction(Instruction::GetProperty);
900 }
901 Card::SetProperty(expr) => {
902 self.compile_subexpr(expr.as_ref())?;
903 self.push_instruction(Instruction::SetProperty);
904 }
905 Card::AppendTable(expr) => {
906 self.compile_subexpr(expr.as_ref())?;
907 self.push_instruction(Instruction::AppendTable);
908 }
909 Card::PopTable(expr) => {
910 self.compile_subexpr(slice::from_ref(expr.card.as_ref()))?;
911 self.push_instruction(Instruction::PopTable);
912 }
913 Card::DynamicCall(jump) => {
914 self.compile_subexpr(jump.args.0.as_slice())?;
915 self.current_index.push_subindex(jump.args.0.len() as u32);
916 self.process_card(&jump.function)?;
917 self.current_index.pop_subindex();
918 self.push_instruction(Instruction::CallFunction);
919 }
920 Card::ScalarNil => {
921 self.push_instruction(Instruction::ScalarNil);
922 }
923 Card::Abort => {
924 self.push_instruction(Instruction::Exit);
925 }
926 Card::CreateTable => {
927 self.push_instruction(Instruction::InitTable);
928 }
929 Card::Comment(_) => {
930 }
932 }
933 Ok(())
934 }
935
936 fn read_var_card(&mut self, mut variable: &str) -> CompilationResult<()> {
937 let props = match variable.split_once('.') {
939 Some((v, props)) => {
940 variable = v;
941 props
942 }
943 None => "",
944 };
945 let scope = self.resolve_var(variable)?;
946 match scope {
947 Variable::Local(index) => {
948 self.read_local_var(index as u32);
949 }
950 Variable::Upvalue(index) => {
951 self.read_upvalue(index as u32);
952 }
953 Variable::Global => {
954 let next_var = &mut self.next_var;
955 let varhash = Handle::from_bytes(variable.as_bytes());
956 let id = *self
957 .program
958 .variables
959 .ids
960 .entry(varhash)
961 .or_insert_with(move || {
962 let id = *next_var;
963 *next_var = VariableId(id.0 + 1);
964 id
965 });
966 self.program
967 .variables
968 .names
969 .entry(Handle::from_u32(id.0))
970 .or_insert_with(|| variable.to_string());
971 self.push_instruction(Instruction::ReadGlobalVar);
972 write_to_vec(id, &mut self.program.bytecode);
973 }
974 }
975 for prop in props.split('.').filter(|p| !p.is_empty()) {
977 self.push_instruction(Instruction::StringLiteral);
978 self.push_str(prop);
979 self.push_instruction(Instruction::GetProperty);
980 }
981 Ok(())
982 }
983
984 fn read_local_var(&mut self, index: u32) {
985 self.push_instruction(Instruction::ReadLocalVar);
986 write_to_vec(index, &mut self.program.bytecode);
987 }
988
989 fn write_local_var(&mut self, index: u32) {
990 self.push_instruction(Instruction::SetLocalVar);
991 write_to_vec(index, &mut self.program.bytecode);
992 }
993
994 fn read_upvalue(&mut self, index: u32) {
995 self.push_instruction(Instruction::ReadUpvalue);
996 write_to_vec(index, &mut self.program.bytecode);
997 }
998
999 fn write_upvalue(&mut self, index: u32) {
1000 self.push_instruction(Instruction::SetUpvalue);
1001 write_to_vec(index, &mut self.program.bytecode);
1002 }
1003
1004 fn validate_var_name(&self, name: &str) -> CompilationResult<()> {
1005 if name.is_empty() {
1006 return Err(self.error(CompilationErrorPayload::EmptyVariable));
1007 }
1008 Ok(())
1009 }
1010
1011 fn push_instruction(&mut self, instruction: Instruction) {
1012 self.program
1013 .trace
1014 .insert(self.program.bytecode.len() as u32, self.trace())
1015 .unwrap();
1016 self.program.bytecode.push(instruction as u8);
1017 }
1018
1019 fn compile_subexpr(&mut self, cards: &'a [Card]) -> CompilationResult<()> {
1020 for (i, card) in cards.iter().enumerate() {
1021 self.current_index.push_subindex(i as u32);
1022 self.process_card(card)?;
1023 self.current_index.pop_subindex();
1024 }
1025 Ok(())
1026 }
1027}
1028
1029fn super_depth(import: &str) -> (usize, Option<&str>) {
1030 let mut super_pog = import.split_once("super.");
1031 let mut super_cnt = 0;
1032 let mut suffix = None;
1033 while let Some((_sup_pre, sup_post)) = super_pog {
1034 super_cnt += 1;
1035 super_pog = sup_post.split_once("super.");
1036 suffix = Some(sup_post);
1037 }
1038
1039 (super_cnt, suffix)
1040}