--- /dev/null
+package org.simantics.graph.compiler.internal.translation;\r
+\r
+import java.util.Collection;\r
+\r
+import org.antlr.runtime.tree.Tree;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.ArrayBinding;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.BooleanBinding;\r
+import org.simantics.databoard.binding.ByteBinding;\r
+import org.simantics.databoard.binding.DoubleBinding;\r
+import org.simantics.databoard.binding.FloatBinding;\r
+import org.simantics.databoard.binding.IntegerBinding;\r
+import org.simantics.databoard.binding.LongBinding;\r
+import org.simantics.databoard.binding.MapBinding;\r
+import org.simantics.databoard.binding.OptionalBinding;\r
+import org.simantics.databoard.binding.RecordBinding;\r
+import org.simantics.databoard.binding.StringBinding;\r
+import org.simantics.databoard.binding.UnionBinding;\r
+import org.simantics.databoard.binding.VariantBinding;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.graph.compiler.internal.parsing.GraphParser;\r
+import org.simantics.ltk.ISource;\r
+import org.simantics.ltk.Problem;\r
+import org.simantics.ltk.antlr.ANTLRUtils;\r
+\r
+public class DataValueTranslator {\r
+ \r
+ ISource source;\r
+ Collection<Problem> problems;\r
+ \r
+ public DataValueTranslator(ISource source, Collection<Problem> problems) {\r
+ this.source = source;\r
+ this.problems = problems;\r
+ }\r
+\r
+ public Object translate(Tree _tree, Binding binding) {\r
+ while(_tree.getType() == GraphParser.TUPLE && \r
+ _tree.getChildCount()==1)\r
+ _tree = _tree.getChild(0);\r
+ final Tree tree = _tree;\r
+ return binding.accept(new Binding.Visitor<Object>() {\r
+\r
+ @Override\r
+ public Object visit(ArrayBinding b) {\r
+ if(tree.getType() == GraphParser.ARRAY) {\r
+ int count = tree.getChildCount();\r
+ Object[] components = new Object[count];\r
+ Binding componentBinding = b.getComponentBinding();\r
+ for(int i=0;i<count;++i)\r
+ components[i] = translate(tree.getChild(i),\r
+ componentBinding\r
+ );\r
+ return b.createUnchecked(components);\r
+ }\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(BooleanBinding b) {\r
+ if(tree.getType() == GraphParser.TRUE)\r
+ return b.createUnchecked(true);\r
+ else if(tree.getType() == GraphParser.FALSE)\r
+ return b.createUnchecked(false);\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(DoubleBinding b) {\r
+ if(tree.getType() == GraphParser.INT || tree.getType() == GraphParser.FLOAT)\r
+ return b.createUnchecked(tree.getText());\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(FloatBinding b) {\r
+ if(tree.getType() == GraphParser.INT || tree.getType() == GraphParser.FLOAT)\r
+ return b.createUnchecked(tree.getText());\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(IntegerBinding b) {\r
+ if(tree.getType() == GraphParser.INT)\r
+ return b.createUnchecked(tree.getText());\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(ByteBinding b) {\r
+ if(tree.getType() == GraphParser.INT)\r
+ return b.createUnchecked(tree.getText());\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(LongBinding b) {\r
+ if(tree.getType() == GraphParser.INT)\r
+ return b.createUnchecked(tree.getText());\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(OptionalBinding b) {\r
+ if(tree.getType() == GraphParser.NO_VALUE) \r
+ return b.createNoValueUnchecked();\r
+ else\r
+ return b.createValueUnchecked(\r
+ translate(tree, b.getComponentBinding())\r
+ );\r
+ }\r
+\r
+ @Override\r
+ public Object visit(RecordBinding b) {\r
+ boolean hadError = false;\r
+ if(tree.getType() == GraphParser.RECORD) {\r
+ int count = tree.getChildCount();\r
+ Object[] components = new Object[b.componentBindings.length];\r
+ boolean[] setValues = new boolean[b.componentBindings.length];\r
+ for(int i=0;i<count;++i) {\r
+ Tree assignment = tree.getChild(i);\r
+ String field = assignment.getChild(0).getText();\r
+ Integer comp = \r
+ b.type().getComponentIndex(field);\r
+ if(comp == null) {\r
+ hadError = true;\r
+ problems.add(new Problem(\r
+ ANTLRUtils.location(source, tree), \r
+ "Record type " + b.type() + " does not have a field " + field + "."\r
+ ));\r
+ }\r
+ else { \r
+ components[comp] = translate(\r
+ assignment.getChild(1),\r
+ b.getComponentBinding(comp)\r
+ );\r
+ setValues[comp] = true;\r
+ }\r
+ }\r
+ try {\r
+ for(int i=0;i<b.componentBindings.length;++i) \r
+ if(!setValues[i]) {\r
+ if(b.componentBindings[i] instanceof OptionalBinding)\r
+ components[i] = b.componentBindings[i].createDefault();\r
+ else \r
+ problems.add(new Problem(\r
+ ANTLRUtils.location(source, tree), \r
+ "Not all fields of the record are given."\r
+ ));\r
+ return b.createDefaultUnchecked();\r
+ }\r
+ return b.create(components);\r
+ } catch(BindingException e) { \r
+ }\r
+ }\r
+ if(tree.getType() == GraphParser.TUPLE) {\r
+ int count = tree.getChildCount();\r
+ if(count == b.getComponentCount()) { \r
+ Object[] components = new Object[count];\r
+ for(int i=0;i<count;++i)\r
+ components[i] = \r
+ translate(tree.getChild(i), \r
+ b.getComponentBinding(i));\r
+ return b.createUnchecked(components);\r
+ }\r
+ }\r
+ if(!hadError)\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(StringBinding b) {\r
+ if(tree.getType() == GraphParser.STRING) {\r
+ String str = tree.getText();\r
+ if(str.charAt(1) == '"' && str.length() >= 6)\r
+ return b.createUnchecked(str.substring(3, str.length()-3));\r
+ else\r
+ return b.createUnchecked(str.substring(1, str.length()-1));\r
+ }\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(UnionBinding b) {\r
+ if(tree.getType() == GraphParser.TAGGED_VALUE) {\r
+ String tag = tree.getChild(0).getText();\r
+ Integer comp = b.type().getComponentIndex(tag);\r
+ if(comp != null) {\r
+ if(tree.getChildCount() == 2)\r
+ return b.createUnchecked(comp, \r
+ translate(\r
+ tree.getChild(1), \r
+ b.getComponentBinding(comp)\r
+ ));\r
+ else {\r
+ Binding binding = b.getComponentBinding(comp);\r
+ if(binding instanceof RecordBinding &&\r
+ ((RecordBinding)binding).getComponentCount() == 0)\r
+ return b.createUnchecked(comp, \r
+ ((RecordBinding)binding).createUnchecked());\r
+ else\r
+ typeError(tree, binding);\r
+ }\r
+ }\r
+ }\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked(); \r
+ }\r
+\r
+ @Override\r
+ public Object visit(VariantBinding b) {\r
+ if(tree.getType() == GraphParser.VARIANT) {\r
+ Datatype type = \r
+ new DataTypeTranslator(source, problems).translate(tree.getChild(0));\r
+ Binding binding = Bindings.getBinding(type);\r
+ \r
+ Object value = translate(tree.getChild(1), binding);\r
+ return b.createUnchecked(binding, value);\r
+ }\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+\r
+ @Override\r
+ public Object visit(MapBinding b) {\r
+ if(tree.getType() == GraphParser.MAP) {\r
+ int count = tree.getChildCount();\r
+ Object[] keys = new Object[count];\r
+ Object[] values = new Object[count];\r
+ Binding keyBinding = b.getKeyBinding();\r
+ Binding valueBinding = b.getValueBinding();\r
+ for(int i=0;i<count;++i) {\r
+ keys[i] = translate(tree.getChild(i).getChild(0), keyBinding);\r
+ values[i] = translate(tree.getChild(i).getChild(1), valueBinding);\r
+ }\r
+ return b.createUnchecked(keys, values);\r
+ }\r
+ typeError(tree, b);\r
+ return b.createDefaultUnchecked();\r
+ }\r
+ });\r
+ }\r
+ \r
+ private void typeError(Tree tree, Binding binding) { \r
+ problems.add(new Problem(\r
+ ANTLRUtils.location(source, tree), \r
+ "Value does not correspond to the data type " + binding.type() + "."\r
+ ));\r
+ }\r
+ \r
+}\r