1use crate::compiler::Helpers;
2use crate::error::{Error, Result as InternalResult, SemanticsErrorContext};
3use crate::optimizer::optimize;
4use crate::types::*;
5
6use bpf_ins::{Instruction, MemoryOpLoadType, Register};
7use peginator::PegParser;
8use peginator_macro::peginate;
9
10use std::collections::HashMap;
11use std::str::FromStr;
12
13peginate!(
14 "
15@export
16ScriptDef = input:InputLine {NewLine exprs:Expression}$;
17
18InputLine = 'fn' '(' [args:TypedArgument {',' args:TypedArgument}] ')';
19TypedArgument = name:Ident ':' type_name:TypeDecl;
20TypeDecl = [is_ref:ReferencePrefix] name:Ident;
21
22Expression = @:Assignment | @:FunctionCall | @:Return;
23
24Assignment = left:LValue [':' type_name:TypeDecl] '=' right:RValue;
25FunctionCall = name:Ident '(' [args:RValue {',' args:RValue}] ')';
26Return = 'return' [value:RValue];
27
28Condition = left:LValue WhiteSpace op:Comparator WhiteSpace right:RValue;
29
30RValue = @:FunctionCall | @:Immediate | @:LValue;
31LValue = [prefix:Prefix] name:Ident {derefs:DeReference};
32
33DeReference = @:FieldAccess | @:ArrayIndex;
34
35FieldAccess = '.' name:Ident;
36ArrayIndex = '[' element:Immediate ']';
37
38@string
39Immediate = {'0'..'9'}+;
40
41Comparator = @:Equals | @:NotEquals | @:LessThan | @:GreaterThan | @:LessOrEqual | @:GreaterOrEqual;
42Equals = '==';
43NotEquals = '!=';
44LessThan = '<';
45GreaterThan = '>';
46LessOrEqual = '<=';
47GreaterOrEqual = '>=';
48ReferencePrefix = '&';
49DeReferencePrefix = '*';
50
51Prefix = @:ReferencePrefix | @:DeReferencePrefix;
52
53@string
54@no_skip_ws
55Ident = {'a'..'z' | 'A'..'Z' | '_' | '0'..'9'}+;
56
57@string
58@no_skip_ws
59WhiteSpace = {' ' | '\t'};
60
61@string
62@no_skip_ws
63NewLine = {'\r' | '\n' | '\r\n'};
64"
65);
66
67macro_rules! semantics_bail {
68 ($line: expr, $($message:expr),+) => {
69 return Err(Error::Semantics {
70 line: $line,
71 message: format!($($message),+)
72 });
73 };
74}
75
76#[derive(Clone, Copy, Debug)]
77enum VariableLocation {
78 SpecialImmediate(u32),
79 Stack(i16),
80}
81
82#[derive(Clone, Debug)]
83struct VariableInfo {
84 var_type: Type,
85 location: VariableLocation,
86}
87
88pub struct Compiler<'a> {
89 types: &'a TypeDatabase,
90 variables: HashMap<String, VariableInfo>,
91 instructions: Vec<Instruction>,
92 stack: u32,
93 expr_num: u32,
94}
95
96impl<'a> Compiler<'a> {
97 const MAX_STACK_SIZE: u32 = 4096;
98
99 pub fn create(types: &'a TypeDatabase) -> Self {
114 Self {
115 types,
116 variables: HashMap::new(),
117 instructions: vec![],
118 stack: 0,
119 expr_num: 1,
120 }
121 }
122
123 pub fn capture(&mut self, name: &str, value: i64) {
149 let info = VariableInfo {
150 var_type: BaseType::Integer(Integer {
151 used_bits: 64,
152 bits: 64,
153 is_signed: false,
154 })
155 .into(),
156 location: VariableLocation::SpecialImmediate(value as u32),
157 };
158 self.variables.insert(name.to_string(), info);
159 }
160
161 fn type_from_decl(&mut self, decl: &TypeDecl) -> InternalResult<Type> {
168 let mut ty = self
169 .types
170 .get_type_by_name(&decl.name)
171 .context(
172 self.expr_num,
173 &format!("Type with name \"{}\" doesn't exist", decl.name),
174 )?
175 .clone();
176
177 if matches!(decl.is_ref, Some(ReferencePrefix)) {
178 ty.num_refs += 1;
179 }
180 Ok(ty)
181 }
182
183 fn get_variable_by_name(&mut self, name: &str) -> InternalResult<VariableInfo> {
190 if let Some(info) = self.variables.get(name) {
191 return Ok(info.clone());
192 }
193
194 semantics_bail!(self.expr_num, "No variable with name \"{}\"", name);
195 }
196
197 fn parse_immediate<T: FromStr>(&mut self, s: &str) -> InternalResult<T> {
204 if let Ok(imm) = s.parse::<T>() {
205 return Ok(imm);
206 }
207
208 semantics_bail!(self.expr_num, "Failed to parse immediate value \"{}\"", s);
209 }
210
211 fn get_stack(&self) -> i16 {
213 -(self.stack as i16)
214 }
215
216 fn push_stack(&mut self, size: u32) -> InternalResult<i16> {
224 if self.stack + size > Self::MAX_STACK_SIZE {
225 semantics_bail!(
226 self.expr_num,
227 "Stack size exceeded {} bytes with this assignment",
228 Self::MAX_STACK_SIZE
229 );
230 }
231
232 self.stack += size;
233 Ok(self.get_stack())
234 }
235
236 fn emit_init_stack_range(&mut self, mut offset: i16, value: i8, mut size: u32) {
245 let value = value as i64;
246 let v64 = value
247 | value << 8
248 | value << 16
249 | value << 24
250 | value << 32
251 | value << 40
252 | value << 48
253 | value << 56;
254 let mut remaining = size;
255 for _ in 0..size / 8 {
256 self.instructions
257 .push(Instruction::store64(Register::R10, offset, v64));
258 remaining -= 8;
259 offset += 8;
260 }
261 size = remaining;
262
263 for _ in 0..size / 4 {
264 self.instructions
265 .push(Instruction::store32(Register::R10, offset, v64 as i32));
266 remaining -= 4;
267 offset += 4;
268 }
269 size = remaining;
270
271 for _ in 0..size / 2 {
272 self.instructions
273 .push(Instruction::store16(Register::R10, offset, v64 as i16));
274 remaining -= 2;
275 offset += 2;
276 }
277 size = remaining;
278
279 for _ in 0..size {
280 self.instructions
281 .push(Instruction::store8(Register::R10, offset, v64 as i8));
282 remaining -= 1;
283 offset += 1;
284 }
285 }
286
287 fn emit_push_immediate(
295 &mut self,
296 imm_str: &str,
297 cast_type: &Type,
298 use_offset: Option<i16>,
299 ) -> InternalResult<(i16, Type)> {
300 let size = cast_type.get_size();
301 if size == 0 && !matches!(cast_type.base_type, BaseType::Void) {
302 semantics_bail!(self.expr_num, "Can't assign to zero-sized type");
303 }
304
305 let offset = match use_offset {
306 Some(off) => off,
307 None => self.push_stack(size)?,
308 };
309
310 if cast_type.is_pointer() {
311 let imm = self.parse_immediate::<u8>(imm_str)?;
312 self.instructions
313 .push(Instruction::store8(Register::R10, offset, imm as i8));
314 return Ok((offset, cast_type.clone()));
315 }
316
317 if matches!(cast_type.base_type, BaseType::Void) {
319 let imm = self.parse_immediate::<i64>(imm_str)?;
320 self.instructions
321 .push(Instruction::store64(Register::R10, offset, imm));
322 let new_type = BaseType::Integer(Integer {
323 used_bits: 64,
324 bits: 64,
325 is_signed: false,
326 });
327 return Ok((offset, new_type.into()));
328 }
329
330 if let BaseType::Integer(integer) = &cast_type.base_type {
331 match (size, integer.is_signed) {
332 (1, false) => {
333 let imm = self.parse_immediate::<u8>(imm_str)?;
334 self.instructions
335 .push(Instruction::store8(Register::R10, offset, imm as i8));
336 }
337 (1, true) => {
338 let imm = self.parse_immediate::<i8>(imm_str)?;
339 self.instructions
340 .push(Instruction::store8(Register::R10, offset, imm));
341 }
342 (2, false) => {
343 let imm = self.parse_immediate::<u16>(imm_str)?;
344 self.instructions
345 .push(Instruction::store16(Register::R10, offset, imm as i16));
346 }
347 (2, true) => {
348 let imm = self.parse_immediate::<i16>(imm_str)?;
349 self.instructions
350 .push(Instruction::store16(Register::R10, offset, imm));
351 }
352 (4, false) => {
353 let imm = self.parse_immediate::<u32>(imm_str)?;
354 self.instructions
355 .push(Instruction::store32(Register::R10, offset, imm as i32));
356 }
357 (4, true) => {
358 let imm = self.parse_immediate::<i32>(imm_str)?;
359 self.instructions
360 .push(Instruction::store32(Register::R10, offset, imm));
361 }
362 (8, false) => {
363 let imm = self.parse_immediate::<u64>(imm_str)?;
364 self.instructions
365 .push(Instruction::store64(Register::R10, offset, imm as i64));
366 }
367 (8, true) => {
368 let imm = self.parse_immediate::<i64>(imm_str)?;
369 self.instructions
370 .push(Instruction::store64(Register::R10, offset, imm));
371 }
372 (bits, _) => {
373 semantics_bail!(self.expr_num, "{}-bit integers not supported", bits);
374 }
375 };
376 } else {
377 let imm = self.parse_immediate::<i8>(imm_str)?;
378 self.emit_init_stack_range(offset, imm, size);
379 }
380
381 Ok((offset, cast_type.clone()))
382 }
383
384 fn emit_push_register(&mut self, reg: Register, offset: Option<i16>) -> InternalResult<i16> {
392 let offset = if let Some(offset) = offset {
393 offset
394 } else {
395 self.push_stack(8)?
396 };
397
398 self.instructions
399 .push(Instruction::storex64(Register::R10, offset, reg));
400 Ok(offset)
401 }
402
403 fn emit_deref_register_to_stack(&mut self, reg: Register, deref_type: &Type, offset: i16) {
414 self.instructions
415 .push(Instruction::movx64(Register::R1, Register::R10));
416 self.instructions
417 .push(Instruction::add64(Register::R1, offset.into()));
418 self.instructions.push(Instruction::mov64(
419 Register::R2,
420 deref_type.get_size() as i32,
421 ));
422 self.instructions
423 .push(Instruction::movx64(Register::R3, reg));
424 self.instructions
425 .push(Instruction::call(Helpers::ProbeRead as u32));
426 }
427
428 fn emit_push_lvalue(
438 &mut self,
439 lval: &LValue,
440 cast_type: &Type,
441 use_offset: Option<i16>,
442 ) -> InternalResult<(i16, Type)> {
443 let var_type = self.emit_set_register_to_lvalue_addr(Register::R6, lval)?;
446
447 let mut real_type = if matches!(cast_type.base_type, BaseType::Void) {
449 var_type.clone()
450 } else {
451 cast_type.clone()
452 };
453
454 if real_type.get_size() != var_type.get_size() {
456 semantics_bail!(self.expr_num, "Cannot assign two types of different sizes");
457 }
458
459 let offset = match use_offset {
461 Some(off) => off,
462 None => self.push_stack(real_type.get_size())?,
463 };
464
465 match lval.prefix {
467 None => self.emit_deref_register_to_stack(Register::R6, &real_type, offset),
468 Some(Prefix::DeReferencePrefix(_)) => {
469 semantics_bail!(self.expr_num, "Dereferencing is not currently supported");
470 }
471 Some(Prefix::ReferencePrefix(_)) => {
472 real_type.num_refs += 1;
473 self.instructions
474 .push(Instruction::storex64(Register::R10, offset, Register::R6));
475 }
476 }
477
478 Ok((offset, real_type.clone()))
479 }
480
481 fn emit_push_rvalue(
491 &mut self,
492 rval: &RValue,
493 cast_type: &Type,
494 use_offset: Option<i16>,
495 ) -> InternalResult<(i16, Type)> {
496 match rval {
497 RValue::Immediate(imm_str) => self.emit_push_immediate(imm_str, cast_type, use_offset),
498 RValue::LValue(lval) => self.emit_push_lvalue(lval, cast_type, use_offset),
499 RValue::FunctionCall(call) => {
500 if let BaseType::Integer(integer) = &cast_type.base_type {
501 if integer.get_size() != 8 {
502 semantics_bail!(
503 self.expr_num,
504 "Function return values can only be stored in 64-bit types"
505 );
506 }
507
508 self.emit_call(call)?;
509 let offset = self.emit_push_register(Register::R0, use_offset)?;
510 Ok((offset, cast_type.clone()))
511 } else {
512 semantics_bail!(
513 self.expr_num,
514 "Function return values can only be stored in integer types"
515 );
516 }
517 }
518 }
519 }
520
521 fn get_field_access(
528 &mut self,
529 structure: &Type,
530 field_name: &str,
531 ) -> InternalResult<(u32, Type)> {
532 let structure = if let BaseType::Struct(structure) = &structure.base_type {
533 structure
534 } else {
535 semantics_bail!(self.expr_num, "Can't field-deref a non-structure type");
536 };
537
538 let field = structure.fields.get(field_name).context(
539 self.expr_num,
540 &format!("Field \"{}\" doesn't exist on type", field_name),
541 )?;
542
543 if field.offset % 8 != 0 {
544 semantics_bail!(self.expr_num, "Bit-field accesses not supported");
545 }
546
547 let field_type = self
548 .types
549 .get_type_by_id(field.type_id)
550 .context(self.expr_num, "Internal error; type id invalid")?;
551 Ok((field.offset / 8, field_type.clone()))
552 }
553
554 fn get_array_index(&mut self, array: &Type, index: &str) -> InternalResult<(u32, Type)> {
561 let array = if let BaseType::Array(array) = &array.base_type {
562 array
563 } else {
564 semantics_bail!(self.expr_num, "Can't array-deref a non-array type");
565 };
566
567 let index = self.parse_immediate::<u32>(index)?;
568 if index > array.num_elements {
569 semantics_bail!(
570 self.expr_num,
571 "Out-of-bounds array access {}/{}",
572 index,
573 array.num_elements
574 );
575 }
576
577 let element_type = self
578 .types
579 .get_type_by_id(array.element_type_id)
580 .context(self.expr_num, "Internal error; type id invalid")?;
581
582 let offset = element_type.get_size() * index;
583 Ok((offset, element_type.clone()))
584 }
585
586 fn get_deref_offset(
593 &mut self,
594 ty: &Type,
595 derefs: &[DeReference],
596 ) -> InternalResult<(i16, Type)> {
597 let mut offset = 0;
598 let mut cur_type = ty.clone();
599 for deref in derefs.iter() {
600 if cur_type.is_pointer() {
601 semantics_bail!(
602 self.expr_num,
603 "Can't deref an offset through an indirection"
604 );
605 }
606
607 let (off, ty) = match deref {
608 DeReference::FieldAccess(ma) => self.get_field_access(&cur_type, &ma.name)?,
609 DeReference::ArrayIndex(ai) => self.get_array_index(&cur_type, &ai.element)?,
610 };
611
612 offset += off;
613 cur_type = ty;
614 }
615
616 let offset: i16 = offset
617 .try_into()
618 .context(self.expr_num, "Type is too large to deref")?;
619 Ok((offset, cur_type))
620 }
621
622 fn emit_assign(&mut self, assign: &Assignment) -> InternalResult<()> {
628 let mut new_variable = true;
629 let (cast_type, use_offset) =
630 if let Ok(info) = &self.get_variable_by_name(&assign.left.name) {
631 if assign.type_name.is_some() {
632 semantics_bail!(
633 self.expr_num,
634 "Can't re-type \"{}\" after first assignment",
635 assign.left.name
636 );
637 } else if let VariableLocation::Stack(off) = info.location {
638 let (rel_off, offset_type) =
639 self.get_deref_offset(&info.var_type, &assign.left.derefs)?;
640 new_variable = false;
641 (offset_type, Some(off + rel_off))
642 } else {
643 semantics_bail!(
644 self.expr_num,
645 "Variable \"{}\" cannot be re-assigned",
646 assign.left.name
647 );
648 }
649 } else if let Some(type_name) = &assign.type_name {
650 let assign_type = self.type_from_decl(type_name)?;
651 (assign_type, None)
652 } else {
653 (Default::default(), None)
654 };
655
656 let (offset, new_type) = self.emit_push_rvalue(&assign.right, &cast_type, use_offset)?;
657
658 if new_variable {
659 self.variables.insert(
660 assign.left.name.clone(),
661 VariableInfo {
662 var_type: new_type,
663 location: VariableLocation::Stack(offset),
664 },
665 );
666 }
667
668 Ok(())
669 }
670
671 fn emit_field_access(
680 &mut self,
681 reg: Register,
682 structure: &Type,
683 field_access: &FieldAccess,
684 ) -> InternalResult<Type> {
685 let (offset, field_type) = self.get_field_access(structure, &field_access.name)?;
686 if offset > 0 {
687 self.instructions
688 .push(Instruction::add64(reg, offset as i32));
689 }
690 Ok(field_type)
691 }
692
693 fn emit_index_array(
702 &mut self,
703 reg: Register,
704 array: &Type,
705 index: &ArrayIndex,
706 ) -> InternalResult<Type> {
707 let (offset, element_type) = self.get_array_index(array, &index.element)?;
708 if offset > 0 {
709 self.instructions
710 .push(Instruction::add64(reg, offset as i32));
711 }
712 Ok(element_type)
713 }
714
715 fn emit_apply_derefs_to_reg(
725 &mut self,
726 reg: Register,
727 var_type: &Type,
728 derefs: &[DeReference],
729 ) -> InternalResult<Type> {
730 if derefs.is_empty() {
731 return Ok(var_type.clone());
732 }
733
734 if var_type.is_pointer() {
738 self.instructions.push(Instruction::loadx64(reg, reg, 0));
739 }
740
741 let next_type = match &derefs[0] {
742 DeReference::FieldAccess(ma) => self.emit_field_access(reg, var_type, ma)?,
743 DeReference::ArrayIndex(ai) => self.emit_index_array(reg, var_type, ai)?,
744 };
745
746 self.emit_apply_derefs_to_reg(reg, &next_type, &derefs[1..])
747 }
748
749 fn emit_set_register_to_lvalue_addr(
759 &mut self,
760 reg: Register,
761 lval: &LValue,
762 ) -> InternalResult<Type> {
763 let info = self.get_variable_by_name(&lval.name)?;
764
765 match info.location {
766 VariableLocation::SpecialImmediate(_) => {
767 semantics_bail!(
768 self.expr_num,
769 "Variable \"{}\" is a capture; captures can't be assigned to",
770 lval.name
771 );
772 }
773 VariableLocation::Stack(o) => {
774 self.instructions
775 .push(Instruction::movx64(reg, Register::R10));
776 self.instructions.push(Instruction::add64(reg, o.into()));
777 }
778 }
779
780 self.emit_apply_derefs_to_reg(reg, &info.var_type, &lval.derefs)
781 }
782
783 fn emit_set_register_from_lvalue(
794 &mut self,
795 reg: Register,
796 lval: &LValue,
797 load_type: Option<MemoryOpLoadType>,
798 ) -> InternalResult<()> {
799 let info = self.get_variable_by_name(&lval.name)?;
800 if let VariableLocation::SpecialImmediate(v) = info.location {
801 if !lval.derefs.is_empty() {
802 semantics_bail!(
803 self.expr_num,
804 "Can't dereference \"{}\"; it's a capture",
805 lval.name
806 );
807 }
808
809 let load_type = load_type.unwrap_or(MemoryOpLoadType::Void);
810 self.instructions
811 .push(Instruction::loadtype(reg, v.into(), load_type));
812 return Ok(());
813 }
814
815 let var_type = self.emit_set_register_to_lvalue_addr(reg, lval)?;
816
817 if matches!(lval.prefix, Some(Prefix::ReferencePrefix(_))) {
822 return Ok(());
823 }
824
825 match var_type.get_size() {
830 1 => self.instructions.push(Instruction::loadx8(reg, reg, 0)),
831 2 => self.instructions.push(Instruction::loadx16(reg, reg, 0)),
832 4 => self.instructions.push(Instruction::loadx32(reg, reg, 0)),
833 8 => self.instructions.push(Instruction::loadx64(reg, reg, 0)),
834 size => {
835 semantics_bail!(
836 self.expr_num,
837 "The variable \"{}\" is {} bytes and is too large to be passed in a register",
838 lval.name,
839 size
840 );
841 }
842 }
843
844 if matches!(lval.prefix, Some(Prefix::DeReferencePrefix(_))) {
849 if !var_type.is_pointer() {
850 semantics_bail!(self.expr_num, "Cannot dereference a non-pointer type");
851 }
852
853 self.instructions.push(Instruction::loadx64(reg, reg, 0));
854 }
855
856 Ok(())
857 }
858
859 fn emit_set_register_from_rvalue(
870 &mut self,
871 reg: Register,
872 rval: &RValue,
873 load_type: Option<MemoryOpLoadType>,
874 ) -> InternalResult<()> {
875 match rval {
876 RValue::Immediate(imm_str) => {
877 if let Some(load_type) = load_type {
878 let imm = self.parse_immediate(imm_str)?;
879 self.instructions
880 .push(Instruction::loadtype(reg, imm, load_type));
881 } else {
882 let imm = self.parse_immediate(imm_str)?;
883 self.instructions.push(Instruction::mov64(reg, imm));
884 }
885 }
886 RValue::LValue(lval) => {
887 self.emit_set_register_from_lvalue(reg, lval, load_type)?;
888 }
889 RValue::FunctionCall(call) => {
890 self.emit_call(call)?;
891 if !matches!(reg, Register::R0) {
892 self.instructions
893 .push(Instruction::movx64(reg, Register::R0));
894 }
895 }
896 }
897
898 Ok(())
899 }
900
901 fn emit_call(&mut self, call: &FunctionCall) -> InternalResult<()> {
907 let helper = match Helpers::from_string(&call.name) {
908 Some(helper) => helper,
909 None => {
910 semantics_bail!(self.expr_num, "Unknown function \"{}\"", call.name);
911 }
912 };
913
914 let types = helper.get_arg_types();
915
916 for (i, arg) in call.args.iter().enumerate() {
917 match i {
918 0 => self.emit_set_register_from_rvalue(Register::R1, arg, Some(types[i]))?,
919 1 => self.emit_set_register_from_rvalue(Register::R2, arg, Some(types[i]))?,
920 2 => self.emit_set_register_from_rvalue(Register::R3, arg, Some(types[i]))?,
921 3 => self.emit_set_register_from_rvalue(Register::R4, arg, Some(types[i]))?,
922 4 => self.emit_set_register_from_rvalue(Register::R5, arg, Some(types[i]))?,
923 _ => {
924 semantics_bail!(self.expr_num, "Function call exceeds 5 arguments");
925 }
926 };
927 }
928 self.instructions.push(Instruction::call(helper as u32));
929
930 Ok(())
931 }
932
933 fn emit_return(&mut self, ret: &Return) -> InternalResult<()> {
939 match &ret.value {
940 None => {
941 self.instructions.push(Instruction::mov64(Register::R0, 0));
942 self.instructions.push(Instruction::exit());
943 }
944 Some(value) => {
945 self.emit_set_register_from_rvalue(Register::R0, value, None)?;
946 self.instructions.push(Instruction::exit());
947 }
948 }
949
950 Ok(())
951 }
952
953 fn emit_prologue(&mut self, input: &InputLine) -> InternalResult<()> {
960 if input.args.len() > 5 {
964 semantics_bail!(self.expr_num, "Function exceeds 5 arguments");
965 }
966
967 for (i, arg) in input.args.iter().enumerate() {
971 let register = Register::from_num((i + 1) as u8).expect("too many args");
972 let arg_type = self.type_from_decl(&arg.type_name)?;
973 let offset = self.emit_push_register(register, None)?;
974 self.variables.insert(
975 arg.name.clone(),
976 VariableInfo {
977 var_type: arg_type,
978 location: VariableLocation::Stack(offset),
979 },
980 );
981 }
982
983 Ok(())
984 }
985
986 fn emit_body(&mut self, exprs: &[Expression]) -> InternalResult<()> {
992 for expr in exprs {
993 self.expr_num += 1;
994
995 match expr {
996 Expression::Assignment(assign) => {
997 self.emit_assign(assign)?;
998 }
999 Expression::FunctionCall(call) => {
1000 self.emit_call(call)?;
1001 }
1002 Expression::Return(ret) => {
1003 self.emit_return(ret)?;
1004 }
1005 }
1006 }
1007
1008 let last = exprs.last();
1012 if matches!(last, None) || !matches!(last, Some(Expression::Return(_))) {
1013 self.emit_return(&Return { value: None })?;
1014 }
1015
1016 Ok(())
1017 }
1018
1019 pub fn compile(&mut self, script_text: &str) -> InternalResult<()> {
1039 let ast = ScriptDef::parse(script_text)?;
1040 self.emit_prologue(&ast.input)?;
1041 self.emit_body(&ast.exprs)?;
1042
1043 self.instructions = optimize(&self.instructions);
1044
1045 Ok(())
1046 }
1047
1048 pub fn get_instructions(&self) -> &[Instruction] {
1067 &self.instructions
1068 }
1069
1070 pub fn get_bytecode(&self) -> Vec<u64> {
1091 let mut bytecode = vec![];
1092 for instruction in &self.instructions {
1093 let (n, x) = instruction.encode();
1094 bytecode.push(n);
1095 if let Some(x) = x {
1096 bytecode.push(x);
1097 }
1098 }
1099
1100 bytecode
1101 }
1102}