From c18ee2c2266fadd98de20b9f63a75cfa84461695 Mon Sep 17 00:00:00 2001 From: jess Date: Sat, 30 May 2026 16:39:53 -0700 Subject: [PATCH] lib --- compile/src/lib.rs | 77 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/compile/src/lib.rs b/compile/src/lib.rs index 1192ddb..a9f882e 100644 --- a/compile/src/lib.rs +++ b/compile/src/lib.rs @@ -182,9 +182,13 @@ fn emit_stmt(out: &mut String, stmt: &Stmt, depth: usize, deps: &mut Vec { - let lhs_s = emit_expr(lhs, hook)?; + let mut steps = Vec::new(); + let root = collect_lvalue_path(lhs, &mut steps, hook)?; let rhs = emit_expr(expr, hook)?; - indent(out, depth, &format!("v_path_assign(&mut {}, &{});", lhs_s, rhs)); + indent(out, depth, &format!( + "v_assign_path(&mut {}, &[{}], {});", + root, steps.join(", "), rhs + )); } Stmt::Return(expr) => { let rhs = emit_expr(expr, hook)?; @@ -277,6 +281,25 @@ fn emit_stmt(out: &mut String, stmt: &Stmt, depth: usize, deps: &mut Vec, hook: &dyn DecomposeHook) -> Result { + match expr { + Expr::Ident(name) => Ok(ident(name)), + Expr::Field(inner, field) => { + let root = collect_lvalue_path(inner, steps, hook)?; + steps.push(format!("Step::Field({:?}.into())", field)); + Ok(root) + } + Expr::Index(inner, idx) => { + let root = collect_lvalue_path(inner, steps, hook)?; + let i = emit_expr(idx, hook)?; + steps.push(format!("Step::Index(v_num(&{}) as i64)", i)); + Ok(root) + } + _ => Err("assignment target must root at a variable".into()), + } +} + fn emit_expr(expr: &Expr, hook: &dyn DecomposeHook) -> Result { if let Some(custom) = hook.expr(expr) { return Ok(custom); @@ -543,8 +566,31 @@ fn v_field(base: &V, name: &str) -> V { } } -fn v_field_set(base: &mut V, _val: &V) { - let _ = base; // path assignment placeholder +enum Step { Field(String), Index(i64) } + +fn v_assign_path(root: &mut V, steps: &[Step], val: V) { + let mut cur = root; + for (i, step) in steps.iter().enumerate() { + let last = i + 1 == steps.len(); + match step { + Step::Field(k) => match cur { + V::Struct(m) => { + if last { m.insert(k.clone(), val); return; } + cur = m.entry(k.clone()).or_insert(V::Void); + } + _ => return, + }, + Step::Index(idx) => match cur { + V::Array(a) => { + let n = if *idx < 0 { (a.len() as i64 + idx) as usize } else { *idx as usize }; + if n >= a.len() { return; } + if last { a[n] = val; return; } + cur = &mut a[n]; + } + _ => return, + }, + } + } } fn v_iter(val: &V) -> Vec { @@ -555,7 +601,6 @@ fn v_iter(val: &V) -> Vec { } } -fn v_path_assign(target: &mut V, val: &V) { *target = val.clone(); } fn v_cell_get(_table: &str, _col: u32, _row: u32) -> V { V::Void } fn v_cell_range(_table: &str, _c1: u32, _r1: u32, _c2: u32, _r2: u32) -> V { V::Array(Vec::new()) } fn v_cell_table(_table: &str) -> V { V::Array(Vec::new()) } @@ -729,8 +774,17 @@ impl Vec2 { let a = Vec2::new(1, 2) let b = Vec2::new(3, 4) let c = a + b +let p = {x: 1, y: 2} +p.x = 10 +let arr = [1, 2, 3] +arr[1] = 20 +let node = {pose: {pos: {x: 0}}} +node.pose.pos.x = 5 "; let mut code = dec(src); + assert!(code.contains("v_assign_path(&mut p")); + assert!(code.contains("v_assign_path(&mut arr")); + assert!(code.contains("v_assign_path(&mut node")); code.push_str(r#" fn main() { let a = Vec2__new(V::Num(1.0), V::Num(2.0)); @@ -740,6 +794,19 @@ fn main() { assert_eq!(v_field(&c, "y"), V::Num(6.0)); let l = v_method_call(&a, "len2", &[]); assert_eq!(l, V::Num(5.0)); + + let mut p = V::Struct([("x".to_string(), V::Num(1.0))].into_iter().collect()); + v_assign_path(&mut p, &[Step::Field("x".into())], V::Num(10.0)); + assert_eq!(v_field(&p, "x"), V::Num(10.0)); + + let mut arr = V::Array(vec![V::Num(1.0), V::Num(2.0), V::Num(3.0)]); + v_assign_path(&mut arr, &[Step::Index(1)], V::Num(20.0)); + assert_eq!(v_index(&arr, &V::Num(1.0)), V::Num(20.0)); + + let mut node = V::Struct([("pose".to_string(), V::Struct([("pos".to_string(), V::Struct([("x".to_string(), V::Num(0.0))].into_iter().collect()))].into_iter().collect()))].into_iter().collect()); + v_assign_path(&mut node, &[Step::Field("pose".into()), Step::Field("pos".into()), Step::Field("x".into())], V::Num(5.0)); + assert_eq!(v_field(&v_field(&v_field(&node, "pose"), "pos"), "x"), V::Num(5.0)); + let _ = run(); println!("OK"); }