@@ -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) ]
364451impl Drop for LinearReg {
365452 fn drop ( & mut self ) {
0 commit comments