[gnome-calculator/60-split-out-a-backend-library] gcalc: saving variables values in manager and equations



commit 999cde51c9bbb421ac9c6ab8d7daecda633dbbcd
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date:   Sun Jan 6 01:52:40 2019 -0600

    gcalc: saving variables values in manager and equations

 gcalc/gcalc-gmath-equation.vala        |  2 +-
 gcalc/gcalc-gparser.vala               | 54 ++++++++++++++++++++++++++++++----
 gcalc/gcalc-gsolver.vala               |  6 ++--
 gcalc/gcalc-gvariable.vala             |  1 +
 gcalc/gcalc-math-equation-manager.vala | 15 ++++++++++
 gcalc/gcalc-term.vala                  | 29 ++++++++++++++++--
 gcalc/gcalc-variable.vala              |  4 +++
 tests/gcalc-parsing.vala               | 24 +++++++++++++++
 8 files changed, 123 insertions(+), 12 deletions(-)
---
diff --git a/gcalc/gcalc-gmath-equation.vala b/gcalc/gcalc-gmath-equation.vala
index bfa234ee..2dc1585c 100644
--- a/gcalc/gcalc-gmath-equation.vala
+++ b/gcalc/gcalc-gmath-equation.vala
@@ -25,7 +25,7 @@ public class GCalc.GMathEquation : GExpression, MathEquation {
     Result res = null;
     if (expressions.get_n_items () == 0) {
       var err = new GErrorResult ("No expressions found in equation");
-      return new GResult.with_error ((Expression) new GExpression (), (ErrorResult) err) as Result;
+      return new GResult.with_error ((Expression) new GErrorExpression (), (ErrorResult) err) as Result;
     }
     var e = expressions.get_item (0) as Expression;
     if (e == null) {
diff --git a/gcalc/gcalc-gparser.vala b/gcalc/gcalc-gparser.vala
index abe807ba..abdbac7b 100644
--- a/gcalc/gcalc-gparser.vala
+++ b/gcalc/gcalc-gparser.vala
@@ -158,16 +158,39 @@ public class GCalc.GParser : Object {
             throw new ParserError.INVALID_TOKEN_ERROR ("Found an unexpected function definition expression");
           } else {
             var v = new GVariable (n) as Expression;
-            if (eq.variables.find_named (n) == null) {
-              eq.variables.add (v);
+            var sv = eqman.find_variable (n) as Variable;
+            if (sv == null) {
+              sv = eq.variables.find_named (n) as Variable;
+              if (sv == null) {
+                eq.variables.add (v);
+              } else {
+                ((Variable) v).bind = sv;
+              }
+            } else {
+              ((Variable) v).bind = sv;
             }
             if (current == null) {
+              message ("Trying to Add a polynomial in a variable");
+              var exp = new GPolynomial ();
+              eq.expressions.add (exp);
+              var t = new GTerm ();
+              exp.expressions.add (t);
+              t.expressions.add (v);
               current = v;
+              current_parent = v.parent;
+              top_parent = current_parent.parent;
               expected.clear ();
+              message ("Created initial variable");
             } else if (current is Operator && current_parent is Term && top_parent is Polynomial) {
                 current_parent.expressions.add (v);
                 current = v;
                 expected.clear ();
+            } else if (current is Term) {
+                current.expressions.add (v);
+                current = v;
+                current_parent = v.parent;
+                top_parent = current_parent.parent;
+                expected.clear ();
             }
           }
           break;
@@ -221,11 +244,30 @@ public class GCalc.GParser : Object {
         case Vala.TokenType.ASSIGN:
           if (current == null) {
             throw new ParserError.INVALID_TOKEN_ERROR ("Found an unexpected expression for an assignment");
-          }
-          if (current is Polynomial) {
+          } else if (current is Polynomial) {
             throw new ParserError.INVALID_TOKEN_ERROR ("Found an unexpected expression: can't set a value to 
a polynomial");
-          }
-          if (current is Variable) {
+          } else if (current is Variable) {
+            bool removed = false;
+            if (current.parent != null) {
+              if (current.parent is Term) {
+                var t = current.parent;
+                if (t.parent != null) {
+                  if (t.parent is Polynomial) {
+                    var p = t.parent;
+                    if (p.parent != null) {
+                      if (p.parent is MathEquation) {
+                        eq.expressions.remove (p);
+                        p.expressions.remove (t);
+                        removed = true;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+            if (!removed) {
+              throw new ParserError.INVALID_EXPRESSION_ERROR ("Found an unexpected expression for an 
assignment. Assignment should be done on variables");
+            }
             var expa = new GAssign ();
             eq.expressions.add (expa);
             expa.expressions.add (current);
diff --git a/gcalc/gcalc-gsolver.vala b/gcalc/gcalc-gsolver.vala
index 3d09b605..7ca51dc8 100644
--- a/gcalc/gcalc-gsolver.vala
+++ b/gcalc/gcalc-gsolver.vala
@@ -33,17 +33,17 @@ public class GCalc.GSolver : Object, Solver {
       p.parse (str, equation_manager);
       if (equation_manager.equations.get_n_items () == 0) {
         var err = new GErrorResult ("No equations found after parsing");
-        res = new GResult.with_error ((Expression) new GExpression (), (ErrorResult) err) as Result;
+        res = new GResult.with_error ((Expression) new GErrorExpression (), (ErrorResult) err) as Result;
       }
       var eq = equation_manager.equations.get_item (0) as MathEquation;
       if (eq == null) {
         var err = new GErrorResult ("No equations found after parsing");
-        res = new GResult.with_error ((Expression) new GExpression (), (ErrorResult) err) as Result;
+        res = new GResult.with_error ((Expression) new GErrorExpression (), (ErrorResult) err) as Result;
       }
       res = eq.solve ();
     } catch (GLib.Error e) {
       var err = new GErrorResult (e.message);
-      res = new GResult.with_error ((Expression) new GExpression (), (ErrorResult) err) as Result;
+      res = new GResult.with_error ((Expression) new GErrorExpression (), (ErrorResult) err) as Result;
     }
     return res;
   }
diff --git a/gcalc/gcalc-gvariable.vala b/gcalc/gcalc-gvariable.vala
index 30329b1c..bd9b3a3d 100644
--- a/gcalc/gcalc-gvariable.vala
+++ b/gcalc/gcalc-gvariable.vala
@@ -22,6 +22,7 @@ public class GCalc.GVariable : GExpression, Variable, Hashable {
 
   public string name { get; construct set; }
   public Constant value { get; set; }
+  public Variable bind { get; set; }
 
   construct {
     _value = new GConstant.@double (0.0);
diff --git a/gcalc/gcalc-math-equation-manager.vala b/gcalc/gcalc-math-equation-manager.vala
index 97b085c1..5bc076cd 100644
--- a/gcalc/gcalc-math-equation-manager.vala
+++ b/gcalc/gcalc-math-equation-manager.vala
@@ -21,5 +21,20 @@
 public interface GCalc.MathEquationManager : Object {
   public abstract ExpressionContainer equations { get; }
   public abstract ExpressionContainer functions { get; }
+  public virtual Variable find_variable (string name) {
+    Variable res = null;
+    foreach (Expression e in equations) {
+      var eq = e as MathEquation;
+      if (e == null) {
+        continue;
+      }
+      var v = eq.variables.find_named (name) as Variable;
+      if (v != null) {
+        res = v;
+        break;
+      }
+    }
+    return res;
+  }
 }
 
diff --git a/gcalc/gcalc-term.vala b/gcalc/gcalc-term.vala
index ba2554d8..6f06d77e 100644
--- a/gcalc/gcalc-term.vala
+++ b/gcalc/gcalc-term.vala
@@ -23,7 +23,7 @@ public interface GCalc.Term : Object, Expression {
     if (t.expressions.get_n_items () == 0) {
       return new GConstant.@double (1.0);
     }
-    Expression res = new GExpression ();
+    Expression res = new GErrorExpression ();
     var e = evaluate ();
     var e2 = t.evaluate ();
     if (e is Constant && e2 is Constant) {
@@ -79,6 +79,31 @@ public interface GCalc.Term : Object, Expression {
             current = evaluate_constants ((Constant) current, (Constant) ev, current_operator);
           }
         }
+      } else if (e is Variable) {
+        message ("Evaluating Variable '%s'", (e as Variable).name);
+        var par = e.parent;
+        while (par != null) {
+          if (par is MathEquation) {
+            break;
+          }
+          par = par.parent;
+        }
+        if (par == null) {
+          throw new TermError.EVALUATION_FAIL ("Variable's equation definition not found");
+        }
+        var res = ((MathEquation) par).solve ();
+        if (res.error != null) {
+          throw new TermError.EVALUATION_FAIL ("Variable evaluation fail: %s", res.error.to_string ());
+        }
+        var ev = res.expression;
+        if (current == null) {
+          current = ev;
+          first = false;
+        } else if (current is Constant && ev is Constant) {
+          if (current_operator != null) {
+            current = evaluate_constants ((Constant) current, (Constant) ev, current_operator);
+          }
+        }
       }
     }
     if (current == null) {
@@ -111,6 +136,6 @@ public interface GCalc.Term : Object, Expression {
 
 public errordomain GCalc.TermError {
   INVALID_OPERATOR,
-  EVALUATION_FAIL
+  EVALUATION_FAIL,
 }
 
diff --git a/gcalc/gcalc-variable.vala b/gcalc/gcalc-variable.vala
index a427a89f..d9fdeae6 100644
--- a/gcalc/gcalc-variable.vala
+++ b/gcalc/gcalc-variable.vala
@@ -21,7 +21,11 @@
 public interface GCalc.Variable : Object, Expression {
   public abstract string name { get; construct set; }
   public abstract Constant @value { get; set; }
+  public abstract Variable bind { get; set; }
   public virtual Expression evaluate () throws GLib.Error {
+    if (bind != null) {
+      return bind.evaluate ();
+    }
     if (parent == null) {
       throw new VariableError.INVALID_PARENT ("Can't access to Variable's expression definition. Invalid 
parent. Expected Assign operator");
     }
diff --git a/tests/gcalc-parsing.vala b/tests/gcalc-parsing.vala
index a44e3053..cd3cbd2d 100644
--- a/tests/gcalc-parsing.vala
+++ b/tests/gcalc-parsing.vala
@@ -896,6 +896,30 @@ class Tests {
         warning ("Error: %s", error.message);
       }
     });
+    Test.add_func ("/gcalc/parser/variables/lookup/equation",
+    ()=>{
+      try {
+        var parser = new GParser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("x=3", eqman);
+        parser.parse ("y=x", eqman);
+        assert (eqman.equations.get_n_items () == 2);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        var v = eq.variables.find_named ("x");
+        assert (v != null);
+        var eq2 = eqman.equations.get_item (1) as MathEquation;
+        assert (eq2 != null);
+        var v2 = eq2.variables.find_named ("y");
+        assert (v2 != null);
+        var v3 = eq2.variables.find_named ("x");
+        assert (v3 == null);
+        assert (eqman.find_variable ("x") != null);
+        assert (eqman.find_variable ("y") != null);
+      } catch (GLib.Error error) {
+        warning ("Error: %s", error.message);
+      }
+    });
     return Test.run ();
   }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]