lib
This commit is contained in:
parent
6c3066fa1d
commit
c18ee2c226
|
|
@ -182,9 +182,13 @@ fn emit_stmt(out: &mut String, stmt: &Stmt, depth: usize, deps: &mut Vec<Depende
|
|||
indent(out, depth, &format!("{} = {};", ident(name), rhs));
|
||||
}
|
||||
Stmt::PathAssign(lhs, expr) => {
|
||||
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<Depende
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// walks a Field/Index lvalue chain into a root identifier plus emitted Step nodes.
|
||||
fn collect_lvalue_path(expr: &Expr, steps: &mut Vec<String>, hook: &dyn DecomposeHook) -> Result<String, String> {
|
||||
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<String, String> {
|
||||
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<V> {
|
||||
|
|
@ -555,7 +601,6 @@ fn v_iter(val: &V) -> Vec<V> {
|
|||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue