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));
|
indent(out, depth, &format!("{} = {};", ident(name), rhs));
|
||||||
}
|
}
|
||||||
Stmt::PathAssign(lhs, expr) => {
|
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)?;
|
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) => {
|
Stmt::Return(expr) => {
|
||||||
let rhs = emit_expr(expr, hook)?;
|
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(())
|
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> {
|
fn emit_expr(expr: &Expr, hook: &dyn DecomposeHook) -> Result<String, String> {
|
||||||
if let Some(custom) = hook.expr(expr) {
|
if let Some(custom) = hook.expr(expr) {
|
||||||
return Ok(custom);
|
return Ok(custom);
|
||||||
|
|
@ -543,8 +566,31 @@ fn v_field(base: &V, name: &str) -> V {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn v_field_set(base: &mut V, _val: &V) {
|
enum Step { Field(String), Index(i64) }
|
||||||
let _ = base; // path assignment placeholder
|
|
||||||
|
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> {
|
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_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_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()) }
|
fn v_cell_table(_table: &str) -> V { V::Array(Vec::new()) }
|
||||||
|
|
@ -729,8 +774,17 @@ impl Vec2 {
|
||||||
let a = Vec2::new(1, 2)
|
let a = Vec2::new(1, 2)
|
||||||
let b = Vec2::new(3, 4)
|
let b = Vec2::new(3, 4)
|
||||||
let c = a + b
|
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);
|
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#"
|
code.push_str(r#"
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = Vec2__new(V::Num(1.0), V::Num(2.0));
|
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));
|
assert_eq!(v_field(&c, "y"), V::Num(6.0));
|
||||||
let l = v_method_call(&a, "len2", &[]);
|
let l = v_method_call(&a, "len2", &[]);
|
||||||
assert_eq!(l, V::Num(5.0));
|
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();
|
let _ = run();
|
||||||
println!("OK");
|
println!("OK");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue