]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/request/SpreadsheetExpressionVisitor.java
Adopt spreadsheet changes made in Balas development
[simantics/platform.git] / bundles / org.simantics.spreadsheet.graph / src / org / simantics / spreadsheet / graph / request / SpreadsheetExpressionVisitor.java
index e7c413a96d4c5645252cf33ed5a238a9c1e1bc9d..71466070ef099d03bbfc947570d43980b98f117a 100644 (file)
-package org.simantics.spreadsheet.graph.request;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.LinkedList;\r
-import java.util.Stack;\r
-\r
-import org.simantics.basicexpression.analysis.DepthFirstAdapter;\r
-import org.simantics.basicexpression.node.AAddressValue;\r
-import org.simantics.basicexpression.node.AConstantValue;\r
-import org.simantics.basicexpression.node.AFunctionPrimary;\r
-import org.simantics.basicexpression.node.AMultMultiplicative;\r
-import org.simantics.basicexpression.node.APlusExpression;\r
-import org.simantics.basicexpression.node.ARangeValue;\r
-import org.simantics.basicexpression.node.ARviValue;\r
-import org.simantics.basicexpression.node.ASequenceArgList;\r
-import org.simantics.basicexpression.node.ASingleArgList;\r
-import org.simantics.basicexpression.node.ASingleRange;\r
-import org.simantics.basicexpression.node.AStringValue;\r
-import org.simantics.basicexpression.node.AVariablePrimary;\r
-import org.simantics.basicexpression.node.PArgList;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.adapter.Function;\r
-import org.simantics.db.layer0.adapter.Instances;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.db.layer0.variable.Variables;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.spreadsheet.Range;\r
-import org.simantics.spreadsheet.util.SpreadsheetUtils;\r
-\r
-public class SpreadsheetExpressionVisitor extends DepthFirstAdapter {\r
-\r
-    public static final boolean DEBUG_APPLICATION = false;\r
-    public static final boolean DEBUG = false;\r
-    \r
-       public static class ApplicationException extends Exception {\r
-\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               public ApplicationException(String message) {\r
-                       super(message);\r
-               }\r
-\r
-       }\r
-\r
-       final ReadGraph graph;\r
-       final Variable cellVariable;\r
-       final Resource model;\r
-       final Resource sheet;\r
-       final int row;\r
-       final int column;\r
-       // final EvaluationEnvironmentImpl env;\r
-       Stack<Object> stack = new Stack<Object>();\r
-\r
-       HashMap<String, Function> builtins = new HashMap<String, Function>();\r
-\r
-       // class EvaluationEnvironmentImpl implements EvaluationEnvironment {\r
-       //        \r
-       // private boolean ready = false;\r
-       // private boolean valid = true;\r
-       // public HashSet<Range> deps = new HashSet<Range>();\r
-       //        \r
-       //\r
-       // @Override\r
-       // public int getColumn() {\r
-       // return column;\r
-       // }\r
-       //\r
-       // @Override\r
-       // public Model getModel() {\r
-       // return model;\r
-       // }\r
-       //\r
-       // @Override\r
-       // public int getRow() {\r
-       // return row;\r
-       // }\r
-       //        \r
-       // public void depend(Range range) {\r
-       // deps.add(range);\r
-       // }\r
-       //        \r
-       // public void listen() {\r
-       // ready = true;\r
-       // }\r
-       //        \r
-       // @Override\r
-       // public void invalidate() {\r
-       // // DependencyHandler handler = model.getAdapter(DependencyHandler.class);\r
-       // // handler.invalidate(row, column);\r
-       // if(!ready) return;\r
-       // valid = false;\r
-       // ThreadUtils.getNonBlockingWorkExecutor().execute(new Runnable() {\r
-       //\r
-       // @Override\r
-       // public void run() {\r
-       //\r
-       // Cell cell = model.get(row, column);\r
-       // UpdateHandler handler = cell.getAdapter(UpdateHandler.class);\r
-       // if(handler != null) handler.update();\r
-       //                    \r
-       // }\r
-       //                \r
-       // });\r
-       //            \r
-       // }\r
-       //        \r
-       // @Override\r
-       // public boolean isDisposed() {\r
-       // return !valid;\r
-       // }\r
-       //        \r
-       // }\r
-\r
-       public SpreadsheetExpressionVisitor(ReadGraph graph, Variable cellVariable, int row, int column) throws DatabaseException {\r
-\r
-               // assert(model != null);\r
-               // // assert(graph != null);\r
-               // // assert(sheet != null);\r
-               this.graph = graph;\r
-               this.cellVariable = cellVariable;\r
-               this.model = Variables.getModel(graph, cellVariable);\r
-               Resource cell = cellVariable.getPossiblePropertyValue(graph, Variables.RESOURCE); \r
-               this.sheet = graph.getPossibleObject(cell, Layer0.getInstance(graph).PartOf);\r
-//             this.sheet = sheet;\r
-//             this.model = model;\r
-               this.row = row;\r
-               this.column = column;\r
-               //        \r
-               // builtins.put("Sequence", new Sequence());\r
-               // builtins.put("Set", new Set());\r
-               // builtins.put("SetBlock", new SetBlock());\r
-               // builtins.put("Sum", new Sum());\r
-               // builtins.put("Naturals", new Naturals());\r
-               //        \r
-               // env = new EvaluationEnvironmentImpl();\r
-               //        \r
-\r
-               // SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);\r
-               //          \r
-               // builtins.put("SUBSCRIPT", new Runnable() {\r
-               //\r
-               // @Override\r
-               // public void run() {\r
-               //                \r
-               // try {\r
-               //                \r
-               // int column = ((Double)stack.pop()).intValue();\r
-               // int row = ((Double)stack.pop()).intValue();\r
-               // Object value = stack.pop();\r
-               //                    \r
-               // //System.out.println("subscript(value=" + value + " row=" + row +\r
-               // " column=" + column + ")");\r
-               //                    \r
-               // if(value instanceof Collection) {\r
-               // stack.push(((Collection)value).toArray()[row]);\r
-               // }\r
-               //                    \r
-               // } catch (Throwable t) {\r
-               // t.printStackTrace();\r
-               // }\r
-               //                \r
-               // }\r
-               //              \r
-               // });\r
-\r
-       }\r
-\r
-       public Object getResult() {\r
-               return stack.pop();\r
-       }\r
-\r
-       public void outAConstantValue(AConstantValue node) {\r
-               if(DEBUG) System.out.println("outAConstantValue " + node);\r
-               stack.push(Double.valueOf(node.toString()));\r
-       }\r
-\r
-       public void outAStringValue(AStringValue node) {\r
-               if(DEBUG) System.out.println("outAStringValue " + node);\r
-               String value = node.toString();\r
-               stack.push(value.substring(1, value.length() - 2).trim());\r
-       }\r
-\r
-       public void outAAddressValue(AAddressValue node) {\r
-               if(DEBUG) System.out.println("outAAddressValue " + node);\r
-               stack.push('&' + node.getRange().toString());\r
-       }\r
-\r
-       @Override\r
-       public void outASingleRange(ASingleRange node) {\r
-               \r
-               if(DEBUG) System.out.println("outASingleRange " + node);\r
-               \r
-       }\r
-       \r
-       @Override\r
-       public void outARviValue(ARviValue node) {\r
-               \r
-               if(DEBUG) System.out.println("outARviValue " + node);\r
-               \r
-               String rvi = node.toString().trim();\r
-               \r
-               try {\r
-                       System.out.println("browsing at " + cellVariable.getURI(graph));\r
-                       Variable var = cellVariable.browse(graph, rvi);\r
-                       stack.push(var);\r
-               } catch (DatabaseException e) {\r
-                       e.printStackTrace();\r
-               }\r
-               \r
-       }\r
-       \r
-       @Override\r
-       public void outAVariablePrimary(AVariablePrimary node) {\r
-               \r
-               if(DEBUG) System.out.println("outAVariablePrimary " + node);\r
-               \r
-               String identifier = node.toString().trim();\r
-\r
-               Range range = SpreadsheetUtils.decodeRange(identifier, row, column);\r
-               if (range.size() != 1) {\r
-                       ArrayList<Object> value = new ArrayList<Object>();\r
-                       for (int c = range.startColumn; c <= range.endColumn; c++) {\r
-                               for (int r = range.startRow; r <= range.endRow; r++) {\r
-                                       try {\r
-                                               String location = SpreadsheetUtils.cellName(r, c);\r
-                                               Variable cell = cellVariable.getChild(graph, location);\r
-                                               System.out.println("cell=" + cell.getURI(graph));\r
-                                               String label = cell.getPossiblePropertyValue(graph, "Label");\r
-                                               System.out.println("lavel=" + label);\r
-                                               value.add(label);\r
-                                       } catch (DatabaseException e) {\r
-                                               value.add(null);\r
-                                       }\r
-                               }\r
-                       }\r
-                       stack.push(value);\r
-                       // System.out.println("pushing " + value);\r
-                       return;\r
-               }\r
-\r
-//             try {\r
-//                     String location = SpreadsheetUtils.cellName(range.startRow,\r
-//                                     range.startColumn);\r
-//                     stack.push(graph.syncRequest(new CellResult(sheet, model, location)));\r
-//             } catch (DatabaseException e) {\r
-//                     stack.push(null);\r
-//             }\r
-               \r
-       }\r
-       \r
-       public void outARangeValue(ARangeValue node) {\r
-\r
-               if(DEBUG) System.out.println("outARangeValue " + node);\r
-\r
-               String identifier = node.getRange().toString().trim();\r
-               // try {\r
-\r
-//             Range range = SpreadsheetUtils.decodeRange(identifier, row, column);\r
-//             // env.depend(range);\r
-//             if (range.size() != 1) {\r
-//                     ArrayList<Object> value = new ArrayList<Object>();\r
-//                     for (int c = range.startColumn; c <= range.endColumn; c++) {\r
-//                             for (int r = range.startRow; r <= range.endRow; r++) {\r
-//                                     try {\r
-//                                             String location = SpreadsheetUtils.cellName(r, c);\r
-//                                             \r
-//                                             value.add(graph\r
-//                                                             .syncRequest(new CellResult(sheet, model, location)));\r
-//                                     } catch (DatabaseException e) {\r
-//                                             value.add(null);\r
-//                                     }\r
-//                             }\r
-//                     }\r
-//                     stack.push(value);\r
-//                     // System.out.println("pushing " + value);\r
-//                     return;\r
-//             }\r
-//\r
-//             try {\r
-//                     String location = SpreadsheetUtils.cellName(range.startRow,\r
-//                                     range.startColumn);\r
-//                     stack.push(graph.syncRequest(new CellResult(sheet, model, location)));\r
-//             } catch (DatabaseException e) {\r
-//                     stack.push(null);\r
-//             }\r
-\r
-       }\r
-\r
-       private double extractValue(Object o) {\r
-               if (o instanceof Number) {\r
-                       return ((Number) o).doubleValue();\r
-               } else if (o instanceof String) {\r
-                       return Double.valueOf((String) o);\r
-               } else {\r
-                       return Double.NaN;\r
-               }\r
-       }\r
-\r
-       public void outAPlusExpression(APlusExpression node) {\r
-               \r
-               if(DEBUG) System.out.println("outAPlusExpression " + node);\r
-               \r
-               Object o1 = stack.pop();\r
-               Object o2 = stack.pop();\r
-               double d1 = extractValue(o1);\r
-               double d2 = extractValue(o2);\r
-               stack.push(d1 + d2);\r
-               // System.out.println("plus " + d1 + " " + d2);\r
-       }\r
-\r
-       public void outAMultMultiplicative(AMultMultiplicative node) {\r
-               \r
-               if(DEBUG) System.out.println("outAMultiplicative " + node);\r
-               \r
-               Object o1 = stack.pop();\r
-               Object o2 = stack.pop();\r
-               double d1 = extractValue(o1);\r
-               double d2 = extractValue(o2);\r
-               stack.push(d1 * d2);\r
-               // System.out.println("mult " + d1 + " " + d2);\r
-       }\r
-\r
-       int countArguments(PArgList args) {\r
-               if (args == null)\r
-                       return 0;\r
-               if (args instanceof ASingleArgList)\r
-                       return 1;\r
-               ASequenceArgList seq = (ASequenceArgList) args;\r
-               return 1 + countArguments(seq.getArgList());\r
-       }\r
-\r
-       public void outAFunctionPrimary(AFunctionPrimary node) {\r
-\r
-               if(DEBUG) System.out.println("outAFunctionPrimary " + node);\r
-\r
-               try {\r
-\r
-                       String functionName = node.getFunc().getText().replace("(", "");\r
-\r
-                       if (DEBUG_APPLICATION)\r
-                           System.out.println("function apply " + functionName);\r
-\r
-                       Function function = builtins.get(functionName);\r
-                       if (function != null) {\r
-\r
-                               LinkedList<Object> args = new LinkedList<Object>();\r
-                               int argc = countArguments(node.getArgList());\r
-                               for (int i = 0; i < argc; i++) {\r
-                                       args.addFirst(stack.pop());\r
-                               }\r
-                               args.addFirst(sheet);\r
-                               args.addFirst(model);\r
-\r
-                               Object result = function.apply(graph, args);\r
-                               stack.push(result);\r
-\r
-                       } else {\r
-\r
-                           Layer0 L0 = Layer0.getInstance(graph);\r
-                               Instances instances = graph.adapt(L0.Function, Instances.class);\r
-                               Collection<Resource> functions = instances.find(graph, model,\r
-                                               "Name:" + functionName);\r
-                   if (DEBUG_APPLICATION)\r
-                       System.out.println("Found " + functions.size() + " matches.");\r
-                               if (functions != null && functions.size() == 1) {\r
-\r
-                                       Resource functionResource = functions.iterator().next();\r
-                                       function = graph.adapt(functionResource, Function.class);\r
-                                       LinkedList<Object> args = new LinkedList<Object>();\r
-                                       int argc = countArguments(node.getArgList());\r
-                                       for (int i = 0; i < argc; i++) {\r
-                                               args.addFirst(stack.pop());\r
-                                       }\r
-                                       args.addFirst(cellVariable);\r
-                                       //args.addFirst(model);\r
-                                       // System.out.println("args=" +\r
-                                       // Arrays.toString(args.toArray()));\r
-                                       Object result = function.apply(graph, args.toArray());\r
-                                       stack.push(result);\r
-\r
-                               } else {\r
-\r
-                                       stack.push(null);\r
-\r
-                               }\r
-\r
-                       }\r
-\r
-               } catch (DatabaseException e) {\r
-\r
-                       stack.push(null);\r
-\r
-               }\r
-\r
-       }\r
-\r
-}\r
+package org.simantics.spreadsheet.graph.request;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Stack;
+
+import org.simantics.basicexpression.analysis.DepthFirstAdapter;
+import org.simantics.basicexpression.node.AAddressValue;
+import org.simantics.basicexpression.node.AConstantValue;
+import org.simantics.basicexpression.node.AFunctionPrimary;
+import org.simantics.basicexpression.node.AMultMultiplicative;
+import org.simantics.basicexpression.node.APlusExpression;
+import org.simantics.basicexpression.node.ARangeValue;
+import org.simantics.basicexpression.node.ARviValue;
+import org.simantics.basicexpression.node.ASequenceArgList;
+import org.simantics.basicexpression.node.ASingleArgList;
+import org.simantics.basicexpression.node.ASingleRange;
+import org.simantics.basicexpression.node.AStringValue;
+import org.simantics.basicexpression.node.AVariablePrimary;
+import org.simantics.basicexpression.node.PArgList;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.adapter.Function;
+import org.simantics.db.layer0.adapter.Instances;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.layer0.Layer0;
+import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
+
+public class SpreadsheetExpressionVisitor extends DepthFirstAdapter {
+
+    public static final boolean DEBUG_APPLICATION = false;
+    public static final boolean DEBUG = false;
+    
+       public static class ApplicationException extends Exception {
+
+               private static final long serialVersionUID = 1L;
+
+               public ApplicationException(String message) {
+                       super(message);
+               }
+
+       }
+
+       final ReadGraph graph;
+       final Variable cellVariable;
+       final Resource model;
+       final Resource sheet;
+       final int row;
+       final int column;
+       // final EvaluationEnvironmentImpl env;
+       Stack<Object> stack = new Stack<Object>();
+
+       HashMap<String, Function> builtins = new HashMap<String, Function>();
+
+       // class EvaluationEnvironmentImpl implements EvaluationEnvironment {
+       //        
+       // private boolean ready = false;
+       // private boolean valid = true;
+       // public HashSet<Range> deps = new HashSet<Range>();
+       //        
+       //
+       // @Override
+       // public int getColumn() {
+       // return column;
+       // }
+       //
+       // @Override
+       // public Model getModel() {
+       // return model;
+       // }
+       //
+       // @Override
+       // public int getRow() {
+       // return row;
+       // }
+       //        
+       // public void depend(Range range) {
+       // deps.add(range);
+       // }
+       //        
+       // public void listen() {
+       // ready = true;
+       // }
+       //        
+       // @Override
+       // public void invalidate() {
+       // // DependencyHandler handler = model.getAdapter(DependencyHandler.class);
+       // // handler.invalidate(row, column);
+       // if(!ready) return;
+       // valid = false;
+       // ThreadUtils.getNonBlockingWorkExecutor().execute(new Runnable() {
+       //
+       // @Override
+       // public void run() {
+       //
+       // Cell cell = model.get(row, column);
+       // UpdateHandler handler = cell.getAdapter(UpdateHandler.class);
+       // if(handler != null) handler.update();
+       //                    
+       // }
+       //                
+       // });
+       //            
+       // }
+       //        
+       // @Override
+       // public boolean isDisposed() {
+       // return !valid;
+       // }
+       //        
+       // }
+
+       public SpreadsheetExpressionVisitor(ReadGraph graph, Variable cellVariable, int row, int column) throws DatabaseException {
+
+               // assert(model != null);
+               // // assert(graph != null);
+               // // assert(sheet != null);
+               this.graph = graph;
+               this.cellVariable = cellVariable;
+               this.model = Variables.getModel(graph, cellVariable);
+               Resource cell = cellVariable.getPossiblePropertyValue(graph, Variables.RESOURCE); 
+               this.sheet = graph.getPossibleObject(cell, Layer0.getInstance(graph).PartOf);
+//             this.sheet = sheet;
+//             this.model = model;
+               this.row = row;
+               this.column = column;
+               //        
+               // builtins.put("Sequence", new Sequence());
+               // builtins.put("Set", new Set());
+               // builtins.put("SetBlock", new SetBlock());
+               // builtins.put("Sum", new Sum());
+               // builtins.put("Naturals", new Naturals());
+               //        
+               // env = new EvaluationEnvironmentImpl();
+               //        
+
+               // SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
+               //          
+               // builtins.put("SUBSCRIPT", new Runnable() {
+               //
+               // @Override
+               // public void run() {
+               //                
+               // try {
+               //                
+               // int column = ((Double)stack.pop()).intValue();
+               // int row = ((Double)stack.pop()).intValue();
+               // Object value = stack.pop();
+               //                    
+               // //System.out.println("subscript(value=" + value + " row=" + row +
+               // " column=" + column + ")");
+               //                    
+               // if(value instanceof Collection) {
+               // stack.push(((Collection)value).toArray()[row]);
+               // }
+               //                    
+               // } catch (Throwable t) {
+               // t.printStackTrace();
+               // }
+               //                
+               // }
+               //              
+               // });
+
+       }
+
+       public Object getResult() {
+               return stack.pop();
+       }
+
+       public void outAConstantValue(AConstantValue node) {
+               if(DEBUG) System.out.println("outAConstantValue " + node);
+               stack.push(Double.valueOf(node.toString()));
+       }
+
+       public void outAStringValue(AStringValue node) {
+               if(DEBUG) System.out.println("outAStringValue " + node);
+               String value = node.toString();
+               stack.push(value.substring(1, value.length() - 2).trim());
+       }
+
+       public void outAAddressValue(AAddressValue node) {
+               if(DEBUG) System.out.println("outAAddressValue " + node);
+               stack.push('&' + node.getRange().toString());
+       }
+
+       @Override
+       public void outASingleRange(ASingleRange node) {
+               
+               if(DEBUG) System.out.println("outASingleRange " + node);
+               
+       }
+       
+       @Override
+       public void outARviValue(ARviValue node) {
+               
+               if(DEBUG) System.out.println("outARviValue " + node);
+               
+               String rvi = node.toString().trim();
+               
+               try {
+                       System.out.println("browsing at " + cellVariable.getURI(graph));
+                       Variable var = cellVariable.browse(graph, rvi);
+                       stack.push(var);
+               } catch (DatabaseException e) {
+                       e.printStackTrace();
+               }
+               
+       }
+       
+       @Override
+       public void outAVariablePrimary(AVariablePrimary node) {
+               
+               if(DEBUG) System.out.println("outAVariablePrimary " + node);
+               
+               String identifier = node.toString().trim();
+
+               Range range = Spreadsheets.decodeRange(identifier, row, column);
+               if (range.size() != 1) {
+                       ArrayList<Object> value = new ArrayList<Object>();
+                       for (int c = range.startColumn; c <= range.endColumn; c++) {
+                               for (int r = range.startRow; r <= range.endRow; r++) {
+                                       try {
+                                               String location = Spreadsheets.cellName(r, c);
+                                               Variable cell = cellVariable.getChild(graph, location);
+                                               System.out.println("cell=" + cell.getURI(graph));
+                                               String label = cell.getPossiblePropertyValue(graph, "Label");
+                                               System.out.println("lavel=" + label);
+                                               value.add(label);
+                                       } catch (DatabaseException e) {
+                                               value.add(null);
+                                       }
+                               }
+                       }
+                       stack.push(value);
+                       // System.out.println("pushing " + value);
+                       return;
+               }
+
+//             try {
+//                     String location = SpreadsheetUtils.cellName(range.startRow,
+//                                     range.startColumn);
+//                     stack.push(graph.syncRequest(new CellResult(sheet, model, location)));
+//             } catch (DatabaseException e) {
+//                     stack.push(null);
+//             }
+               
+       }
+       
+       public void outARangeValue(ARangeValue node) {
+
+               if(DEBUG) System.out.println("outARangeValue " + node);
+
+               String identifier = node.getRange().toString().trim();
+               // try {
+
+//             Range range = SpreadsheetUtils.decodeRange(identifier, row, column);
+//             // env.depend(range);
+//             if (range.size() != 1) {
+//                     ArrayList<Object> value = new ArrayList<Object>();
+//                     for (int c = range.startColumn; c <= range.endColumn; c++) {
+//                             for (int r = range.startRow; r <= range.endRow; r++) {
+//                                     try {
+//                                             String location = SpreadsheetUtils.cellName(r, c);
+//                                             
+//                                             value.add(graph
+//                                                             .syncRequest(new CellResult(sheet, model, location)));
+//                                     } catch (DatabaseException e) {
+//                                             value.add(null);
+//                                     }
+//                             }
+//                     }
+//                     stack.push(value);
+//                     // System.out.println("pushing " + value);
+//                     return;
+//             }
+//
+//             try {
+//                     String location = SpreadsheetUtils.cellName(range.startRow,
+//                                     range.startColumn);
+//                     stack.push(graph.syncRequest(new CellResult(sheet, model, location)));
+//             } catch (DatabaseException e) {
+//                     stack.push(null);
+//             }
+
+       }
+
+       private double extractValue(Object o) {
+               if (o instanceof Number) {
+                       return ((Number) o).doubleValue();
+               } else if (o instanceof String) {
+                       return Double.valueOf((String) o);
+               } else {
+                       return Double.NaN;
+               }
+       }
+
+       public void outAPlusExpression(APlusExpression node) {
+               
+               if(DEBUG) System.out.println("outAPlusExpression " + node);
+               
+               Object o1 = stack.pop();
+               Object o2 = stack.pop();
+               double d1 = extractValue(o1);
+               double d2 = extractValue(o2);
+               stack.push(d1 + d2);
+               // System.out.println("plus " + d1 + " " + d2);
+       }
+
+       public void outAMultMultiplicative(AMultMultiplicative node) {
+               
+               if(DEBUG) System.out.println("outAMultiplicative " + node);
+               
+               Object o1 = stack.pop();
+               Object o2 = stack.pop();
+               double d1 = extractValue(o1);
+               double d2 = extractValue(o2);
+               stack.push(d1 * d2);
+               // System.out.println("mult " + d1 + " " + d2);
+       }
+
+       int countArguments(PArgList args) {
+               if (args == null)
+                       return 0;
+               if (args instanceof ASingleArgList)
+                       return 1;
+               ASequenceArgList seq = (ASequenceArgList) args;
+               return 1 + countArguments(seq.getArgList());
+       }
+
+       public void outAFunctionPrimary(AFunctionPrimary node) {
+
+               if(DEBUG) System.out.println("outAFunctionPrimary " + node);
+
+               try {
+
+                       String functionName = node.getFunc().getText().replace("(", "");
+
+                       if (DEBUG_APPLICATION)
+                           System.out.println("function apply " + functionName);
+
+                       Function function = builtins.get(functionName);
+                       if (function != null) {
+
+                               LinkedList<Object> args = new LinkedList<Object>();
+                               int argc = countArguments(node.getArgList());
+                               for (int i = 0; i < argc; i++) {
+                                       args.addFirst(stack.pop());
+                               }
+                               args.addFirst(sheet);
+                               args.addFirst(model);
+
+                               Object result = function.apply(graph, args);
+                               stack.push(result);
+
+                       } else {
+
+                           Layer0 L0 = Layer0.getInstance(graph);
+                               Instances instances = graph.adapt(L0.Function, Instances.class);
+                               Collection<Resource> functions = instances.find(graph, model,
+                                               "Name:" + functionName);
+                   if (DEBUG_APPLICATION)
+                       System.out.println("Found " + functions.size() + " matches.");
+                               if (functions != null && functions.size() == 1) {
+
+                                       Resource functionResource = functions.iterator().next();
+                                       function = graph.adapt(functionResource, Function.class);
+                                       LinkedList<Object> args = new LinkedList<Object>();
+                                       int argc = countArguments(node.getArgList());
+                                       for (int i = 0; i < argc; i++) {
+                                               args.addFirst(stack.pop());
+                                       }
+                                       args.addFirst(cellVariable);
+                                       //args.addFirst(model);
+                                       // System.out.println("args=" +
+                                       // Arrays.toString(args.toArray()));
+                                       Object result = function.apply(graph, args.toArray());
+                                       stack.push(result);
+
+                               } else {
+
+                                       stack.push(null);
+
+                               }
+
+                       }
+
+               } catch (DatabaseException e) {
+
+                       stack.push(null);
+
+               }
+
+       }
+
+}