Skip to content

Commit ecc7dcc

Browse files
committed
interpreter: binary placing operations; expand IR
1 parent 4615b76 commit ecc7dcc

4 files changed

Lines changed: 130 additions & 22 deletions

File tree

interpreter/src/ir.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,15 @@ pub enum Instruction {
6262
Concat(BinaryArg),
6363

6464
// Intrinsic operations
65-
LoadUser(LoadStoreArg),
66-
LoadBultin(LoadStoreArg),
67-
LoadConst(LoadStoreArg),
68-
StoreUser(LoadStoreArg),
69-
StoreBuiltin(LoadStoreArg),
65+
LoadUserScalar(MemScalarArg),
66+
LoadUserArray(MemArrayArg),
67+
LoadBuiltinScalar(MemScalarArg),
68+
LoadBuiltinArray(MemArrayArg),
69+
LoadConst(MemScalarArg),
70+
StoreUserScalar(MemScalarArg),
71+
StoreBuiltinScalar(MemScalarArg),
72+
StoreUserArray(MemArrayArg),
73+
StoreBuiltinArray(MemArrayArg),
7074
IntrinsicCall(CallArgs),
7175
UserCall(IndCallArgs),
7276
IndirectCall(CallArgs),
@@ -79,7 +83,8 @@ const _: () = const { assert!(size_of::<Instruction>() <= 8) };
7983

8084
pub type UnaryArg = (Reg, Reg);
8185
pub type BinaryArg = (Reg, Reg, Reg);
82-
pub type LoadStoreArg = (Reg, NonLocal);
86+
pub type MemScalarArg = (Reg, NonLocal);
87+
pub type MemArrayArg = (Reg, Reg, NonLocal);
8388
pub type JumpArg = Label;
8489
pub type RetArg = Reg;
8590
pub type BranchArg = (Reg, Label, Label);
@@ -133,15 +138,22 @@ impl Display for Instruction {
133138
| Self::Modulo((dest, lhs, rhs)) => {
134139
write!(f, "{dest} <- {op} {lhs}, {rhs}")
135140
}
136-
Self::LoadUser((dest, src)) | Self::StoreUser((dest, src)) => {
141+
Self::LoadUserScalar((dest, src)) | Self::StoreUserScalar((dest, src)) => {
137142
write!(f, "{dest} <- {op} user[{src}]")
138143
}
144+
Self::LoadUserArray((dest, src, place)) | Self::StoreUserArray((dest, src, place)) => {
145+
write!(f, "{dest} <- {op} user[{place}[{src}]]")
146+
}
139147
Self::LoadConst((dest, src)) => {
140148
write!(f, "{dest} <- {op} mem[{src}]")
141149
}
142-
Self::StoreBuiltin((dest, src)) | Self::LoadBultin((dest, src)) => {
150+
Self::StoreBuiltinScalar((dest, src)) | Self::LoadBuiltinScalar((dest, src)) => {
143151
write!(f, "{dest} <- {op} intrinsic[{src}]")
144152
}
153+
Self::LoadBuiltinArray((dest, src, place))
154+
| Self::StoreBuiltinArray((dest, src, place)) => {
155+
write!(f, "{dest} <- {op} intrinsic[{place}[{src}]]")
156+
}
145157
Self::Branch((cond, label_then, label_else)) => {
146158
write!(f, "{op} {cond}, {label_then}, {label_else}")
147159
}
@@ -185,11 +197,15 @@ impl Instruction {
185197
Self::Divide(_) => "div",
186198
Self::Raise(_) => "pow",
187199
Self::Modulo(_) => "mod",
188-
Self::LoadUser(_) => "vload",
189-
Self::LoadBultin(_) => "iload",
200+
Self::LoadUserScalar(_) => "vsload",
201+
Self::LoadBuiltinScalar(_) => "isload",
202+
Self::LoadUserArray(_) => "vaload",
203+
Self::LoadBuiltinArray(_) => "iaload",
190204
Self::LoadConst(_) => "cload",
191-
Self::StoreUser(_) => "vstore",
192-
Self::StoreBuiltin(_) => "istore",
205+
Self::StoreUserScalar(_) => "vsstore",
206+
Self::StoreBuiltinScalar(_) => "isstore",
207+
Self::StoreUserArray(_) => "vastore",
208+
Self::StoreBuiltinArray(_) => "iastore",
193209
Self::Copy(_) => "cpy",
194210
Self::IntrinsicCall(_) => "icall",
195211
Self::UserCall(_) => "ucall",

interpreter/src/ir/lower.rs

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl<'a> Code<'a> {
136136
Expr::Leaf(atom) => match atom {
137137
Atom::Variable(Variable::User(ident)) => {
138138
let src = self.symbols.register_user_var(ident, self.arena);
139-
self.bc.emit(Instruction::LoadUser((dest, src)));
139+
self.bc.emit(Instruction::LoadUserScalar((dest, src)));
140140
}
141141
&Atom::Number(n) => {
142142
let src = self.register_const(Value::Float(n));
@@ -202,19 +202,101 @@ impl<'a> Code<'a> {
202202
let next = self.following_instr(0);
203203
self.bc.nth(jump).set_label(next);
204204
}
205-
ExprNode::BinaryPlaceOperation(BinaryPlaceOperator::Assignment, place, expr) => {
205+
ExprNode::BinaryPlaceOperation(op, place, expr) => {
206206
self.lower_expr_into(expr, dest);
207-
let Place::Variable(Variable::User(var)) = place else {
208-
todo!()
207+
208+
let second_op = match op {
209+
BinaryPlaceOperator::Assignment => {
210+
self.store_place(place, dest);
211+
return;
212+
}
213+
BinaryPlaceOperator::AddAssign => Instruction::Add,
214+
BinaryPlaceOperator::SubAssign => Instruction::Subtract,
215+
BinaryPlaceOperator::MulAssign => Instruction::Multiply,
216+
BinaryPlaceOperator::DivAssign => Instruction::Divide,
217+
BinaryPlaceOperator::PowAssign => Instruction::Raise,
218+
BinaryPlaceOperator::ModAssign => Instruction::Modulo,
209219
};
210-
let var = self.symbols.register_user_var(var, self.arena);
211-
self.bc.emit(Instruction::StoreUser((dest, var)));
220+
let lhs = self.alloc_reg();
221+
222+
self.load_place(*lhs, place);
223+
self.bc.emit(second_op((dest, *lhs, dest)));
224+
self.store_place(place, dest);
225+
226+
self.free_reg(lhs);
212227
}
213228
_ => todo!(),
214229
},
215230
}
216231
}
217232

233+
fn load_place(&mut self, dest: Reg, place: &Place<'_>) {
234+
match place {
235+
Place::Record(_) => {
236+
todo!()
237+
}
238+
Place::Variable(Variable::User(ident)) => {
239+
let src = self.symbols.register_user_var(ident, self.arena);
240+
self.bc.emit(Instruction::LoadUserScalar((dest, src)));
241+
}
242+
Place::Variable(var) => {
243+
self.bc
244+
.emit(Instruction::LoadBuiltinScalar((dest, var_index(var))));
245+
}
246+
Place::Index(Variable::User(ident), index) => {
247+
self.subsep_index(dest, index);
248+
let src = self.symbols.register_user_var(ident, self.arena);
249+
self.bc.emit(Instruction::LoadUserArray((dest, dest, src)));
250+
}
251+
Place::Index(var, index) => {
252+
self.subsep_index(dest, index);
253+
self.bc
254+
.emit(Instruction::LoadBuiltinArray((dest, dest, var_index(var))));
255+
}
256+
}
257+
}
258+
259+
fn store_place(&mut self, place: &Place<'_>, src: Reg) {
260+
match place {
261+
Place::Record(_) => todo!(),
262+
Place::Variable(Variable::User(ident)) => {
263+
self.bc.emit(Instruction::StoreUserScalar((
264+
src,
265+
self.symbols.register_user_var(ident, self.arena),
266+
)));
267+
}
268+
Place::Variable(var) => {
269+
self.bc
270+
.emit(Instruction::StoreBuiltinScalar((src, var_index(var))));
271+
}
272+
Place::Index(Variable::User(ident), index) => {
273+
let rhs = self.alloc_reg();
274+
self.subsep_index(*rhs, index);
275+
let place = self.symbols.register_user_var(ident, self.arena);
276+
self.bc
277+
.emit(Instruction::StoreUserArray((src, *rhs, place)));
278+
self.free_reg(rhs);
279+
}
280+
Place::Index(var, index) => {
281+
let rhs = self.alloc_reg();
282+
self.subsep_index(*rhs, index);
283+
self.bc
284+
.emit(Instruction::StoreBuiltinArray((src, *rhs, var_index(var))));
285+
self.free_reg(rhs);
286+
}
287+
}
288+
}
289+
290+
fn subsep_index(&mut self, dest: Reg, index: &[Expr<'_>]) {
291+
let rhs = self.alloc_reg();
292+
self.lower_expr_into(&index[0], dest);
293+
for i in &index[1..] {
294+
self.lower_expr_into(i, *rhs);
295+
self.bc.emit(Instruction::Concat((dest, dest, *rhs)));
296+
}
297+
self.free_reg(rhs);
298+
}
299+
218300
fn alloc_reg(&mut self) -> LinearReg {
219301
self.free_regs.pop().map(LinearReg).unwrap_or_else(|| {
220302
let current = self.reg_pointer;
@@ -360,6 +442,11 @@ impl Deref for LinearReg {
360442
}
361443
}
362444

445+
fn var_index(var: &Variable<'_>) -> NonLocal {
446+
// SAFETY: it is repr(u16).
447+
unsafe { *<*const Variable>::from(var).cast::<NonLocal>() }
448+
}
449+
363450
#[cfg(debug_assertions)]
364451
impl Drop for LinearReg {
365452
fn drop(&mut self) {

interpreter/src/vm.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,20 +169,24 @@ impl Interpreter<'_> {
169169
rhs.write_string(&mut buf);
170170
self.registers.write(dest, Value::String(buf.into()));
171171
}
172-
Instruction::LoadUser((dest, src)) => {
172+
Instruction::LoadUserScalar((dest, src)) => {
173173
let val = self.symbols.lookup_user_scalar(src);
174174
self.registers.write(dest, val.clone());
175175
}
176-
Instruction::LoadBultin((_dest, _src)) => todo!(),
176+
Instruction::LoadUserArray((_dest, _src, _place)) => todo!(),
177+
Instruction::LoadBuiltinScalar((_dest, _src)) => todo!(),
178+
Instruction::LoadBuiltinArray((_dest, _src, _place)) => todo!(),
177179
Instruction::LoadConst((dest, src)) => {
178180
let val = self.consts.0.get_index(src.0 as _).unwrap().clone();
179181
self.registers.write(dest, val);
180182
}
181-
Instruction::StoreUser((dest, src)) => {
183+
Instruction::StoreUserScalar((dest, src)) => {
182184
let val = self.registers.get(dest).clone();
183185
self.symbols.write_user_val(src, val);
184186
}
185-
Instruction::StoreBuiltin((_dest, _src)) => todo!(),
187+
Instruction::StoreUserArray((_dest, _src, _place)) => todo!(),
188+
Instruction::StoreBuiltinScalar((_dest, _src)) => todo!(),
189+
Instruction::StoreBuiltinArray((_dest, _src, _place)) => todo!(),
186190
Instruction::IntrinsicCall((_dest, _code, _args)) => todo!(),
187191
Instruction::UserCall((_dest, _code, _args)) => todo!(),
188192
Instruction::IndirectCall((_dest, _code, _args)) => todo!(),

parser/src/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub struct Identifier<'a> {
6161
pub literal: &'a str,
6262
}
6363

64+
#[repr(u16)]
6465
#[derive(Clone, Copy)]
6566
pub enum Variable<'a> {
6667
User(Identifier<'a>),

0 commit comments

Comments
 (0)