[gnome-calculator/60-split-out-a-backend-library] gcalc: saving variables values in manager and equations
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calculator/60-split-out-a-backend-library] gcalc: saving variables values in manager and equations
- Date: Sun, 6 Jan 2019 17:16:37 +0000 (UTC)
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]