Просмотр исходного кода

wallet: add if_else and store_var to expr language, and use it for fit to scale images

darkfi 1 год назад
Родитель
Сommit
5a887f5207

+ 34 - 3
bin/darkwallet/src/app/schema.rs

@@ -20,7 +20,7 @@ use sled_overlay::sled;
 
 use crate::{
     error::Error,
-    expr::{self, Compiler},
+    expr::{self, Compiler, Op},
     gfx::{GraphicsEventPublisherPtr, Rectangle, RenderApiPtr, Vertex},
     mesh::{Color, MeshBuilder},
     prop::{
@@ -486,11 +486,42 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
     prop.set_f32(Role::App, 1, 0.).unwrap();
     prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
     prop.set_expr(Role::App, 3, expr::load_var("h")).unwrap();
+
+    let R = 1.78;
+    let code = vec![Op::StoreVar((
+        "r".to_string(),
+        Box::new(Op::Div((
+            Box::new(Op::LoadVar("w".to_string())),
+            Box::new(Op::LoadVar("h".to_string())),
+        ))),
+    ))];
+
+    let mut u_code = code.clone();
+    u_code.push(Op::IfElse((
+        Box::new(Op::LessThan((
+            Box::new(Op::LoadVar("r".to_string())),
+            Box::new(Op::ConstFloat32(R)),
+        ))),
+        vec![Op::Div((Box::new(Op::LoadVar("r".to_string())), Box::new(Op::ConstFloat32(R))))],
+        vec![Op::ConstFloat32(1.)],
+    )));
+
+    let mut v_code = code.clone();
+    v_code.push(Op::IfElse((
+        Box::new(Op::LessThan((
+            Box::new(Op::LoadVar("r".to_string())),
+            Box::new(Op::ConstFloat32(R)),
+        ))),
+        vec![Op::ConstFloat32(1.)],
+        vec![Op::Div((Box::new(Op::ConstFloat32(R)), Box::new(Op::LoadVar("r".to_string()))))],
+    )));
+
     let prop = node.get_property("uv").unwrap();
     prop.set_f32(Role::App, 0, 0.).unwrap();
     prop.set_f32(Role::App, 1, 0.).unwrap();
-    prop.set_f32(Role::App, 2, 1.).unwrap();
-    prop.set_f32(Role::App, 3, 1.).unwrap();
+    prop.set_expr(Role::App, 2, u_code).unwrap();
+    prop.set_expr(Role::App, 3, v_code).unwrap();
+
     node.set_property_str(Role::App, "path", BG_PATH).unwrap();
     node.set_property_u32(Role::App, "z_index", 0).unwrap();
     let node = node.setup(|me| Image::new(me, app.render_api.clone(), app.ex.clone())).await;

+ 67 - 18
bin/darkwallet/src/expr/mod.rs

@@ -144,16 +144,17 @@ pub enum Op {
     ConstFloat32(f32),
     ConstStr(String),
     LoadVar(String),
-    //StoreVar((String, Box<Op>)),
+    StoreVar((String, Box<Op>)),
     Min((Box<Op>, Box<Op>)),
     Max((Box<Op>, Box<Op>)),
     IsEqual((Box<Op>, Box<Op>)),
     LessThan((Box<Op>, Box<Op>)),
     Float32ToUint32(Box<Op>),
+    IfElse((Box<Op>, SExprCode, SExprCode)),
 }
 
 impl<'a> SExprMachine<'a> {
-    pub fn call(&self) -> Result<SExprVal> {
+    pub fn call(&mut self) -> Result<SExprVal> {
         if self.stmts.is_empty() {
             return Ok(SExprVal::Null)
         }
@@ -163,7 +164,7 @@ impl<'a> SExprMachine<'a> {
         self.eval(self.stmts.last().unwrap())
     }
 
-    fn eval(&self, op: &Op) -> Result<SExprVal> {
+    fn eval(&mut self, op: &Op) -> Result<SExprVal> {
         match op {
             Op::Null => Ok(SExprVal::Null),
             Op::Add((lhs, rhs)) => self.add(lhs, rhs),
@@ -175,16 +176,17 @@ impl<'a> SExprMachine<'a> {
             Op::ConstFloat32(val) => Ok(SExprVal::Float32(*val)),
             Op::ConstStr(val) => Ok(SExprVal::Str(val.clone())),
             Op::LoadVar(var) => self.load_var(var),
-            //Op::StoreVar((var, val)) => self.store_var(var, val),
+            Op::StoreVar((var, val)) => self.store_var(var, val),
             Op::Min((lhs, rhs)) => self.min(lhs, rhs),
             Op::Max((lhs, rhs)) => self.max(lhs, rhs),
             Op::IsEqual((lhs, rhs)) => self.is_equal(lhs, rhs),
             Op::LessThan((lhs, rhs)) => self.less_than(lhs, rhs),
             Op::Float32ToUint32(val) => self.float32_to_uint32(val),
+            Op::IfElse((cond, if_val, else_val)) => self.if_else(cond, if_val, else_val),
         }
     }
 
-    fn add(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn add(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -197,7 +199,7 @@ impl<'a> SExprMachine<'a> {
 
         Ok(SExprVal::Float32(lhs + rhs))
     }
-    fn sub(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn sub(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -210,7 +212,7 @@ impl<'a> SExprMachine<'a> {
 
         Ok(SExprVal::Float32(lhs - rhs))
     }
-    fn mul(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn mul(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -223,7 +225,7 @@ impl<'a> SExprMachine<'a> {
 
         Ok(SExprVal::Float32(lhs * rhs))
     }
-    fn div(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn div(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -242,9 +244,12 @@ impl<'a> SExprMachine<'a> {
         }
         Err(Error::SExprGlobalNotFound)
     }
-    //fn store_var(&mut self, var, val) {
-    //}
-    fn min(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn store_var(&mut self, var: &str, val: &Op) -> Result<SExprVal> {
+        let val = self.eval(val)?;
+        self.globals.push((var.to_string(), val));
+        Ok(SExprVal::Null)
+    }
+    fn min(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -261,7 +266,7 @@ impl<'a> SExprMachine<'a> {
 
         Ok(SExprVal::Float32(min))
     }
-    fn max(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn max(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -278,7 +283,7 @@ impl<'a> SExprMachine<'a> {
 
         Ok(SExprVal::Float32(max))
     }
-    fn is_equal(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn is_equal(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -292,7 +297,7 @@ impl<'a> SExprMachine<'a> {
 
         Ok(SExprVal::Bool(is_equal))
     }
-    fn less_than(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
+    fn less_than(&mut self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
         let lhs = self.eval(lhs)?;
         let rhs = self.eval(rhs)?;
 
@@ -305,13 +310,25 @@ impl<'a> SExprMachine<'a> {
 
         Ok(SExprVal::Bool(lhs < rhs))
     }
-    fn float32_to_uint32(&self, val: &Op) -> Result<SExprVal> {
+    fn float32_to_uint32(&mut self, val: &Op) -> Result<SExprVal> {
         let val = self.eval(val)?;
         if val.is_u32() {
             return Ok(SExprVal::Uint32(val.as_u32()?))
         }
         Ok(SExprVal::Uint32(val.as_f32()? as u32))
     }
+    fn if_else(&mut self, cond: &Op, if_val: &SExprCode, else_val: &SExprCode) -> Result<SExprVal> {
+        let cond = self.eval(cond)?;
+        let cond = cond.as_bool()?;
+
+        if cond {
+            let mut machine = SExprMachine { globals: self.globals.clone(), stmts: if_val };
+            machine.call()
+        } else {
+            let mut machine = SExprMachine { globals: self.globals.clone(), stmts: else_val };
+            machine.call()
+        }
+    }
 }
 
 impl Encodable for Op {
@@ -361,7 +378,11 @@ impl Encodable for Op {
                 len += 9u8.encode(s)?;
                 len += var.encode(s)?;
             }
-            // StoreVar
+            Self::StoreVar((var, val)) => {
+                len += 10u8.encode(s)?;
+                len += var.encode(s)?;
+                len += val.encode(s)?;
+            }
             Self::Min((lhs, rhs)) => {
                 len += 11u8.encode(s)?;
                 len += lhs.encode(s)?;
@@ -386,6 +407,12 @@ impl Encodable for Op {
                 len += 15u8.encode(s)?;
                 len += val.encode(s)?;
             }
+            Self::IfElse((cond, if_val, else_val)) => {
+                len += 16u8.encode(s)?;
+                len += cond.encode(s)?;
+                len += if_val.encode(s)?;
+                len += else_val.encode(s)?;
+            }
         }
         Ok(len)
     }
@@ -405,12 +432,17 @@ impl Decodable for Op {
             7 => Self::ConstFloat32(d.read_f32()?),
             8 => Self::ConstStr(String::decode(d)?),
             9 => Self::LoadVar(String::decode(d)?),
-            // StoreVar
+            10 => Self::StoreVar((String::decode(d)?, Box::new(Self::decode(d)?))),
             11 => Self::Min((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
             12 => Self::Max((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
             13 => Self::IsEqual((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
             14 => Self::LessThan((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
             15 => Self::Float32ToUint32(Box::new(Self::decode(d)?)),
+            16 => Self::IfElse((
+                Box::new(Self::decode(d)?),
+                Decodable::decode(d)?,
+                Decodable::decode(d)?,
+            )),
             _ => return Err(std::io::Error::new(std::io::ErrorKind::Other, "Invalid Op type")),
         };
         Ok(self_)
@@ -424,7 +456,7 @@ mod tests {
 
     #[test]
     fn seval() {
-        let machine = SExprMachine {
+        let mut machine = SExprMachine {
             globals: vec![
                 ("sw".to_string(), SExprVal::Uint32(110u32)),
                 ("sh".to_string(), SExprVal::Uint32(4u32)),
@@ -454,4 +486,21 @@ mod tests {
         let code2 = deserialize::<Op>(&code_s).unwrap();
         assert_eq!(code, code2);
     }
+
+    #[test]
+    fn if_store() {
+        let code = vec![
+            Op::StoreVar((
+                "s".to_string(),
+                Box::new(Op::IfElse((
+                    Box::new(Op::ConstBool(false)),
+                    vec![Op::ConstUint32(4)],
+                    vec![Op::ConstUint32(110)],
+                ))),
+            )),
+            Op::LoadVar("s".to_string()),
+        ];
+        let mut machine = SExprMachine { globals: vec![], stmts: &code };
+        assert_eq!(machine.call().unwrap(), SExprVal::Uint32(110));
+    }
 }

+ 1 - 1
bin/darkwallet/src/prop/wrap.rs

@@ -289,7 +289,7 @@ impl PropertyRect {
 
             let expr = self.prop.get_expr(i).unwrap();
 
-            let machine = SExprMachine {
+            let mut machine = SExprMachine {
                 globals: vec![
                     ("w".to_string(), SExprVal::Float32(parent_rect.w)),
                     ("h".to_string(), SExprVal::Float32(parent_rect.h)),

+ 1 - 1
bin/darkwallet/src/ui/vector_art/shape.rs

@@ -61,7 +61,7 @@ impl VectorShape {
         for shape_vert in &self.verts {
             let mut pos = [0.; 2];
             for (i, shape_X) in [(0, &shape_vert.x), (1, &shape_vert.y)] {
-                let machine = SExprMachine {
+                let mut machine = SExprMachine {
                     globals: vec![
                         ("w".to_string(), SExprVal::Float32(w)),
                         ("h".to_string(), SExprVal::Float32(h)),