X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fruntime%2FValueConversion.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fruntime%2FValueConversion.java;h=049799566818015cb8359d9e5bcd0714267811ce;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java new file mode 100644 index 000000000..049799566 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java @@ -0,0 +1,269 @@ +package org.simantics.scl.compiler.runtime; + + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.scl.compiler.types.TApply; +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; + +public class ValueConversion { + + public static Number convertNumber(TCon expectedType, Number value) { + if (expectedType == Types.DOUBLE) { + if (value instanceof Double) return value; + else return new Double(value.doubleValue()); + } + else if (expectedType == Types.INTEGER) { + if (value instanceof Integer) return value; + else return new Integer(value.intValue()); + } + else if (expectedType == Types.FLOAT) { + if (value instanceof Float) return value; + else return new Float(value.floatValue()); + } + else if (expectedType == Types.BYTE) { + if (value instanceof Byte) return value; + else return new Byte(value.byteValue()); + } + else if (expectedType == Types.SHORT) { + if (value instanceof Short) return value; + else return new Short(value.shortValue()); + } + else if (expectedType == Types.LONG) { + if (value instanceof Long) return value; + else return new Long(value.longValue()); + } + + // Not expecting a number type + return value; + } + + public static Object parsePrimitive(TCon expectedType, String value) { + try { + if (expectedType == Types.DOUBLE) { + return Double.parseDouble(value); + } + else if (expectedType == Types.INTEGER) { + return Integer.parseInt(value); + } + else if (expectedType == Types.FLOAT) { + return Float.parseFloat(value); + } + else if (expectedType == Types.BYTE) { + return Byte.parseByte(value); + } + else if (expectedType == Types.SHORT) { + return Short.parseShort(value); + } + else if (expectedType == Types.LONG) { + return Long.parseLong(value); + } + else if (expectedType == Types.BOOLEAN) { + return Boolean.parseBoolean(value); + } + else if (expectedType == Types.CHARACTER && value.length() == 1) { + return value.charAt(0); + } + } catch(NumberFormatException e) { + e.printStackTrace(); + } + + return value; + } + + public static Class getNativeClass(Type expectedType) { + if (expectedType == Types.STRING) + return String.class; + else if (expectedType == Types.DOUBLE) + return Double.class; + else if (expectedType == Types.INTEGER) + return Integer.class; + else if (expectedType == Types.FLOAT) + return Float.class; + else if (expectedType == Types.BYTE) + return Byte.class; + else if (expectedType == Types.SHORT) + return Short.class; + else if (expectedType == Types.LONG) + return Long.class; + else if (expectedType == Types.BOOLEAN) + return Boolean.class; + else if (expectedType == Types.CHARACTER) + return Character.class; + else + return Object.class; + } + + public static Class getNativePrimitiveClass(Type expectedType) { + if (expectedType == Types.STRING) + return String.class; + else if (expectedType == Types.DOUBLE) + return double.class; + else if (expectedType == Types.INTEGER) + return int.class; + else if (expectedType == Types.FLOAT) + return float.class; + else if (expectedType == Types.BYTE) + return byte.class; + else if (expectedType == Types.SHORT) + return short.class; + else if (expectedType == Types.LONG) + return long.class; + else if (expectedType == Types.BOOLEAN) + return boolean.class; + else if (expectedType == Types.CHARACTER) + return char.class; + else + return Object.class; + } + + @SuppressWarnings("unchecked") + public static boolean needsConversion(Type expectedType, Object value) { + if (!needsConversion(expectedType, value.getClass(), false)) + return false; + + if (expectedType instanceof TApply) { + TApply apply = (TApply)expectedType; + if (apply.function == Types.LIST) { + if (!(value instanceof List)) + return true; + else { + for (Object item : (List)value) { + if (needsConversion(apply.parameter, item)) + return true; + } + return false; + } + } + } + + return true; + } + + public static boolean needsConversion(Type expectedType, Class clazz, boolean needPrimitive) { + if (expectedType instanceof TCon) { + if (needPrimitive && Types.isPrimitive(expectedType)) { + Class expectedClass = getNativePrimitiveClass(expectedType); + if (expectedClass.isPrimitive()) + return clazz == expectedClass; + else + return expectedClass.isAssignableFrom(clazz); + } + else if (clazz.isPrimitive()) { + return true; + } + else { + return !getNativeClass(expectedType).isAssignableFrom(clazz); + } + } + else if (expectedType instanceof TApply) { + TApply apply = (TApply)expectedType; + if (apply.function == Types.LIST) { + return true; + } + else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) { + if (!clazz.isArray()) + return true; + else { + boolean needPrimitive2 = apply.function != Types.ARRAY; + return needsConversion(apply.parameter, clazz.getComponentType(), needPrimitive2); + } + } + } + + return false; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static Object fromDynamic(Type expectedType, Object value) { + if (value == null) + return null; + else if (value instanceof Variant) + return fromDynamic(expectedType, ((Variant)value).getValue()); + else if (expectedType == Types.DYNAMIC) + return value; + else if (!needsConversion(expectedType, value)) + return value; + + if(expectedType instanceof TCon) { + TCon con = (TCon)expectedType; + if (con == Types.STRING) + return value.toString(); + else if (value instanceof Number) + return convertNumber(con, (Number)value); + else if (value instanceof String && Types.isPrimitive(con)) + return parsePrimitive(con, (String)value); + } + else if(expectedType instanceof TApply) { + TApply apply = (TApply)expectedType; + Type expectedComponentType = apply.parameter; + + if(apply.function == Types.LIST) { + Class valueClass = value.getClass(); + + if(valueClass.isArray()) { + Class componentType = valueClass.getComponentType(); + if(needsConversion(expectedComponentType, componentType, false)) { + int length = Array.getLength(value); + ArrayList list = new ArrayList(length); + for(int i=0;i valueClass = value.getClass(); + Class expectedComponentClass = apply.function != Types.ARRAY ? + getNativePrimitiveClass(expectedComponentType) : + getNativeClass(expectedComponentType); + + if(valueClass.isArray()) { + Class componentType = valueClass.getComponentType(); + int length = Array.getLength(value); + Object array = Array.newInstance(expectedComponentClass, length); + if (needsConversion(expectedComponentType, componentType, apply.function != Types.ARRAY)) { + for(int i=0;i list = new ArrayList(); + for (Object item : (Iterable)value) { + list.add(fromDynamic(expectedComponentType, item)); + } + if (apply.function != Types.ARRAY && expectedComponentClass.isPrimitive()) { + int length = list.size(); + Object array = Array.newInstance(expectedComponentClass, length); + for (int i = 0; i < length; i++) + Array.set(array, i, list.get(i)); + return array; + } + else + return list.toArray(); + } + } + } + return value; + } +}