1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/// Single instruction of the interpreter
#[derive(Debug, Clone, Copy, Eq, PartialEq, num_enum::TryFromPrimitive)]
// #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
pub(crate) enum Instruction {
/// Add two numbers
Add,
/// Subtract two numbers
Sub,
/// Multiply two numbers
Mul,
/// Divide the first number by the second
Div,
/// Call a function provided by the runtime
/// Requires function name as a string as input
Call,
/// Push an int onto the stack
ScalarInt,
/// Push a float onto the stack
ScalarFloat,
/// Push a `nil` value onto the stack
ScalarNil,
/// Writes the strings followed by the instruction to memory and pushes the pointer pointing to
/// it onto the stack
StringLiteral,
/// Empty instruction that has no effects
Pass,
/// Clones the last element on the stack
/// Does nothing if no elements are on the stack
CopyLast,
/// If the value at the top of the stack is truthy jumps to the input node
/// Else does nothing
/// Quit the program returning the last value on the stack
Exit,
/// Read bytecode position and Lane arity from the program and perform a jump there.
CallLane,
/// Compares two scalars
Equals,
/// Compares two scalars
NotEquals,
/// Is the first param less than the second?
Less,
/// Is the first param less than or equal to the second?
LessOrEq,
/// Pops the top of the stack and discards it
Pop,
/// Sets the variable at the top of the stack to the value of the second item on the stack
SetGlobalVar,
/// Reads the variable and pushes its value onto the stack
ReadGlobalVar,
/// Set the value in position given by the instruction to the value on top of the stack
SetLocalVar,
/// Read the value in position given by the instruction
ReadLocalVar,
/// Clears the last callframe's stack
ClearStack,
/// Returns to right-after-the-last-call-instruction
/// Also clears the stack until the last call frame
///
/// Pops the stack and pushes the value back after clearing.
Return,
/// Swaps the last two values on the stack
SwapLast,
And,
Or,
Xor,
Not,
/// Read bytecode position and move there
Goto,
/// Pop a scalar from the stack and `goto` there if the value was
/// truthy
GotoIfTrue,
/// Pop a scalar from the stack and `goto` there if the value was
/// falsy
GotoIfFalse,
/// Creates a new Cao-Lang Table and pushes it onto the stack
InitTable,
/// Pops an Object instance from the stack, get's its value at the encoded key and pushes it's value to the stack
GetProperty,
/// Pops an Object instance and a Value from the stack then sets the table value at the encoded
/// key
SetProperty,
/// Pushes the length of the topmost table to the stack
/// Errors if the top Value is not a Table
Len,
/// Must be called before the first call to Repeat in a loop
BeginRepeat,
Repeat,
BeginForEach,
ForEach,
}
/// return the number of bytes this instruction spans in the bytecode
pub(crate) const fn instruction_span(instr: Instruction) -> i32 {
match instr {
Instruction::Add
| Instruction::Sub
| Instruction::Exit
| Instruction::Mul
| Instruction::Div
| Instruction::Call
| Instruction::Equals
| Instruction::NotEquals
| Instruction::Less
| Instruction::LessOrEq
| Instruction::Pop
| Instruction::Pass
| Instruction::ScalarNil
| Instruction::ClearStack
| Instruction::CopyLast
| Instruction::Return
| Instruction::SwapLast
| Instruction::And
| Instruction::Or
| Instruction::Xor
| Instruction::InitTable
| Instruction::Len
| Instruction::BeginRepeat
| Instruction::BeginForEach
| Instruction::Not => 1,
//
Instruction::ScalarInt | Instruction::ScalarFloat => 9,
Instruction::StringLiteral => 5,
//
Instruction::SetLocalVar
| Instruction::ReadLocalVar
| Instruction::SetProperty
| Instruction::GetProperty
| Instruction::SetGlobalVar
| Instruction::ReadGlobalVar => 5,
//
Instruction::Goto | Instruction::GotoIfTrue | Instruction::GotoIfFalse => 5,
Instruction::ForEach | Instruction::Repeat | Instruction::CallLane => 9,
}
}