From: Hannu Niemistö Date: Tue, 20 Dec 2016 10:09:30 +0000 (+0200) Subject: Merged changes from feature/scl to master. X-Git-Tag: v1.26.0~18 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=a8758de5bc19e5adb3f618d3038743a164f09912;p=simantics%2Fplatform.git Merged changes from feature/scl to master. This commit contains lots of SCL compiler and runtime changes: * New CHR-rule based sublanguage. This change alters meaning of when-keyword and so some code using when may break. * Removed type classes Eq and Hashable. Compiler now generates and uses Java methods equals and hashCode. This change is needed for better interoperability with Java code. * Type based overloading for symbols imported from different modules * Some expressions ignore their return value (statements in do/let/where, if and match cases if the return value of if/match is ignored). These expressions can have any type and if/match expression branches may have different types. Also if-expressions may have only else branch. If the return value of apply-experssion is ignored, the expression cannot be partial application that does not have side-effects. * View pattern support (https://ghc.haskell.org/trac/ghc/wiki/ViewPatterns) * Lambda-match support (https://ghc.haskell.org/trac/ghc/wiki/LambdasVsPatternMatching) * String interpolation can be used also in patterns * SCL compiler regression test suite has been moved to a new bundle org.simantics.scl.compiler.tests * Improvements to SCL module editor syntax coloring * SCL compiler refactorings, for example all name constants are now in a dedicated class Names and CompilationContext merging old context classes * Improved byte code for comparisons * Improved code generation from string interpolation * Anonymous object support in SCL backend (not yet frontend support) * Bugfixes and new regression tests refs #6888 Change-Id: I9d4c001d0323069d3b86a83369fa3581f02ee305 --- diff --git a/bundles/org.simantics.image.ui/scl/Simantics/Image.scl b/bundles/org.simantics.image.ui/scl/Simantics/Image.scl index df9ba8360..2faaaf9e2 100644 --- a/bundles/org.simantics.image.ui/scl/Simantics/Image.scl +++ b/bundles/org.simantics.image.ui/scl/Simantics/Image.scl @@ -1,7 +1,6 @@ include "Simantics/Entity" hiding (nameOf) import "Simantics/Misc" import "Simantics/Library" -import "Simantics/DrawingTemplate" type Image = Resource diff --git a/bundles/org.simantics.modeling.ui/scl/Simantics/Testing/ActionBrowseContext.scl b/bundles/org.simantics.modeling.ui/scl/Simantics/Testing/ActionBrowseContext.scl index 471a83ef9..510603d51 100644 --- a/bundles/org.simantics.modeling.ui/scl/Simantics/Testing/ActionBrowseContext.scl +++ b/bundles/org.simantics.modeling.ui/scl/Simantics/Testing/ActionBrowseContext.scl @@ -20,9 +20,6 @@ importJava "org.simantics.modeling.ui.actions.ModeledActions" where """ ACTION_COMPARATOR :: Comparator Action -instance Eq Action where - a == b = compareWithComparator ACTION_COMPARATOR a b == 0 - instance Ord Action where compare = compareWithComparator ACTION_COMPARATOR diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphPropertyRelation.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphPropertyRelation.java index 45ac24f1c..4e450005b 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphPropertyRelation.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphPropertyRelation.java @@ -2,6 +2,8 @@ package org.simantics.modeling.scl; import org.simantics.db.Resource; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant; import org.simantics.scl.compiler.elaboration.expressions.EVariable; @@ -10,7 +12,9 @@ import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; +import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; @@ -63,7 +67,7 @@ public class GraphPropertyRelation implements SCLRelation { Expression possibleValue = new EApply( Locations.NO_LOCATION, Types.READ_GRAPH, - context.getTypingContext().getConstant(POSSIBLE_RELATED_VALUE, valueType), + context.getCompilationContext().getConstant(POSSIBLE_RELATED_VALUE, valueType), context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)), new EVariable(parameters[0]), new EExternalConstant(propertyRelation, RESOURCE) @@ -72,9 +76,8 @@ public class GraphPropertyRelation implements SCLRelation { case BB: { Variable temp = new Variable("temp", valueType); context.condition(new EApply( - context.getTypingContext().getConstant(Name.create("Prelude", "=="), valueType), + context.getCompilationContext().getConstant(Names.Builtin_equals, valueType), new Expression[] { - context.getEvidence(location, Types.pred(Types.EQ, valueType)), new EVariable(temp), new EVariable(parameters[1]) } @@ -95,7 +98,7 @@ public class GraphPropertyRelation implements SCLRelation { return new EApply( Locations.NO_LOCATION, Types.WRITE_GRAPH, - context.getTypingContext().getConstant(CLAIM_RELATED_VALUE, valueType), + context.getCompilationContext().getConstant(CLAIM_RELATED_VALUE, valueType), context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)), new EVariable(parameters[0]), new EExternalConstant(propertyRelation, RESOURCE), @@ -108,4 +111,14 @@ public class GraphPropertyRelation implements SCLRelation { return 0; } + @Override + public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce."); + } + + @Override + public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables, + Expression[] expressions) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate."); + } } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphRelation.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphRelation.java index 807d44a16..72bfa128e 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphRelation.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphRelation.java @@ -2,6 +2,7 @@ package org.simantics.modeling.scl; import org.simantics.db.Resource; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant; import org.simantics.scl.compiler.elaboration.expressions.EVariable; @@ -10,7 +11,9 @@ import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; +import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; @@ -69,7 +72,7 @@ public class GraphRelation implements SCLRelation { context.iterateList(parameters[1], new EApply( Locations.NO_LOCATION, Types.READ_GRAPH, - context.getTypingContext().getConstant(GET_OBJECTS), + context.getCompilationContext().getConstant(GET_OBJECTS), new EVariable(parameters[0]), new EExternalConstant(relation, Types.RESOURCE) )); @@ -80,7 +83,7 @@ public class GraphRelation implements SCLRelation { context.iterateList(parameters[0], new EApply( Locations.NO_LOCATION, Types.READ_GRAPH, - context.getTypingContext().getConstant(GET_OBJECTS), + context.getCompilationContext().getConstant(GET_OBJECTS), new EVariable(parameters[1]), new EExternalConstant(inverseRelation, Types.RESOURCE) )); @@ -91,7 +94,7 @@ public class GraphRelation implements SCLRelation { ? new EApply( Locations.NO_LOCATION, Types.READ_GRAPH, - context.getTypingContext().getConstant(HAS_STATEMENT), + context.getCompilationContext().getConstant(HAS_STATEMENT), new Expression[] { new EVariable(parameters[0]), new EExternalConstant(relation, Types.RESOURCE), @@ -101,7 +104,7 @@ public class GraphRelation implements SCLRelation { : new EApply( Locations.NO_LOCATION, Types.READ_GRAPH, - context.getTypingContext().getConstant(HAS_STATEMENT), + context.getCompilationContext().getConstant(HAS_STATEMENT), new Expression[] { new EVariable(parameters[1]), new EExternalConstant(inverseRelation, Types.RESOURCE), @@ -121,7 +124,7 @@ public class GraphRelation implements SCLRelation { return new EApply( Locations.NO_LOCATION, Types.WRITE_GRAPH, - context.getTypingContext().getConstant(CLAIM), + context.getCompilationContext().getConstant(CLAIM), new EVariable(parameters[0]), new EExternalConstant(relation, Types.RESOURCE), new EVariable(parameters[1]) @@ -133,4 +136,50 @@ public class GraphRelation implements SCLRelation { return 0; } + @Override + public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables, + Expression[] expressions) { + Environment env = context.context.environment; + switch(boundMask) { + case BF: + context.iterateList(location, w, variables[1], + w.apply(location, + env.getValue(GET_OBJECTS).getValue(), + expressions[0].toVal(env, w), + w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE))); + break; + case FB: + if(inverseRelation == null) + throw new IllegalArgumentException(); + context.iterateList(location, w, variables[0], + w.apply(location, + env.getValue(GET_OBJECTS).getValue(), + expressions[1].toVal(env, w), + w.getModuleWriter().getExternalConstant(inverseRelation, Types.RESOURCE))); + break; + case BB: + context.check(location, w, + inverseRelation == null || relationSelectivity <= inverseRelationSelectivity + ? w.apply(location, env.getValue(HAS_STATEMENT).getValue(), + expressions[0].toVal(env, w), + w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE), + expressions[1].toVal(env, w)) + : w.apply(location, env.getValue(HAS_STATEMENT).getValue(), + expressions[1].toVal(env, w), + w.getModuleWriter().getExternalConstant(inverseRelation, Types.RESOURCE), + expressions[0].toVal(env, w))); + break; + default: throw new IllegalArgumentException(); + } + } + + @Override + public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) { + Environment env = context.context.environment; + w.apply(location, + env.getValue(CLAIM).getValue(), + parameters[0].toVal(env, w), + w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE), + parameters[1].toVal(env, w)); + } } diff --git a/bundles/org.simantics.scl.compiler/.classpath b/bundles/org.simantics.scl.compiler/.classpath index 1c982aa6b..b862a296d 100755 --- a/bundles/org.simantics.scl.compiler/.classpath +++ b/bundles/org.simantics.scl.compiler/.classpath @@ -3,7 +3,5 @@ - - diff --git a/bundles/org.simantics.scl.compiler/.settings/org.eclipse.core.resources.prefs b/bundles/org.simantics.scl.compiler/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index ba028231b..000000000 --- a/bundles/org.simantics.scl.compiler/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding//tests/org/simantics/scl/compiler/tests/scl/InvalidEncoding.scl=ISO-8859-1 diff --git a/bundles/org.simantics.scl.compiler/ActiveTests.launch b/bundles/org.simantics.scl.compiler/ActiveTests.launch deleted file mode 100644 index 379d4db7e..000000000 --- a/bundles/org.simantics.scl.compiler/ActiveTests.launch +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/bundles/org.simantics.scl.compiler/META-INF/MANIFEST.MF b/bundles/org.simantics.scl.compiler/META-INF/MANIFEST.MF index 916e66cfd..603cdaf48 100755 --- a/bundles/org.simantics.scl.compiler/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.scl.compiler/META-INF/MANIFEST.MF @@ -2,14 +2,15 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: SCL Compiler Bundle-SymbolicName: org.simantics.scl.compiler -Bundle-Version: 0.5.0.qualifier +Bundle-Version: 0.6.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: gnu.trove3;bundle-version="3.0.0", org.simantics.scl.runtime;bundle-version="0.1.4";visibility:=reexport, org.junit;bundle-version="4.12.0";resolution:=optional, org.objectweb.asm;bundle-version="[5.0.0,6.0.0)", org.objectweb.asm.commons;bundle-version="[5.0.0,6.0.0)", - org.objectweb.asm.util;bundle-version="[5.0.0,6.0.0)" + org.objectweb.asm.util;bundle-version="[5.0.0,6.0.0)", + org.slf4j.api;bundle-version="1.7.2" Export-Package: org.cojen.classfile, org.simantics.scl.compiler.commands, org.simantics.scl.compiler.common.datatypes, @@ -19,6 +20,10 @@ Export-Package: org.cojen.classfile, org.simantics.scl.compiler.compilation, org.simantics.scl.compiler.constants, org.simantics.scl.compiler.constants.generic, + org.simantics.scl.compiler.elaboration.chr, + org.simantics.scl.compiler.elaboration.chr.plan, + org.simantics.scl.compiler.elaboration.chr.planning, + org.simantics.scl.compiler.elaboration.chr.relations;x-friends:="org.simantics.scl.compiler.tests", org.simantics.scl.compiler.elaboration.contexts, org.simantics.scl.compiler.elaboration.equation, org.simantics.scl.compiler.elaboration.errors, @@ -39,6 +44,11 @@ Export-Package: org.cojen.classfile, org.simantics.scl.compiler.environment.filter, org.simantics.scl.compiler.environment.specification, org.simantics.scl.compiler.errors, + org.simantics.scl.compiler.internal.codegen.chr;x-friends:="org.simantics.scl.compiler.tests", + org.simantics.scl.compiler.internal.codegen.references, + org.simantics.scl.compiler.internal.codegen.types;x-friends:="org.simantics.scl.compiler.tests", + org.simantics.scl.compiler.internal.codegen.utils;x-friends:="org.simantics.scl.compiler.tests", + org.simantics.scl.compiler.internal.codegen.writer, org.simantics.scl.compiler.internal.elaboration.constraints2, org.simantics.scl.compiler.internal.elaboration.subsumption, org.simantics.scl.compiler.internal.parsing, @@ -62,7 +72,6 @@ Export-Package: org.cojen.classfile, org.simantics.scl.compiler.types.exceptions, org.simantics.scl.compiler.types.kinds, org.simantics.scl.compiler.types.util -Bundle-ClassPath: tools/procyon-decompiler-0.5.29.jar, - . +Bundle-ClassPath: . Service-Component: OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml Import-Package: org.osgi.service.component.annotations diff --git a/bundles/org.simantics.scl.compiler/SCLRegressionTests.launch b/bundles/org.simantics.scl.compiler/SCLRegressionTests.launch deleted file mode 100644 index 893498e85..000000000 --- a/bundles/org.simantics.scl.compiler/SCLRegressionTests.launch +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/bundles/org.simantics.scl.compiler/build.properties b/bundles/org.simantics.scl.compiler/build.properties index 2038552d7..33fbae442 100755 --- a/bundles/org.simantics.scl.compiler/build.properties +++ b/bundles/org.simantics.scl.compiler/build.properties @@ -2,5 +2,4 @@ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ - tools/procyon-decompiler-0.5.29.jar,\ OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml diff --git a/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java b/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java index cfc5a1deb..acf2bb18d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java +++ b/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java @@ -16,7 +16,6 @@ package org.cojen.classfile; -import java.io.Serializable; import java.lang.ref.SoftReference; import java.lang.reflect.Array; import java.util.Collections; @@ -34,7 +33,7 @@ import org.cojen.util.WeakIdentityMap; * @author Brian S O'Neill */ @SuppressWarnings("rawtypes") -public abstract class TypeDesc extends Descriptor implements Serializable { +public abstract class TypeDesc extends Descriptor { /** * Type code returned from getTypeCode, which can be used with the * newarray instruction. diff --git a/bundles/org.simantics.scl.compiler/src/org/cojen/util/KeyFactory.java b/bundles/org.simantics.scl.compiler/src/org/cojen/util/KeyFactory.java deleted file mode 100644 index 1bd1b01bc..000000000 --- a/bundles/org.simantics.scl.compiler/src/org/cojen/util/KeyFactory.java +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Copyright 2004-2010 Brian S O'Neill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.cojen.util; - -import java.util.Arrays; - -/** - * KeyFactory generates keys which can be hashed or compared for any kind of - * object including arrays, arrays of arrays, and null. All hashcode - * computations, equality tests, and ordering comparsisons fully recurse into - * arrays. - * - * @author Brian S O'Neill - */ -@SuppressWarnings({ "rawtypes", "unused", "unchecked", "serial" }) -public class KeyFactory { - static final Object NULL = new Comparable() { - public int compareTo(Object obj) { - return obj == this || obj == null ? 0 : 1; - } - }; - - public static Object createKey(boolean[] obj) { - return obj == null ? NULL : new BooleanArrayKey(obj); - } - - public static Object createKey(byte[] obj) { - return obj == null ? NULL : new ByteArrayKey(obj); - } - - public static Object createKey(char[] obj) { - return obj == null ? NULL : new CharArrayKey(obj); - } - - public static Object createKey(double[] obj) { - return obj == null ? NULL : new DoubleArrayKey(obj); - } - - public static Object createKey(float[] obj) { - return obj == null ? NULL : new FloatArrayKey(obj); - } - - public static Object createKey(int[] obj) { - return obj == null ? NULL : new IntArrayKey(obj); - } - - public static Object createKey(long[] obj) { - return obj == null ? NULL : new LongArrayKey(obj); - } - - public static Object createKey(short[] obj) { - return obj == null ? NULL : new ShortArrayKey(obj); - } - - public static Object createKey(Object[] obj) { - return obj == null ? NULL : new ObjectArrayKey(obj); - } - - public static Object createKey(Object obj) { - if (obj == null) { - return NULL; - } - if (!obj.getClass().isArray()) { - return obj; - } - if (obj instanceof Object[]) { - return createKey((Object[])obj); - } else if (obj instanceof int[]) { - return createKey((int[])obj); - } else if (obj instanceof float[]) { - return createKey((float[])obj); - } else if (obj instanceof long[]) { - return createKey((long[])obj); - } else if (obj instanceof double[]) { - return createKey((double[])obj); - } else if (obj instanceof byte[]) { - return createKey((byte[])obj); - } else if (obj instanceof char[]) { - return createKey((char[])obj); - } else if (obj instanceof boolean[]) { - return createKey((boolean[])obj); - } else if (obj instanceof short[]) { - return createKey((short[])obj); - } else { - return obj; - } - } - - static int hashCode(boolean[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - hash = (hash << 1) + (a[i] ? 0 : 1); - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(byte[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - hash = (hash << 1) + a[i]; - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(char[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - hash = (hash << 1) + a[i]; - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(double[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - long v = Double.doubleToLongBits(a[i]); - hash = hash * 31 + (int)(v ^ v >>> 32); - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(float[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - hash = hash * 31 + Float.floatToIntBits(a[i]); - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(int[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - hash = (hash << 1) + a[i]; - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(long[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - long v = a[i]; - hash = hash * 31 + (int)(v ^ v >>> 32); - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(short[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - hash = (hash << 1) + a[i]; - } - return hash == 0 ? -1 : hash; - } - - static int hashCode(Object[] a) { - int hash = 0; - for (int i = a.length; --i >= 0; ) { - hash = hash * 31 + hashCode(a[i]); - } - return hash == 0 ? -1 : hash; - } - - // Compute object or array hashcode and recurses into arrays within. - static int hashCode(Object a) { - if (a == null) { - return -1; - } - if (!a.getClass().isArray()) { - return a.hashCode(); - } - if (a instanceof Object[]) { - return hashCode((Object[])a); - } else if (a instanceof int[]) { - return hashCode((int[])a); - } else if (a instanceof float[]) { - return hashCode((float[])a); - } else if (a instanceof long[]) { - return hashCode((long[])a); - } else if (a instanceof double[]) { - return hashCode((double[])a); - } else if (a instanceof byte[]) { - return hashCode((byte[])a); - } else if (a instanceof char[]) { - return hashCode((char[])a); - } else if (a instanceof boolean[]) { - return hashCode((boolean[])a); - } else if (a instanceof short[]) { - return hashCode((short[])a); - } else { - int hash = a.getClass().hashCode(); - return hash == 0 ? -1 : hash; - } - } - - // Compares object arrays and recurses into arrays within. - static boolean equals(Object[] a, Object[] b) { - if (a == b) { - return true; - } - if (a == null || b == null) { - return false; - } - int i; - if ((i = a.length) != b.length) { - return false; - } - while (--i >= 0) { - if (!equals(a[i], b[i])) { - return false; - } - } - return true; - } - - // Compares objects or arrays and recurses into arrays within. - static boolean equals(Object a, Object b) { - if (a == b) { - return true; - } - if (a == null || b == null) { - return false; - } - Class ac = a.getClass(); - if (!(ac.isArray())) { - return a.equals(b); - } - if (ac != b.getClass()) { - return false; - } - if (a instanceof Object[]) { - return equals((Object[])a, (Object[])b); - } else if (a instanceof int[]) { - return Arrays.equals((int[])a, (int[])b); - } else if (a instanceof float[]) { - return Arrays.equals((float[])a, (float[])b); - } else if (a instanceof long[]) { - return Arrays.equals((long[])a, (long[])b); - } else if (a instanceof double[]) { - return Arrays.equals((double[])a, (double[])b); - } else if (a instanceof byte[]) { - return Arrays.equals((byte[])a, (byte[])b); - } else if (a instanceof char[]) { - return Arrays.equals((char[])a, (char[])b); - } else if (a instanceof boolean[]) { - return Arrays.equals((boolean[])a, (boolean[])b); - } else if (a instanceof short[]) { - return Arrays.equals((short[])a, (short[])b); - } else { - return a.equals(b); - } - } - - static int compare(boolean[] a, boolean[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i bv ? 1 : 0); - } - return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0); - } - - static int compare(byte[] a, byte[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i bv ? 1 : 0); - } - return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0); - } - - static int compare(char[] a, char[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i bv ? 1 : 0); - } - return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0); - } - - static int compare(double[] a, double[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i b.length ? 1 : 0); - } - - static int compare(float[] a, float[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i b.length ? 1 : 0); - } - - static int compare(int[] a, int[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i bv ? 1 : 0); - } - return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0); - } - - static int compare(long[] a, long[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i bv ? 1 : 0); - } - return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0); - } - - static int compare(short[] a, short[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i bv ? 1 : 0); - } - return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0); - } - - // Compares object arrays and recurses into arrays within. - static int compare(Object[] a, Object[] b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - int length = Math.min(a.length, b.length); - for (int i=0; i b.length ? 1 : 0); - } - - // Compares objects or arrays and recurses into arrays within. - static int compare(Object a, Object b) { - if (a == b) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - Class ac = a.getClass(); - if (!(ac.isArray())) { - return ((Comparable)a).compareTo(b); - } - if (ac != b.getClass()) { - throw new ClassCastException(); - } - if (a instanceof Object[]) { - return compare((Object[])a, (Object[])b); - } else if (a instanceof int[]) { - return compare((int[])a, (int[])b); - } else if (a instanceof float[]) { - return compare((float[])a, (float[])b); - } else if (a instanceof long[]) { - return compare((long[])a, (long[])b); - } else if (a instanceof double[]) { - return compare((double[])a, (double[])b); - } else if (a instanceof byte[]) { - return compare((byte[])a, (byte[])b); - } else if (a instanceof char[]) { - return compare((char[])a, (char[])b); - } else if (a instanceof boolean[]) { - return compare((boolean[])a, (boolean[])b); - } else if (a instanceof short[]) { - return compare((short[])a, (short[])b); - } else { - throw new ClassCastException(); - } - } - - protected KeyFactory() { - } - - private static interface ArrayKey extends Comparable, java.io.Serializable { - int hashCode(); - - boolean equals(Object obj); - - int compareTo(Object obj); - } - - private static class BooleanArrayKey implements ArrayKey { - protected final boolean[] mArray; - private transient int mHash; - - BooleanArrayKey(boolean[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof BooleanArrayKey ? - Arrays.equals(mArray, ((BooleanArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((BooleanArrayKey) obj).mArray); - } - } - - private static class ByteArrayKey implements ArrayKey { - protected final byte[] mArray; - private transient int mHash; - - ByteArrayKey(byte[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof ByteArrayKey ? - Arrays.equals(mArray, ((ByteArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((ByteArrayKey) obj).mArray); - } - } - - private static class CharArrayKey implements ArrayKey { - protected final char[] mArray; - private transient int mHash; - - CharArrayKey(char[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof CharArrayKey ? - Arrays.equals(mArray, ((CharArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((CharArrayKey) obj).mArray); - } - } - - private static class DoubleArrayKey implements ArrayKey { - protected final double[] mArray; - private transient int mHash; - - DoubleArrayKey(double[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof DoubleArrayKey ? - Arrays.equals(mArray, ((DoubleArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((DoubleArrayKey) obj).mArray); - } - } - - private static class FloatArrayKey implements ArrayKey { - protected final float[] mArray; - private transient int mHash; - - FloatArrayKey(float[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof FloatArrayKey ? - Arrays.equals(mArray, ((FloatArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((FloatArrayKey) obj).mArray); - } - } - - private static class IntArrayKey implements ArrayKey { - protected final int[] mArray; - private transient int mHash; - - IntArrayKey(int[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof IntArrayKey ? - Arrays.equals(mArray, ((IntArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((IntArrayKey) obj).mArray); - } - } - - private static class LongArrayKey implements ArrayKey { - protected final long[] mArray; - private transient int mHash; - - LongArrayKey(long[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof LongArrayKey ? - Arrays.equals(mArray, ((LongArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((LongArrayKey) obj).mArray); - } - } - - private static class ShortArrayKey implements ArrayKey { - protected final short[] mArray; - private transient int mHash; - - ShortArrayKey(short[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof ShortArrayKey ? - Arrays.equals(mArray, ((ShortArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((ShortArrayKey) obj).mArray); - } - } - - private static class ObjectArrayKey implements ArrayKey { - protected final Object[] mArray; - private transient int mHash; - - ObjectArrayKey(Object[] array) { - mArray = array; - } - - public int hashCode() { - int hash = mHash; - return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash; - } - - public boolean equals(Object obj) { - return this == obj ? true : - (obj instanceof ObjectArrayKey ? - KeyFactory.equals(mArray, ((ObjectArrayKey) obj).mArray) : false); - } - - public int compareTo(Object obj) { - return compare(mArray, ((ObjectArrayKey) obj).mArray); - } - } -} diff --git a/bundles/org.simantics.scl.compiler/src/org/cojen/util/ReferencedValueHashMap.java b/bundles/org.simantics.scl.compiler/src/org/cojen/util/ReferencedValueHashMap.java index d854fafec..cf2772f40 100644 --- a/bundles/org.simantics.scl.compiler/src/org/cojen/util/ReferencedValueHashMap.java +++ b/bundles/org.simantics.scl.compiler/src/org/cojen/util/ReferencedValueHashMap.java @@ -46,6 +46,12 @@ import java.util.Set; public abstract class ReferencedValueHashMap extends AbstractMap implements Map, Cloneable { + static final Object NULL = new Comparable() { + public int compareTo(Object obj) { + return obj == this || obj == null ? 0 : 1; + } + }; + private transient Entry[] table; private transient int count; private int threshold; @@ -128,7 +134,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap public boolean containsValue(Object value) { if (value == null) { - value = KeyFactory.NULL; + value = NULL; } Entry[] tab = this.table; @@ -221,7 +227,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap } count--; } else if (e.hash == hash && key.equals(e.key)) { - return (entryValue == KeyFactory.NULL) ? null : entryValue; + return (entryValue == NULL) ? null : entryValue; } else { prev = e; } @@ -241,7 +247,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap } this.count--; } else if (e.key == null) { - return (entryValue == KeyFactory.NULL) ? null : entryValue; + return (entryValue == NULL) ? null : entryValue; } else { prev = e; } @@ -311,7 +317,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap public V put(K key, V value) { if (value == null) { - value = (V) KeyFactory.NULL; + value = (V) NULL; } // Makes sure the key is not already in the HashMap. @@ -336,7 +342,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap this.count--; } else if (e.hash == hash && key.equals(e.key)) { e.setValue(value); - return (entryValue == KeyFactory.NULL) ? null : entryValue; + return (entryValue == NULL) ? null : entryValue; } else { prev = e; } @@ -358,7 +364,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap this.count--; } else if (e.key == null) { e.setValue(value); - return (entryValue == KeyFactory.NULL) ? null : entryValue; + return (entryValue == NULL) ? null : entryValue; } else { prev = e; } @@ -415,7 +421,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap this.count--; e.setValue(null); - return (entryValue == KeyFactory.NULL) ? null : entryValue; + return (entryValue == NULL) ? null : entryValue; } else { prev = e; } @@ -443,7 +449,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap this.count--; e.setValue(null); - return (entryValue == KeyFactory.NULL) ? null : entryValue; + return (entryValue == NULL) ? null : entryValue; } else { prev = e; } @@ -693,12 +699,12 @@ public abstract class ReferencedValueHashMap extends AbstractMap public V getValue() { V value = this.value.get(); - return value == KeyFactory.NULL ? null : value; + return value == NULL ? null : value; } public V setValue(V value) { V oldValue = getValue(); - this.value = newReference(value == null ? ((V) KeyFactory.NULL) : value); + this.value = newReference(value == null ? ((V) NULL) : value); return oldValue; } @@ -713,7 +719,7 @@ public abstract class ReferencedValueHashMap extends AbstractMap Object thisValue = get(); if (thisValue == null) { return false; - } else if (thisValue == KeyFactory.NULL) { + } else if (thisValue == NULL) { thisValue = null; } return (this.key == null ? e.getKey() == null : this.key.equals(e.getKey())) && diff --git a/bundles/org.simantics.scl.compiler/src/org/cojen/util/WeakIdentityMap.java b/bundles/org.simantics.scl.compiler/src/org/cojen/util/WeakIdentityMap.java index 70030ab88..b771a982f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/cojen/util/WeakIdentityMap.java +++ b/bundles/org.simantics.scl.compiler/src/org/cojen/util/WeakIdentityMap.java @@ -208,7 +208,7 @@ public class WeakIdentityMap extends AbstractMap implements Map extends AbstractMap implements Map[] tab = this.table; @@ -329,7 +329,7 @@ public class WeakIdentityMap extends AbstractMap implements Map extends AbstractMap implements Map[] tab = this.table; @@ -637,7 +637,7 @@ public class WeakIdentityMap extends AbstractMap implements Map extends AbstractMap implements Map() { @Override - public Tuple0 apply(CommandSession commandSession, Tuple0 _) { + public Tuple0 apply(CommandSession commandSession, Tuple0 dummy) { commandSession.removeTransientImports(); commandSession.removeVariables(); commandSession.moduleRepository.getSourceRepository().checkUpdates(); @@ -212,7 +207,7 @@ public class CommandSession { }, Types.functionE(Types.UNIT, Types.PROC, Types.UNIT))); LOCAL_FUNCTIONS.put("variables", new LocalFunction(new FunctionImpl2>() { @Override - public List apply(CommandSession commandSession, Tuple0 _) { + public List apply(CommandSession commandSession, Tuple0 dummy) { ArrayList result = new ArrayList(commandSession.variableTypes.keySet()); Collections.sort(result); return result; @@ -255,7 +250,7 @@ public class CommandSession { }, Types.functionE(Types.STRING, Types.PROC, Types.UNIT))); LOCAL_FUNCTIONS.put("stopPrintingToFile", new LocalFunction(new FunctionImpl2() { @Override - public Tuple0 apply(final CommandSession commandSession, Tuple0 _) { + public Tuple0 apply(final CommandSession commandSession, Tuple0 dummy) { if(commandSession.fileOutput != null) { commandSession.fileOutput.close(); commandSession.fileOutput = null; @@ -267,13 +262,13 @@ public class CommandSession { private LocalEnvironment createLocalEnvironment() { return new AbstractLocalEnvironment() { - Variable contextVariable = new Variable("context", CONTEXT_TYPE); + Variable contextVariable = new Variable("context", Names.Expressions_Context_Context); @Override public Expression resolve(Environment environment, String localName) { Type type = variableTypes.get(localName); if(type != null) return new EApply( - new EConstant(environment.getValue(CONTEXT_GET), type), + new EConstant(environment.getValue(Names.Expressions_Context_contextGet), type), new EVariable(contextVariable), new ELiteral(new StringConstant(localName)) ); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java new file mode 100644 index 000000000..046d31f10 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java @@ -0,0 +1,80 @@ +package org.simantics.scl.compiler.common.names; + +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; + +public class Names { + + public static final Name ArrayList_add = Name.create("ArrayList", "add"); + public static final Name ArrayList_freeze = Name.create("ArrayList", "freeze"); + public static final Name ArrayList_new = Name.create("ArrayList", "new"); + public static final Name Builtin_equals = Name.create(Types.BUILTIN, "=="); + public static final Name Builtin_fail = Name.create(Types.BUILTIN, "fail"); + public static final Name Builtin_runProc = Name.create(Types.BUILTIN, "runProc"); + public static final Name Data_XML_createElement = Name.create("Data/XML", "createElement"); + public static final Type Data_XML_Element = Types.con("Data/XML", "Element"); + public static final TCon Expressions_Context_Context = Types.con("Expressions/Context", "Context"); + public static final Name Expressions_Context_contextGet = Name.create("Expressions/Context", "contextGet"); + public static final Name JavaBuiltin_unsafeCoerce = Name.create("JavaBuiltin", "unsafeCoerce"); + public static final Name MList_add = Name.create("MList", "add"); + public static final Name MList_create = Name.create("MList", "create"); + public static final Name MList_removeLast = Name.create("MList", "removeLast"); + public static final TCon MList_T = Types.con("MList", "T"); + public static final Name MSet_add = Name.create("MSet", "add"); + public static final Name MSet_contains = Name.create("MSet", "contains"); + public static final Name MSet_create = Name.create("MSet", "create"); + public static final Name MSet_iter = Name.create("MSet", "iter"); + public static final Name MSet_mapFirst = Name.create("MSet", "mapFirst"); + public static final TCon MSet_T = Types.con("MSet", "T"); + public static final Name Prelude_addList = Name.create("Prelude", "addList"); + public static final Name Prelude_any = Name.create("Prelude", "any"); + public static final Name Prelude_appendList = Name.create("Prelude", "appendList"); + public static final Name Prelude_bind = Name.create("Prelude", ">>="); + public static final Name Prelude_build = Name.create("Prelude", "build"); + public static final Name Prelude_concatMap = Name.create("Prelude", "concatMap"); + public static final Name Prelude_elem = Name.create("Prelude", "elem"); + public static final Name Prelude_elemMaybe = Name.create("Prelude", "elemMaybe"); + public static final Name Prelude_emptyList = Name.create("Prelude", "emptyList"); + public static final Name Prelude_foldl = Name.create("Prelude", "foldl"); + public static final Name Prelude_fromDouble = Name.create("Prelude", "fromDouble"); + public static final Name Prelude_fromInteger = Name.create("Prelude", "fromInteger"); + public static final Name Prelude_guardList = Name.create("Prelude", "guardList"); + public static final Name Prelude_iterList = Name.create("Prelude", "iterList"); + public static final Name Prelude_mapFirst = Name.create("Prelude", "mapFirst"); + public static final Name Prelude_mapList = Name.create("Prelude", "mapList"); + public static final Name Prelude_neg = Name.create("Prelude", "neg"); + public static final Name Prelude_not = Name.create("Prelude", "not"); + public static final Name Prelude_range = Name.create("Prelude", "range"); + public static final Name Prelude_showForPrinting = Name.create("Prelude", "showForPrinting"); + public static final Name Prelude_singletonList = Name.create("Prelude", "singletonList"); + public static final Name R_R_runR = Name.create("R/R", "runR"); + public static final Name Random_runRandom = Name.create("Random", "runRandom"); + public static final Name Serialization_ioSize = Name.create("Serialization", "ioSize"); + public static final Name Serialization_read = Name.create("Serialization", "read"); + public static final Name Serialization_write = Name.create("Serialization", "write"); + public static final Name Simantics_DB_newResource = Name.create("Simantics/DB", "newResource"); + public static final Name Simantics_DB_syncRead = Name.create("Simantics/DB", "syncRead"); + public static final Name Simantics_DB_syncWrite = Name.create("Simantics/DB", "syncWrite"); + public static final Name Simantics_Variables_child_ = Name.create("Simantics/Variables", "child_"); + public static final Name Simantics_Variables_property = Name.create("Simantics/Variables", "property"); + public static final Name Simantics_Variables_untypedPropertyValue = Name.create("Simantics/Variables", "untypedPropertyValue"); + public static final Name Unifiable_createUMap = Name.create("Unification", "createUMap"); + public static final Name Unifiable_extractWithDefault = Name.create("Unification", "extractWithDefault"); + public static final Name Unifiable_getUMapWithDefault = Name.create("Unification", "getUMapWithDefault"); + public static final Name Unifiable_putUMap = Name.create("Unification", "putUMap"); + public static final Name Unifiable_putUMapC = Name.create("Unification", "putUMapC"); + public static final Name Unifiable_uCons = Name.create("Unification", "uCons"); + public static final Name Unifiable_uId = Name.create("Unification", "uId"); + public static final TCon Unifiable_UMap = Types.con("Unification", "UMap"); + public static final TCon Unifiable_Unifiable = Types.con("Unification", "Unifiable"); + public static final Name Unifiable_uPending = Name.create("Unification", "uPending"); + public static final Name Unifiable_uTag = Name.create("Unification", "uTag"); + public static final TCon Unifiable_UTag = Types.con("Unification", "UTag"); + public static final Name Unifiable_uVar = Name.create("Unification", "uVar"); + public static final Name Vector_anyVector = Name.create("Vector", "anyVector"); + public static final Name Vector_concatMapVector = Name.create("Vector", "concatMapVector"); + public static final Name Vector_iterVector = Name.create("Vector", "iterVector"); + public static final Name Vector_mapFirstVector = Name.create("Vector", "mapFirstVector"); + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java index 470b8e9f0..52abbc6d8 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java @@ -25,7 +25,6 @@ import org.simantics.scl.compiler.elaboration.modules.SCLValueProperty; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance; import org.simantics.scl.compiler.elaboration.modules.TypeClassMethod; -import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.internal.codegen.references.IVal; import org.simantics.scl.compiler.internal.codegen.references.Val; @@ -37,7 +36,6 @@ import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder; import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils; import org.simantics.scl.compiler.internal.codegen.utils.CodeBuildingException; import org.simantics.scl.compiler.internal.codegen.utils.Constants; -import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase; import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; @@ -61,10 +59,8 @@ public class CodeGeneration { public static final int OPTIMIZATION_PHASES = 2; + CompilationContext compilationContext; ErrorLog errorLog; - Environment environment; - JavaNamingPolicy namingPolicy; - JavaTypeTranslator javaTypeTranslator; JavaReferenceValidator validator; ConcreteModule module; ModuleBuilder moduleBuilder; @@ -75,28 +71,22 @@ public class CodeGeneration { Map classes; @SuppressWarnings("unchecked") - public CodeGeneration(ErrorLog errorLog, - Environment environment, - JavaNamingPolicy namingPolicy, JavaTypeTranslator javaTypeTranslator, + public CodeGeneration(CompilationContext compilationContext, JavaReferenceValidator javaReferenceValidator, - ConcreteModule module) { - this.errorLog = errorLog; - this.environment = environment; - this.namingPolicy = namingPolicy; - this.javaTypeTranslator = javaTypeTranslator; + ConcreteModule module) { + this.compilationContext = compilationContext; + this.errorLog = compilationContext.errorLog; this.module = module; this.validator = (JavaReferenceValidator) javaReferenceValidator; - moduleBuilder = new ModuleBuilder(namingPolicy, javaTypeTranslator); + moduleBuilder = new ModuleBuilder(compilationContext.namingPolicy, compilationContext.javaTypeTranslator); } public void simplifyValues() { //System.out.println("===== Simplify values ====="); Collection values = module.getValues(); - SimplificationContext simplificationContext = - new SimplificationContext(environment, errorLog, - javaTypeTranslator, validator); + SimplificationContext simplificationContext = new SimplificationContext(compilationContext, validator); //System.out.println("-----------------------------------------------"); SCLValue[] valueArray = values.toArray(new SCLValue[values.size()]); @@ -116,7 +106,7 @@ public class CodeGeneration { } public void convertToSSA() { - ModuleWriter mw = new ModuleWriter(namingPolicy.getModuleClassName()); + ModuleWriter mw = new ModuleWriter(compilationContext.namingPolicy.getModuleClassName()); for(SCLValue value : module.getValues()) { //System.out.println(value.getName().name + " :: " + value.getType()); Expression expression = value.getExpression(); @@ -124,8 +114,6 @@ public class CodeGeneration { continue; Name name = value.getName(); - DecomposedExpression decomposed = - DecomposedExpression.decompose(expression); SCLConstant constant = new SCLConstant(name, value.getType()); value.setValue(constant); @@ -177,7 +165,7 @@ public class CodeGeneration { IVal[] parameterVals = w.getParameters(); for(int i=0;i valueCache = new THashMap(); + + public SCLValue getValue(Name name) { + if(valueCache.containsKey(name)) + return valueCache.get(name); + SCLValue value = environment.getValue(name); + if(value == null) + errorLog.log(Locations.NO_LOCATION, "Couldn't find " + name + "."); + valueCache.put(name, value); + return value; + } + + public Expression getConstant(Name name, Type ... typeParameters) { + SCLValue value = getValue(name); + if(value == null) + return new EError(Locations.NO_LOCATION); + return new EConstant(value, typeParameters); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java index 54f0bb7d8..6f82720c4 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java @@ -69,8 +69,8 @@ public class DeclarationClassification { ErrorLog errorLog; - public DeclarationClassification(ErrorLog errorLog) { - this.errorLog = errorLog; + public DeclarationClassification(CompilationContext compilationContext) { + this.errorLog = compilationContext.errorLog; } public void handle(DeclarationAst declaration) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DocumentationGeneration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DocumentationGeneration.java index b24243180..69f4b7014 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DocumentationGeneration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DocumentationGeneration.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.internal.parsing.declarations.DDocumentationAst; import org.simantics.scl.compiler.module.ConcreteModule; import org.simantics.scl.compiler.types.TCon; @@ -48,7 +48,7 @@ public class DocumentationGeneration { value.setDocumentation(doc.documentation); } for(String name : typeDocumentation.keySet()) { - TypeConstructor typeConstructor = module.getTypeConstructor(name); + TypeDescriptor typeConstructor = module.getTypeDescriptor(name); DDocumentationAst doc = typeDocumentation.get(name); if(typeConstructor != null && doc != null) typeConstructor.setDocumentation(doc.documentation); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java index d331283fd..d89c00c82 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java @@ -16,6 +16,7 @@ import org.simantics.scl.compiler.constants.generic.ConvertToListFilter; import org.simantics.scl.compiler.constants.generic.MethodRef; import org.simantics.scl.compiler.constants.generic.OutputFilter; import org.simantics.scl.compiler.constants.generic.ParameterStackItem; +import org.simantics.scl.compiler.constants.generic.Pop2OutputFilter; import org.simantics.scl.compiler.constants.generic.PopOutputFilter; import org.simantics.scl.compiler.constants.generic.StackItem; import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem; @@ -110,18 +111,17 @@ import gnu.trove.set.hash.TIntHashSet; public class Elaboration { // inputs - ErrorLog errorLog; - String moduleName; - ArrayList importsAst; - JavaReferenceValidator javaReferenceValidator; - ValueRepository valueDefinitionsAst; - RelationRepository relationDefinitionsAst; + private final CompilationContext compilationContext; + private final ErrorLog errorLog; + private final String moduleName; + private final ArrayList importsAst; + final JavaReferenceValidator javaReferenceValidator; + private final ValueRepository valueDefinitionsAst; + private final RelationRepository relationDefinitionsAst; // creates ConcreteModule module; Environment importedEnvironment; - Environment environment; - JavaNamingPolicy namingPolicy; ArrayList supplementedTypeAnnotations = new ArrayList(); JavaTypeTranslator javaTypeTranslator; @@ -130,12 +130,13 @@ public class Elaboration { THashMap branchPoints; @SuppressWarnings("unchecked") - public Elaboration(ErrorLog errorLog, CompilationTimer timer, EnvironmentFactory localEnvironmentFactory, + public Elaboration(CompilationContext compilationContext, CompilationTimer timer, EnvironmentFactory localEnvironmentFactory, String moduleName, ArrayList importsAst, JavaReferenceValidator javaReferenceValidator, ValueRepository valueDefinitionsAst, RelationRepository relationDefinitionsAst) { - this.errorLog = errorLog; + this.compilationContext = compilationContext; + this.errorLog = compilationContext.errorLog; this.moduleName = moduleName; importsAst = processRelativeImports(importsAst); this.importsAst = importsAst; @@ -144,6 +145,7 @@ public class Elaboration { this.relationDefinitionsAst = relationDefinitionsAst; module = new ConcreteModule(moduleName); + compilationContext.module = module; try { if(timer != null) timer.suspendTimer(); @@ -151,7 +153,7 @@ public class Elaboration { importsAst.toArray(new ImportDeclaration[importsAst.size()])); if(timer != null) timer.continueTimer(); - this.environment = new EnvironmentOfModule(importedEnvironment, module); + compilationContext.environment = new EnvironmentOfModule(importedEnvironment, module); } catch (ImportFailureException e) { for(ImportFailure failure : e.failures) errorLog.log(failure.location, failure.toString()); @@ -164,7 +166,7 @@ public class Elaboration { false, importAst.spec)); localEnvironmentFactory.addBuiltinDependencies(module); - namingPolicy = new JavaNamingPolicy(moduleName); + compilationContext.namingPolicy = new JavaNamingPolicy(moduleName); } private ArrayList processRelativeImports(ArrayList relativeImports) { @@ -229,7 +231,7 @@ public class Elaboration { NameExistenceChecks.checkIfTypeExists(errorLog, dataType.location, importedEnvironment, dataType.name); - if(module.addTypeConstructor(dataType.name, typeConstructor)) + if(module.addTypeDescriptor(dataType.name, typeConstructor)) errorLog.log(dataType.location, "Type "+dataType.name+" has already been defined in this module."); dataType.typeConstructor = typeConstructor; } @@ -238,7 +240,7 @@ public class Elaboration { TypeAlias alias = new TypeAlias(Types.con(moduleName, typeAlias.name), typeAlias.parameters.length); NameExistenceChecks.checkIfTypeExists(errorLog, typeAlias.location, importedEnvironment, typeAlias.name); - if(module.addTypeAlias(typeAlias.name, alias)) { + if(module.addTypeDescriptor(typeAlias.name, alias)) { errorLog.log(typeAlias.location, "Type alias "+typeAlias.name+" has already been defined in this module."); } } @@ -253,7 +255,8 @@ public class Elaboration { if(module.addEffectConstructor(effect.name, effectConstructor)) errorLog.log(effect.location, "Type "+effect.name+" has already been defined in this module."); } - javaTypeTranslator = new JavaTypeTranslator(environment); + javaTypeTranslator = new JavaTypeTranslator(compilationContext.environment); + compilationContext.javaTypeTranslator = javaTypeTranslator; } private static final int[] EMPTY_INT_ARRAY = new int[0]; @@ -309,7 +312,7 @@ public class Elaboration { if(errorLog.isEmpty()) { for(DTypeAst typeAlias : orderedTypeAliases) { - TypeAlias alias = module.getTypeAlias(typeAlias.name); + TypeAlias alias = (TypeAlias)module.getTypeDescriptor(typeAlias.name); TypeTranslationContext context = createTypeTranslationContext(); for(int i=0;i=0;--i) parameterTypes[i] = context.toType(constructor.parameters[i]); String javaName = constructors.length == 1 ? className - : namingPolicy.getConstructorClassName(name); + : compilationContext.namingPolicy.getConstructorClassName(name); String[] fieldNames = null; for(DAnnotationAst annotation : constructor.annotations) if(annotation.id.text.equals("@JavaType")) { @@ -433,7 +436,7 @@ public class Elaboration { TypeClass typeClass = new TypeClass(classAst.location, classContext, con, - namingPolicy.getTypeClassInterfaceName(con), + compilationContext.namingPolicy.getTypeClassInterfaceName(con), parameters, Fundep.mapFundeps(classAst.parameters, classAst.fundeps)); @@ -451,7 +454,7 @@ public class Elaboration { typeClass.methodNames.add(name.name); methods.put(name.name, new TypeClassMethod(typeClass, name.name, - namingPolicy.getMethodName(name.name), + compilationContext.namingPolicy.getMethodName(name.name), type, Types.getArity(type), name.location) ); @@ -484,7 +487,7 @@ public class Elaboration { } private TypeTranslationContext createTypeTranslationContext() { - return new TypeTranslationContext(errorLog, environment); + return new TypeTranslationContext(compilationContext); } public void processDerivingInstances(ArrayList derivingInstancesAst, @@ -493,7 +496,7 @@ public class Elaboration { String name = derivingInstance.name.name; TCon con; try { - con = Environments.getTypeClassName(environment, name); + con = Environments.getTypeClassName(compilationContext.environment, name); } catch (AmbiguousNameException e) { errorLog.log(derivingInstance.name.location, e.getMessage()); continue; @@ -506,7 +509,7 @@ public class Elaboration { if(deriver == null) errorLog.log(derivingInstance.location, "Doesn't know how to derive " + name + "."); else - deriver.derive(errorLog, environment, instancesAst, derivingInstance); + deriver.derive(errorLog, compilationContext.environment, instancesAst, derivingInstance); } } @@ -520,7 +523,7 @@ public class Elaboration { String name = instanceAst.name.name; TCon typeClassCon; try { - typeClassCon = Environments.getTypeClassName(environment, name); + typeClassCon = Environments.getTypeClassName(compilationContext.environment, name); } catch (AmbiguousNameException e) { errorLog.log(instanceAst.name.location, e.getMessage()); continue; @@ -529,7 +532,7 @@ public class Elaboration { errorLog.log(instanceAst.name.location, "Couldn't resolve class " + name + "."); continue; } - TypeClass typeClass = environment.getTypeClass(typeClassCon); + TypeClass typeClass = compilationContext.environment.getTypeClass(typeClassCon); pInstanceAst.typeClass = typeClass; if(instanceAst.types.length != typeClass.parameters.length) { @@ -550,7 +553,7 @@ public class Elaboration { for(int i=0;i defs, DAnnotationAst annotation) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java index a23249709..0b4d03a04 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java @@ -5,10 +5,9 @@ import java.util.Collection; import org.simantics.scl.compiler.common.names.Name; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.elaboration.rules.TransformationRule; @@ -56,11 +55,11 @@ public class EnvironmentOfModule implements Environment { return base.getEntityType(name); } @Override - public TypeConstructor getTypeConstructor(TCon type) { + public TypeDescriptor getTypeDescriptor(TCon type) { if(type.module.equals(module.getName())) - return module.getTypeConstructor(type.name); + return module.getTypeDescriptor(type.name); else - return base.getTypeConstructor(type); + return base.getTypeDescriptor(type); } @Override public EffectConstructor getEffectConstructor(TCon type) { @@ -70,13 +69,6 @@ public class EnvironmentOfModule implements Environment { return base.getEffectConstructor(type); } @Override - public TypeAlias getTypeAlias(TCon type) { - if(type.module.equals(module.getName())) - return module.getTypeAlias(type.name); - else - return base.getTypeAlias(type); - } - @Override public TypeClass getTypeClass(TCon type) { if(type.module.equals(module.getName())) return module.getTypeClass(type.name); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NameExistenceChecks.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NameExistenceChecks.java index 1f45c5f41..090f200c4 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NameExistenceChecks.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NameExistenceChecks.java @@ -1,7 +1,7 @@ package org.simantics.scl.compiler.compilation; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.environment.AmbiguousNameException; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.errors.ErrorLog; @@ -32,11 +32,11 @@ public class NameExistenceChecks { public static void checkIfTypeExists(ErrorLog errorLog, long location, Environment environment, String name) { try { - TypeConstructor value = environment.getLocalNamespace().getTypeConstructor(name); - if(value != null) + TypeDescriptor tdesc = environment.getLocalNamespace().getTypeDescriptor(name); + if(tdesc != null) errorLog.log(location, "Type " + name + " is already defined in the module " + - value.name.module + + tdesc.name.module + " that is imported to the default namespace."); } catch(AmbiguousNameException e) { errorLog.log(location, diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java index 8ade1602e..c010835e9 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java @@ -4,9 +4,9 @@ import java.util.Arrays; import java.util.function.Consumer; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.elaboration.rules.MappingRelation; @@ -59,9 +59,9 @@ public class NamespaceOfModule implements Namespace { throw new AmbiguousNameException(Arrays.asList(value.getName().module, value2.getName().module), value.getName().name); } else { - if(value != null) - return value; - return base.getValue(name); + if(value != null) + return value; + return base.getValue(name); } } @@ -83,12 +83,12 @@ public class NamespaceOfModule implements Namespace { } @Override - public TypeConstructor getTypeConstructor(String name) + public TypeDescriptor getTypeDescriptor(String name) throws AmbiguousNameException { - TypeConstructor typeConstructor = module.getTypeConstructor(name); - if(typeConstructor != null) - return typeConstructor; - return base.getTypeConstructor(name); + TypeDescriptor typeDescriptor = module.getTypeDescriptor(name); + if(typeDescriptor != null) + return typeDescriptor; + return base.getTypeDescriptor(name); } @Override @@ -107,14 +107,6 @@ public class NamespaceOfModule implements Namespace { return typeClass; return base.getTypeClass(name); } - - @Override - public TypeAlias getTypeAlias(String name) throws AmbiguousNameException { - TypeAlias typeAlias = module.getTypeAlias(name); - if(typeAlias != null) - return typeAlias; - return base.getTypeAlias(name); - } @Override public MappingRelation getMappingRelation(String name) diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java index b5bd4ef31..27583ea53 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java @@ -18,8 +18,8 @@ import org.simantics.scl.compiler.top.SCLCompilerConfiguration; import org.simantics.scl.compiler.top.StandardModuleInitializer; public class SCLCompiler { - ErrorLog errorLog = new ErrorLog(); - DeclarationClassification declarations = new DeclarationClassification(errorLog); + CompilationContext compilationContext = new CompilationContext(); + DeclarationClassification declarations = new DeclarationClassification(compilationContext); // publishable results Map classes; @@ -42,9 +42,9 @@ public class SCLCompiler { for(DeclarationAst declaration : (ArrayList)parser.parseModule()) declarations.handle(declaration); } catch(SCLSyntaxErrorException e) { - errorLog.log(e.location, e.getMessage()); + compilationContext.errorLog.log(e.location, e.getMessage()); } catch(Exception e) { - errorLog.log(e); + compilationContext.errorLog.log(e); } finally { try { sourceReader.close(); @@ -55,13 +55,17 @@ public class SCLCompiler { if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Parsing"); } + private boolean hasErrors() { + return !compilationContext.errorLog.isEmpty(); + } + public void compile( EnvironmentFactory localEnvironmentFactory, String moduleName, JavaReferenceValidator javaReferenceValidator) { try { - if(!errorLog.isEmpty()) return; - Elaboration elaboration = new Elaboration(errorLog, + if(hasErrors()) return; + Elaboration elaboration = new Elaboration(compilationContext, timer, localEnvironmentFactory, moduleName, @@ -72,24 +76,24 @@ public class SCLCompiler { if(options.computeCoverage) elaboration.addCoverageBranchPoints(); // Elaboration - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.addTypesToEnvironment( declarations.dataTypesAst, declarations.typeAliasesAst, declarations.effectsAst); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.processTypeAliases(declarations.typeAliasesAst); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.processDataTypes(declarations.dataTypesAst); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.processTypeClasses(declarations.typeClassesAst); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.processDerivingInstances(declarations.derivingInstancesAst, declarations.instancesAst); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.processInstances(declarations.instancesAst); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.processJavaMethods(declarations.javaMethodDeclarations); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; elaboration.addDataTypesToEnvironment(); elaboration.addTypeClassesToEnvironment(); elaboration.preprocessValueDefinitions(declarations.typeAnnotationsAst); @@ -101,9 +105,9 @@ public class SCLCompiler { if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Elaboration"); // Type checking - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; //new TypeChecking(errorLog, elaboration.environment, elaboration.module).typeCheck(); - new TypeChecking(errorLog, elaboration.environment, elaboration.module).typeCheck(); + new TypeChecking(compilationContext, elaboration.module).typeCheck(); if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Type checking"); @@ -125,36 +129,33 @@ public class SCLCompiler { this.declarations = null; // Code generation - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; CodeGeneration codeGeneration = new CodeGeneration( - errorLog, - elaboration.environment, - elaboration.namingPolicy, - elaboration.javaTypeTranslator, + compilationContext, elaboration.javaReferenceValidator, elaboration.module); codeGeneration.simplifyValues(); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; codeGeneration.convertToSSA(); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; codeGeneration.optimizeSSA(); if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("SSA conversion and optimization"); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; codeGeneration.generateCode(); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; codeGeneration.generateDataTypes(elaboration.dataTypes); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; codeGeneration.generateTypeClasses(); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; codeGeneration.generateTypeClassInstances(); - if(!errorLog.isEmpty()) return; + if(hasErrors()) return; classes = codeGeneration.classes; module = codeGeneration.module; moduleInitializer = StandardModuleInitializer.create( - codeGeneration.namingPolicy.getModuleClassName(), + compilationContext.namingPolicy.getModuleClassName(), codeGeneration.externalConstants); module.setClasses(classes); @@ -166,12 +167,12 @@ public class SCLCompiler { reportTiming(moduleName); } } catch(Exception e) { - errorLog.log(e); + compilationContext.errorLog.log(e); } } public ErrorLog getErrorLog() { - return errorLog; + return compilationContext.errorLog; } public Map getClasses() { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeChecking.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeChecking.java index 554a36081..667c089c3 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeChecking.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeChecking.java @@ -25,7 +25,6 @@ import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.elaboration.rules.MappingRelation; import org.simantics.scl.compiler.elaboration.rules.TransformationRule; import org.simantics.scl.compiler.environment.Environment; -import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint; import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintEnvironment; import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintSolver; @@ -45,17 +44,16 @@ import gnu.trove.set.hash.THashSet; import gnu.trove.set.hash.TIntHashSet; public class TypeChecking { - final ErrorLog errorLog; + final CompilationContext compilationContext; final Environment environment; final ConcreteModule module; ConstraintEnvironment ce; TypeCheckingScheduler scheduler; - public TypeChecking(ErrorLog errorLog, Environment environment, - ConcreteModule module) { - this.errorLog = errorLog; - this.environment = environment; + public TypeChecking(CompilationContext compilationContext, ConcreteModule module) { + this.compilationContext = compilationContext; + this.environment = compilationContext.environment; this.module = module; } @@ -100,7 +98,7 @@ public class TypeChecking { expression = expression.checkType(context, value.getType()); context.popEffectUpperBound(); for(EAmbiguous overloaded : context.overloadedExpressions) - overloaded.assertResolved(errorLog); + overloaded.assertResolved(compilationContext.errorLog); value.setExpression(expression); ArrayList constraintDemand = context.getConstraintDemand(); @@ -129,7 +127,7 @@ public class TypeChecking { for(Constraint c : red.unsolvedConstraints) if(c.constraint.isGround()) - errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">."); + compilationContext.errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">."); ArrayList fe = new ArrayList(red.unsolvedConstraints.size()); for(Constraint c : red.unsolvedConstraints) @@ -212,12 +210,12 @@ public class TypeChecking { ArrayList givenConstraints = new ArrayList(); type = Types.removePred(type, givenConstraints); - TypingContext context = new TypingContext(errorLog, environment); + TypingContext context = new TypingContext(compilationContext); context.pushEffectUpperBound(expression.location, Types.PROC); expression = expression.checkType(context, type); context.popEffectUpperBound(); for(EAmbiguous overloaded : context.overloadedExpressions) - overloaded.assertResolved(errorLog); + overloaded.assertResolved(compilationContext.errorLog); expression.getType().addPolarity(Polarity.POSITIVE); context.solveSubsumptions(expression.getLocation()); ArrayList demands = context.getConstraintDemand(); @@ -226,10 +224,10 @@ public class TypeChecking { ConstraintSolver.solve(ce, givenConstraints, demands, true); givenConstraints.clear(); for(Constraint c : red.unsolvedConstraints) { - errorLog.log(c.getDemandLocation(), + compilationContext.errorLog.log(c.getDemandLocation(), "Constraint <"+c.constraint+"> is not given and cannot be derived."); } - if(errorLog.isEmpty()) { // To prevent exceptions + if(compilationContext.errorLog.isEmpty()) { // To prevent exceptions expression = ExpressionAugmentation.augmentSolved( red.solvedConstraints, expression); @@ -239,13 +237,13 @@ public class TypeChecking { } } else { - if(errorLog.isEmpty()) // To prevent exceptions + if(compilationContext.errorLog.isEmpty()) // To prevent exceptions expression = expression.decomposeMatching(); } expression = expression.closure(vars.toArray(new TVar[vars.size()])); value.setExpression(expression); } catch(Exception e) { - errorLog.log(expression.location, e); + compilationContext.errorLog.log(expression.location, e); } } }); @@ -336,7 +334,7 @@ public class TypeChecking { public void typeCheck() { ce = new ConstraintEnvironment(environment); - scheduler = new TypeCheckingScheduler(errorLog, environment); + scheduler = new TypeCheckingScheduler(compilationContext); typeCheckValues(); typeCheckRelations(); @@ -424,7 +422,7 @@ public class TypeChecking { for(MappingRelation mappingRelation : module.getMappingRelations()) for(Type parameterType : mappingRelation.parameterTypes) if(!parameterType.isGround()) { - errorLog.log(mappingRelation.location, "Parameter types of the mapping relation are not completely determined."); + compilationContext.errorLog.log(mappingRelation.location, "Parameter types of the mapping relation are not completely determined."); break; } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java index cb6752527..e2b0109d1 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java @@ -5,8 +5,6 @@ import java.util.ArrayList; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.environment.Environment; -import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint; import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents; import org.simantics.scl.compiler.types.TPred; @@ -24,15 +22,13 @@ import gnu.trove.set.hash.TIntHashSet; * @author Hannu Niemistö */ public class TypeCheckingScheduler { - final ErrorLog errorLog; - final Environment environment; + private final CompilationContext compilationContext; - ArrayList definitions = new ArrayList(); - ArrayList postTypeCheckingRunnables = new ArrayList(); + private final ArrayList definitions = new ArrayList(); + private final ArrayList postTypeCheckingRunnables = new ArrayList(); - public TypeCheckingScheduler(ErrorLog errorLog, Environment environment) { - this.errorLog = errorLog; - this.environment = environment; + public TypeCheckingScheduler(CompilationContext compilationContext) { + this.compilationContext = compilationContext; } public void addTypeInferableDefinition(TypeInferableDefinition definition) { @@ -74,7 +70,7 @@ public class TypeCheckingScheduler { } private void typeCheck(int[] component) { - TypingContext context = new TypingContext(errorLog, environment); + TypingContext context = new TypingContext(compilationContext); context.recursiveValues = new THashSet(); for(int c : component) @@ -106,7 +102,7 @@ public class TypeCheckingScheduler { constraintMap.put(cons.constraint, cons); } Constraint cons = constraintMap.get(constraint); - errorLog.log(cons.getDemandLocation(), + compilationContext.errorLog.log(cons.getDemandLocation(), "Constrain " + constraint + " contains free variables not mentioned in the type of the value."); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/BooleanConstant.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/BooleanConstant.java index 89a902ece..194e03828 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/BooleanConstant.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/BooleanConstant.java @@ -9,6 +9,9 @@ import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder; import org.simantics.scl.compiler.types.Types; public class BooleanConstant extends Constant { + public static final BooleanConstant TRUE = new BooleanConstant(true); + public static final BooleanConstant FALSE = new BooleanConstant(false); + boolean value; public BooleanConstant(boolean value) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/ComparisonFunction.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/ComparisonFunction.java new file mode 100644 index 000000000..1e69a16c9 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/ComparisonFunction.java @@ -0,0 +1,11 @@ +package org.simantics.scl.compiler.constants; + +import org.simantics.scl.compiler.internal.codegen.continuations.Cont; +import org.simantics.scl.compiler.internal.codegen.references.Val; +import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; + +public interface ComparisonFunction { + + void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_); + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonOperation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonOperation.java index 684e7ed5d..53cbfd7aa 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonOperation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonOperation.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.constants; import org.objectweb.asm.Label; +import org.simantics.scl.compiler.internal.codegen.continuations.Cont; import org.simantics.scl.compiler.internal.codegen.references.Val; import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; @@ -9,7 +10,13 @@ import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; -public class JavaComparisonOperation extends FunctionValue { +public class JavaComparisonOperation extends FunctionValue implements ComparisonFunction { + public static final JavaComparisonOperation IEQUAL = new JavaComparisonOperation("==", Types.INTEGER); + public static final JavaComparisonOperation INOT_EQUAL = new JavaComparisonOperation("!=", Types.INTEGER); + public static final JavaComparisonOperation ILESS = new JavaComparisonOperation("<", Types.INTEGER); + public static final JavaComparisonOperation ILESS_OR_EQUAL = new JavaComparisonOperation("<=", Types.INTEGER); + public static final JavaComparisonOperation IGREATER = new JavaComparisonOperation(">", Types.INTEGER); + public static final JavaComparisonOperation IGREATER_OR_EQUAL = new JavaComparisonOperation(">=", Types.INTEGER); String op; @@ -23,10 +30,11 @@ public class JavaComparisonOperation extends FunctionValue { JavaTypeTranslator tt = mb.getJavaTypeTranslator(); Label thenBranch = mb.createLabel(); Label joinPoint = mb.createLabel(); + Type type = parameterTypes[0]; mb.push(parameters[0], type); mb.push(parameters[1], type); - mb.ifComparisonBranch(thenBranch, op, tt.toTypeDesc(parameterTypes[0])); + mb.ifComparisonBranch(thenBranch, op, tt.toTypeDesc(type)); mb.loadConstant(false); mb.branch(joinPoint); @@ -43,4 +51,15 @@ public class JavaComparisonOperation extends FunctionValue { return "(" + op + ")"; } + @Override + public void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_) { + JavaTypeTranslator tt = mb.getJavaTypeTranslator(); + Type type = parameterTypes[0]; + mb.push(parameters[0], type); + mb.push(parameters[1], type); + mb.ifComparisonBranch(mb.getLabel(then_), op, tt.toTypeDesc(type)); + mb.jump(else_); + mb.ensureExists(then_); + } + } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonToZeroOperation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonToZeroOperation.java index e5a58bb77..058faf9c3 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonToZeroOperation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaComparisonToZeroOperation.java @@ -1,13 +1,20 @@ package org.simantics.scl.compiler.constants; import org.objectweb.asm.Label; +import org.simantics.scl.compiler.internal.codegen.continuations.Cont; import org.simantics.scl.compiler.internal.codegen.references.Val; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; -public class JavaComparisonToZeroOperation extends FunctionValue { +public class JavaComparisonToZeroOperation extends FunctionValue implements ComparisonFunction { + public static final JavaComparisonToZeroOperation IEQUAL = new JavaComparisonToZeroOperation("=="); + public static final JavaComparisonToZeroOperation INOT_EQUAL = new JavaComparisonToZeroOperation("!="); + public static final JavaComparisonToZeroOperation ILESS = new JavaComparisonToZeroOperation("<"); + public static final JavaComparisonToZeroOperation ILESS_OR_EQUAL = new JavaComparisonToZeroOperation("<="); + public static final JavaComparisonToZeroOperation IGREATER = new JavaComparisonToZeroOperation(">"); + public static final JavaComparisonToZeroOperation IGREATER_OR_EQUAL = new JavaComparisonToZeroOperation(">="); String op; @@ -34,6 +41,14 @@ public class JavaComparisonToZeroOperation extends FunctionValue { return getReturnType(); } + @Override + public void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_) { + mb.push(parameters[0], Types.INTEGER); + mb.ifZeroComparisonBranch(mb.getLabel(then_), op); + mb.jump(else_); + mb.ensureExists(then_); + } + @Override public String toString() { return op; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java index a4c47ea76..ce39a6780 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java @@ -99,7 +99,7 @@ public class SCLConstant extends DelegateConstant implements Named { if(isPrivate && !hasMoreThanOneOccurences()) context.removeConstant(name); else - def = def.copy(); + def = (SSAFunction)def.copy(); if(parameters.length >= def.getArity()) { if(parameters.length != def.getArity()) @@ -363,7 +363,7 @@ public class SCLConstant extends DelegateConstant implements Named { definition.simplify(context); if(inlineArity == Integer.MAX_VALUE && definition.isSimpleEnoughForInline()) { inlineArity = definition.getArity(); - inlinableDefinition = definition.copy(); + inlinableDefinition = (SSAFunction)definition.copy(); context.markModified("mark inlineable " + name); // FIXME this will make self calling function inlinable that may crash the compiler } @@ -371,6 +371,6 @@ public class SCLConstant extends DelegateConstant implements Named { public void saveInlinableDefinition() { if(inlineArity < Integer.MAX_VALUE) - inlinableDefinition = definition.copy(); + inlinableDefinition = (SSAFunction)definition.copy(); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/StringInterpolation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/StringInterpolation.java index 55bba5604..9b3bbca92 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/StringInterpolation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/StringInterpolation.java @@ -1,8 +1,16 @@ package org.simantics.scl.compiler.constants; +import java.util.Arrays; + import org.cojen.classfile.TypeDesc; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.internal.codegen.continuations.Cont; +import org.simantics.scl.compiler.internal.codegen.references.IVal; import org.simantics.scl.compiler.internal.codegen.references.Val; import org.simantics.scl.compiler.internal.codegen.utils.Constants; +import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; @@ -22,6 +30,22 @@ public class StringInterpolation extends FunctionValue { public StringInterpolation(String[] textParts) { this(stringTypeArray(textParts.length-1), textParts); } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append('"'); + boolean first = true; + for(String textPart : textParts) { + if(first) + first = false; + else + b.append("\\(.)"); + b.append(textPart); + } + b.append('"'); + return b.toString(); + } private static Type[] stringTypeArray(int length) { Type[] result = new Type[length]; @@ -32,6 +56,37 @@ public class StringInterpolation extends FunctionValue { @Override public Type applyExact(MethodBuilder mb, Val[] parameters) { + if(textParts.length==1) { + mb.loadConstant(textParts[0]); + } + else if(textParts.length==2) { + if(parameters[0].getType() == Types.STRING) { + // Optimized special cases "asd" + x, x + "asd" + if(textParts[0].isEmpty()) { + mb.push(parameters[0], Types.STRING); + if(!textParts[1].isEmpty()) { + mb.loadConstant(textParts[1]); + mb.invokeVirtual("java/lang/String", "concat", TypeDesc.STRING, new TypeDesc[] {TypeDesc.STRING}); + } + return Types.STRING; + } + else if(textParts[1].isEmpty()) { + mb.loadConstant(textParts[0]); + mb.push(parameters[0], Types.STRING); + mb.invokeVirtual("java/lang/String", "concat", TypeDesc.STRING, new TypeDesc[] {TypeDesc.STRING}); + return Types.STRING; + } + } + } + else if(textParts.length==3) { + if(parameters[0].getType() == Types.STRING && parameters[1].getType() == Types.STRING + && textParts[0].isEmpty() && textParts[1].isEmpty() && textParts[2].isEmpty()) { + mb.push(parameters[0], Types.STRING); + mb.push(parameters[1], Types.STRING); + mb.invokeVirtual("java/lang/String", "concat", TypeDesc.STRING, new TypeDesc[] {TypeDesc.STRING}); + return Types.STRING; + } + } mb.newObject(STRING_BUILDER); mb.dup(); mb.invokeConstructor(STRING_BUILDER, Constants.EMPTY_TYPEDESC_ARRAY); @@ -60,5 +115,55 @@ public class StringInterpolation extends FunctionValue { return Types.STRING; } + + @Override + public int hashCode() { + return Arrays.hashCode(textParts) ^ Arrays.hashCode(parameterTypes); + } + @Override + public boolean equals(Object obj) { + if(this == obj) + return true; + if(obj == null || obj.getClass() != getClass()) + return false; + StringInterpolation other = (StringInterpolation)obj; + return Arrays.equals(textParts, other.textParts) && Arrays.equals(parameterTypes, other.parameterTypes); + } + + @Override + public int constructorTag() { + return textParts.length == 2 && parameterTypes[0] == Types.STRING ? 0 : -1; + } + + @Override + public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) { + if(textParts.length != 2) + throw new InternalCompilerError("String interpolation with more than one open string parts cannot be used as a pattern."); + mb.push(parameter, Types.STRING); + LocalVariable temp = mb.createLocalVariable(null, TypeDesc.STRING); + mb.storeLocal(temp); + if(!textParts[0].isEmpty()) { + mb.loadLocal(temp); + mb.loadConstant(textParts[0]); + mb.invokeVirtual("java/lang/String", "startsWith", TypeDesc.BOOLEAN, new TypeDesc[] {TypeDesc.STRING}); + mb.ifZeroComparisonBranch(failure, "=="); + } + if(!textParts[1].isEmpty()) { + mb.loadLocal(temp); + mb.loadConstant(textParts[1]); + mb.invokeVirtual("java/lang/String", "endsWith", TypeDesc.BOOLEAN, new TypeDesc[] {TypeDesc.STRING}); + mb.ifZeroComparisonBranch(failure, "=="); + } + mb.loadLocal(temp); + mb.loadConstant(textParts[0].length()); + mb.loadLocal(temp); + mb.invokeVirtual("java/lang/String", "length", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY); + mb.loadConstant(textParts[1].length()); + mb.math(Opcodes.ISUB); + mb.invokeVirtual("java/lang/String", "substring", TypeDesc.STRING, new TypeDesc[] {TypeDesc.INT, TypeDesc.INT}); + mb.storeLocal(temp); + mb.jump(success, new LocalVariableConstant(Types.STRING, temp)); + } + } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/UnsafeCoerce.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/UnsafeCoerce.java deleted file mode 100644 index 0ac69c1dc..000000000 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/UnsafeCoerce.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.simantics.scl.compiler.constants; - -import org.simantics.scl.compiler.internal.codegen.references.Val; -import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; -import org.simantics.scl.compiler.types.TVar; -import org.simantics.scl.compiler.types.Type; -import org.simantics.scl.compiler.types.Types; -import org.simantics.scl.compiler.types.kinds.Kinds; - -public class UnsafeCoerce extends FunctionValue { - private static TVar A = Types.var(Kinds.STAR); - private static TVar B = Types.var(Kinds.STAR); - public static final UnsafeCoerce INSTANCE = new UnsafeCoerce(); - - private UnsafeCoerce() { - super(new TVar[] {A, B}, Types.NO_EFFECTS, B, A); - } - - @Override - public Type applyExact(MethodBuilder mb, Val[] parameters) { - mb.pushBoxed(parameters[0]); - return getReturnType(); - } -} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/CallJava.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/CallJava.java index 300f11802..b5a3a8e4d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/CallJava.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/CallJava.java @@ -21,6 +21,11 @@ public class CallJava extends FunctionValue { Type[] parameterTypes, StackItem[] stackItems, MethodRef methodRef, OutputFilter filter) { super(typeParameters, effect, returnType, parameterTypes); + if(stackItems == null) { + stackItems = new StackItem[parameterTypes.length]; + for(int i=0;i allRefs, TIntHashSet refs) { + for(Expression parameter : parameters) + parameter.collectRefs(allRefs, refs); + } + + public void checkType(TypingContext context) { + if(relation == SpecialCHRRelation.EXECUTE) { + if(parameters.length != 1) + throw new InternalCompilerError("Wrong number of parameters for EXECUTE constraint."); + parameters[0] = parameters[0].checkIgnoredType(context); + } + else { + TVar[] typeVariables = relation.getTypeVariables(); + typeParameters = typeVariables.length == 0 ? Type.EMPTY_ARRAY : new Type[typeVariables.length]; + for(int i=0;i allVars, TIntHashSet vars) { + for(Expression parameter : parameters) + parameter.collectVars(allVars, vars); + } + + public void forVariables(VariableProcedure procedure) { + for(Expression parameter : parameters) + parameter.forVariables(procedure); + } + + public void collectFreeVariables(THashSet vars) { + for(Expression parameter : parameters) + parameter.collectFreeVariables(vars); + } + + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + this.location = loc; + for(Expression parameter : parameters) + parameter.setLocationDeep(loc); + } + } + + public void simplify(SimplificationContext context) { + for(int i=0;i effects) { + } + + public void collectEnforceEffects(THashSet effects) { + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java new file mode 100644 index 000000000..8bcd14b38 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java @@ -0,0 +1,94 @@ +package org.simantics.scl.compiler.elaboration.chr; + +import org.simantics.scl.compiler.elaboration.chr.plan.PostCommitOp; +import org.simantics.scl.compiler.elaboration.chr.plan.PreCommitOp; +import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext; +import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.contexts.TypingContext; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.Variable; +import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure; +import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor; +import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.internal.parsing.Symbol; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class CHRQuery extends Symbol { + public CHRLiteral[] literals; + + public CHRQuery(CHRLiteral[] literals) { + this.literals = literals; + } + + public void resolve(TranslationContext context) { + for(CHRLiteral literal : literals) + literal.resolve(context); + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + for(CHRLiteral literal : literals) + literal.collectRefs(allRefs, refs); + } + + public void checkType(TypingContext context) { + for(CHRLiteral literal : literals) + literal.checkType(context); + } + + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + for(CHRLiteral literal : literals) + literal.collectVars(allVars, vars); + } + + public void forVariables(VariableProcedure procedure) { + for(CHRLiteral literal : literals) + literal.forVariables(procedure); + } + + public void collectFreeVariables(THashSet vars) { + for(CHRLiteral literal : literals) + literal.collectFreeVariables(vars); + } + + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + this.location = loc; + for(CHRLiteral literal : literals) + literal.setLocationDeep(loc); + } + } + + public void createQueryPlan(QueryPlanningContext context, Expression inputFact, int activeLiteralId) { + for(int i=0;i allRefs, TIntHashSet refs) { + head.collectRefs(allRefs, refs); + body.collectRefs(allRefs, refs); + } + + public void checkType(TypingContext context) { + for(Variable variable : existentialVariables) + variable.setType(Types.metaVar(Kinds.STAR)); + head.checkType(context); + body.checkType(context); + } + + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + head.collectVars(allVars, vars); + body.collectVars(allVars, vars); + } + + public void forVariables(VariableProcedure procedure) { + head.forVariables(procedure); + body.forVariables(procedure); + } + + public void collectFreeVariables(THashSet vars) { + head.collectFreeVariables(vars); + body.collectFreeVariables(vars); + } + + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + this.location = loc; + head.setLocationDeep(loc); + body.setLocationDeep(loc); + } + } + + public void simplify(SimplificationContext context) { + head.simplify(context); + body.simplify(context); + } + + public void compile(CompilationContext compilationContext, CHRConstraint initConstraint) { + boolean hasActiveLiteral = false; + for(int i=0;i constraints = new ArrayList(); + public ArrayList rules = new ArrayList(); + + public CHRConstraint initConstraint; + public int priorityCount; + + public String storeClassName; + public TCon storeType; + public BoundVar storeVariable; + public TypeDesc storeTypeDesc; + public Constant activateProcedure; + public Constant readCurrentId; + public Constant writeCurrentId; + + // FIXME remove and change the parameter of Expression.toVal + private CompilationContext cachedContext; + + // For code generation + public BoundVar this_; + public BoundVar[] parameters; + public TypeDesc[] parameterTypeDescs; + + public CHRRuleset() { + initConstraint = new CHRConstraint(Locations.NO_LOCATION, INIT_CONSTRAINT, Type.EMPTY_ARRAY); + constraints.add(initConstraint); + } + + public void resolve(TranslationContext context) { + for(CHRConstraint constraint : constraints) + context.newCHRConstraint(constraint.name, constraint); + priorityCount = 0; + for(CHRRule rule : rules) { + rule.resolve(context); + rule.priority = priorityCount++; + } + /*for(CHRConstraint constraint : constraints) { + Variable newVariable = context.newVariable("claim" + constraint.factClassName); + }*/ + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + for(CHRRule rule : rules) + rule.collectRefs(allRefs, refs); + } + + public void checkType(TypingContext context) { + for(CHRRule rule : rules) + rule.checkType(context); + } + + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + for(CHRRule rule : rules) + rule.collectVars(allVars, vars); + } + + public void forVariables(VariableProcedure procedure) { + for(CHRRule rule : rules) + rule.forVariables(procedure); + } + + public void collectFreeVariables(THashSet vars) { + for(CHRRule rule : rules) + rule.collectFreeVariables(vars); + } + + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + this.location = loc; + for(CHRRule rule : rules) + rule.setLocationDeep(loc); + } + } + + public void compile(SimplificationContext context) { + initializeCodeGeneration(context.getCompilationContext()); + UsageAnalysis.analyzeUsage(this); + for(CHRRule rule : rules) + rule.compile(context.getCompilationContext(), initConstraint); + // remove init constraint if it is not useful + if(initConstraint.plans.isEmpty()) { + constraints.remove(0); + initConstraint = null; + } + for(CHRConstraint constraint : constraints) { + constraint.plans.sort((PrioritizedPlan a, PrioritizedPlan b) -> { + return Integer.compare(a.priority, b.priority); + }); + /*System.out.println(constraint.name); + for(PrioritizedPlan plan : constraint.plans) { + System.out.println(" priority " + plan.priority); + for(PlanOp op : plan.ops) + System.out.println(" " + op); + }*/ + } + } + + public void simplify(SimplificationContext context) { + for(CHRRule rule : rules) + rule.simplify(context); + } + + public void initializeCodeGeneration(CompilationContext context) { + cachedContext = context; // FIXME remove + + String suffix = context.namingPolicy.getFreshClosureClassNameSuffix(); + storeType = Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix); + storeClassName = context.namingPolicy.getModuleClassName() + suffix; + storeTypeDesc = TypeDesc.forClass(storeClassName); + storeVariable = new BoundVar(storeType); + for(CHRConstraint constraint : constraints) + constraint.initializeCodeGeneration(context, this); + activateProcedure = new JavaMethod(true, storeClassName, "activate", Types.PROC, Types.UNIT, storeType, Types.INTEGER); + readCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {storeType}, + null, new FieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null); + writeCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {storeType, Types.INTEGER}, + null, new SetFieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null); + if(context.module != null) // for unit testing + context.module.addTypeDescriptor(storeType.name, new StandardTypeConstructor(storeType, TVar.EMPTY_ARRAY, storeTypeDesc)); + } + + public void generateCode(CodeWriter w) { + CHRRulesetObject object = new CHRRulesetObject(storeVariable, this); + w.defineObject(object); + for(CHRConstraint constraint : constraints) { + //System.out.println(constraint); + for(PrioritizedPlan plan : constraint.plans) { + /*System.out.println(" plan " + plan.priority); + for(PlanOp planOp : plan.ops) + System.out.println(" " + planOp);*/ + PlanRealizer realizer = new PlanRealizer(cachedContext, this, storeVariable, plan.ops); + CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.BOOLEAN, new Type[] {constraint.factType}); + plan.implementation = methodWriter.getFunction(); + plan.activeFact.setVal(methodWriter.getParameters()[0]); + realizer.nextOp(methodWriter); + if(methodWriter.isUnfinished()) + methodWriter.return_(BooleanConstant.TRUE); + } + } + if(initConstraint != null) { + IVal initFact = w.apply(location, initConstraint.constructor, IntegerConstant.ZERO); + w.apply(location, initConstraint.addProcedure, storeVariable, initFact); + w.apply(location, activateProcedure, storeVariable, new IntegerConstant(Integer.MAX_VALUE)); + } + } + + public void collectEffects(THashSet effects) { + for(CHRRule rule : rules) { + for(CHRLiteral literal : rule.head.literals) + literal.collectQueryEffects(effects); + for(CHRLiteral literal : rule.head.literals) + literal.collectEnforceEffects(effects); + } + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java new file mode 100644 index 000000000..f14cb0c6b --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java @@ -0,0 +1,31 @@ +package org.simantics.scl.compiler.elaboration.chr; + +import org.simantics.scl.compiler.constants.Constant; +import org.simantics.scl.compiler.constants.JavaConstructor; +import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator; +import org.simantics.scl.compiler.internal.codegen.references.BoundVar; +import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject; +import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; +import org.simantics.scl.compiler.types.Types; + +public class CHRRulesetObject extends SSAObject { + CHRRuleset ruleset; + + public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) { + super(ruleset.storeType); + this.setTarget(target); + this.ruleset = ruleset; + } + + @Override + public Constant liftClosure(BoundVar newTarget, BoundVar[] parameters) { + ruleset.this_ = newTarget; + ruleset.parameters = parameters; + return new JavaConstructor(ruleset.storeClassName, Types.PROC, ruleset.storeType, Types.getTypes(parameters)); + } + + @Override + public void generateCode(ModuleBuilder moduleBuilder) { + CHRCodeGenerator.generateStore(moduleBuilder, ruleset); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java new file mode 100644 index 000000000..3e13e0f3f --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java @@ -0,0 +1,149 @@ +package org.simantics.scl.compiler.elaboration.chr.analysis; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.CHRRule; +import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; + +import gnu.trove.map.hash.THashMap; + +public class UsageAnalysis { + public static void analyzeUsage(CHRRuleset ruleset) { + THashMap> headConstraintMap = createHeadConstraintMap(ruleset); + calculateFirstPriorities(ruleset, headConstraintMap); + calculateLastPriorities(ruleset, headConstraintMap); + for(CHRRule rule : ruleset.rules) + determinePassiveLiterals(rule); + //printPriorities(ruleset); + } + + private static void calculateFirstPriorities(CHRRuleset ruleset, + THashMap> headConstraintMap) { + for(CHRRule rule : ruleset.rules) + rule.firstPriorityExecuted = Integer.MAX_VALUE; + for(CHRConstraint constraint : ruleset.constraints) { + constraint.firstPriorityAdded = Integer.MAX_VALUE; + constraint.firstPriorityRemoved = Integer.MAX_VALUE; + } + for(CHRRule rule : ruleset.rules) + calculateFirstPriority(headConstraintMap, rule); + } + + private static void calculateFirstPriority(THashMap> headConstraintMap, CHRRule rule) { + int result = rule.priority; + for(CHRLiteral literal : rule.head.literals) + if(literal.relation instanceof CHRConstraint) { + CHRConstraint constraint = (CHRConstraint)literal.relation; + int constraintPriority = constraint.firstPriorityAdded; + if(constraintPriority == Integer.MAX_VALUE) + return; + result = Math.max(result, constraint.firstPriorityAdded); + } + rule.firstPriorityExecuted = result; + for(CHRLiteral literal : rule.head.literals) + if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) { + CHRConstraint constraint = (CHRConstraint)literal.relation; + if(constraint.firstPriorityRemoved != Integer.MAX_VALUE) + continue; + constraint.firstPriorityRemoved = result; + } + for(CHRLiteral literal : rule.body.literals) + if(literal.relation instanceof CHRConstraint) { + CHRConstraint constraint = (CHRConstraint)literal.relation; + if(constraint.firstPriorityAdded != Integer.MAX_VALUE) + continue; + constraint.firstPriorityAdded = result; + ArrayList list = headConstraintMap.get(constraint); + if(list == null) + continue; + for(CHRRule lowerPriorityRule : list) + if(lowerPriorityRule.priority < rule.priority) + calculateFirstPriority(headConstraintMap, lowerPriorityRule); + } + } + + private static void calculateLastPriorities(CHRRuleset ruleset, + THashMap> headConstraintMap) { + for(CHRRule rule : ruleset.rules) + rule.lastPriorityExecuted = Integer.MIN_VALUE; + for(CHRConstraint constraint : ruleset.constraints) { + constraint.lastPriorityAdded = Integer.MIN_VALUE; + constraint.lastPriorityRemoved = Integer.MIN_VALUE; + } + for(int i=ruleset.rules.size()-1;i>=0;--i) { + CHRRule rule = ruleset.rules.get(i); + if(rule.lastPriorityExecuted == Integer.MIN_VALUE) + calculateLastPriority(headConstraintMap, rule, rule.priority); + } + } + + private static void calculateLastPriority(THashMap> headConstraintMap, + CHRRule rule, int priority) { + rule.lastPriorityExecuted = priority; + for(CHRLiteral literal : rule.head.literals) + if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) { + CHRConstraint constraint = (CHRConstraint)literal.relation; + if(constraint.lastPriorityRemoved != Integer.MIN_VALUE) + continue; + constraint.lastPriorityRemoved = priority; + } + for(CHRLiteral literal : rule.body.literals) + if(literal.relation instanceof CHRConstraint) { + CHRConstraint constraint = (CHRConstraint)literal.relation; + if(constraint.lastPriorityAdded != Integer.MIN_VALUE) + continue; + constraint.lastPriorityAdded = priority; + ArrayList list = headConstraintMap.get(constraint); + if(list == null) + continue; + for(CHRRule lowerPriorityRule : list) + if(lowerPriorityRule.lastPriorityExecuted == Integer.MIN_VALUE) + calculateLastPriority(headConstraintMap, lowerPriorityRule, priority); + } + } + + private static THashMap> createHeadConstraintMap(CHRRuleset ruleset) { + THashMap> map = new THashMap>(); + for(CHRRule rule : ruleset.rules) + for(CHRLiteral literal : rule.head.literals) + if(literal.relation instanceof CHRConstraint) { + ArrayList list = map.get(literal.relation); + if(list == null) { + list = new ArrayList(); + map.put((CHRConstraint)literal.relation, list); + list.add(rule); + } + else if(list.get(list.size()-1) != rule) + list.add(rule); + } + return map; + } + + private static void printPriorities(CHRRuleset ruleset) { + System.out.println("-------------------------------"); + for(CHRConstraint constraint : ruleset.constraints) { + System.out.print(" [" + constraint.firstPriorityAdded + ".." + constraint.lastPriorityAdded + "]"); + if(constraint.firstPriorityRemoved != Integer.MAX_VALUE) + System.out.print("R[" + constraint.firstPriorityRemoved + ".." + constraint.lastPriorityRemoved + "]"); + System.out.print(" "); + System.out.println(constraint); + } + for(CHRRule rule : ruleset.rules) { + System.out.print(rule.priority); + System.out.print(" [" + rule.firstPriorityExecuted + ".." + rule.lastPriorityExecuted + "] "); + System.out.println(rule); + } + } + + private static void determinePassiveLiterals(CHRRule rule) { + for(CHRLiteral literal : rule.head.literals) { + if(literal.passive) + continue; + CHRConstraint constraint = (CHRConstraint)literal.relation; + if(constraint.lastPriorityAdded < rule.priority) + literal.passive = true; + } + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/AccessFactOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/AccessFactOp.java new file mode 100644 index 000000000..befcfdd5b --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/AccessFactOp.java @@ -0,0 +1,51 @@ +package org.simantics.scl.compiler.elaboration.chr.plan; + +import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.constants.BooleanConstant; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.Variable; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; + +public class AccessFactOp extends PlanOp { + + Expression inputFact; + CHRConstraint constraint; + Variable[] variables; + boolean killAfterMatch; + + public AccessFactOp(long location, Expression inputFact, CHRConstraint constraint, Variable[] variables, + boolean killAfterMatch) { + super(location); + this.inputFact = inputFact; + this.constraint = constraint; + this.variables = variables; + this.killAfterMatch = killAfterMatch; + } + + @Override + public void toString(StringBuilder b) { + b.append("ACCESS "); + if(killAfterMatch) + b.append("- "); + b.append(constraint); + for(Variable variable : variables) + b.append(' ').append(variable); + b.append(" = ").append(inputFact); + } + + @Override + public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) { + IVal inputVal = inputFact.toVal(context.environment, w); + for(int i=0;i parameters = new ArrayList(expressions.length+1); + parameters.add(planContext.storeVar); + for(int i=0;i>i)&1)==1) + parameters.add(expressions[i].toVal(context.environment, w)); + w.jump(bodyContinuation, w.apply(location, + constraint.fetchFromIndex(context, boundMask), parameters.toArray(new IVal[parameters.size()]))); + + body.branchAwayIf(body.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), + end.getContinuation()); + IVal id = body.apply(location, constraint.accessId, fact); + for(PartnerFact partnerFact : planContext.partnerFacts) + if(partnerFact.active && !passive) { + body.branchAwayUnless(body.apply(location, JavaComparisonOperation.ILESS, id, partnerFact.id), + nextFact.getContinuation()); + } + else if(partnerFact.constraint == constraint) { + body.branchAwayIf(body.apply(location, JavaComparisonOperation.IEQUAL, id, partnerFact.id), + nextFact.getContinuation()); + } + + for(int i=0;i>i)&1)==0) + variables[i].setVal(body.apply(location, constraint.accessComponent(i), fact)); + Constant nextElement = constraint.nextElement(context, boundMask); + planContext.partnerFacts.add(new PartnerFact(false, id, constraint, fact, constraint.mayBeRemoved(), killAfterMatch, nextElement, bodyContinuation, end.getContinuation())); + planContext.nextOp(body); + if(body.isUnfinished()) + body.jump(nextFact.getContinuation()); + nextFact.jump(bodyContinuation, nextFact.apply(location, nextElement, fact)); + + w.continueAs(end); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateListOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateListOp.java new file mode 100644 index 000000000..57abca10a --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateListOp.java @@ -0,0 +1,30 @@ +package org.simantics.scl.compiler.elaboration.chr.plan; + + +import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.Variable; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; + +public class IterateListOp extends PlanOp { + public Variable variable; + public Expression list; + + public IterateListOp(long location, Variable variable, Expression list) { + super(location); + this.variable = variable; + this.list = list; + } + + @Override + public void toString(StringBuilder b) { + b.append("ITERATE ").append(variable).append(" <- ").append(list); + } + + @Override + public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) { + IVal listValue = list.toVal(context.environment, w); + planContext.iterateList(location, w, variable, listValue); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateRelationOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateRelationOp.java new file mode 100644 index 000000000..51dcb3762 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateRelationOp.java @@ -0,0 +1,42 @@ +package org.simantics.scl.compiler.elaboration.chr.plan; + +import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.Variable; +import org.simantics.scl.compiler.elaboration.relations.SCLRelation; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; + +public class IterateRelationOp extends PlanOp { + + public SCLRelation relation; + public Variable[] variables; + public Expression[] expressions; + public int boundMask; + + public IterateRelationOp(long location, SCLRelation relation, Variable[] variables, Expression[] expressions, + int boundMask) { + super(location); + this.relation = relation; + this.variables = variables; + this.expressions = expressions; + this.boundMask = boundMask; + + } + + @Override + public void toString(StringBuilder b) { + b.append("ITERATE ").append(relation); + for(int i=0;i ops; + public SSAFunction implementation; + + public PrioritizedPlan(int priority, Variable activeFact, List ops) { + this.priority = priority; + this.activeFact = activeFact; + this.ops = ops; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/PlanPriorityQueue.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/PlanPriorityQueue.java new file mode 100644 index 000000000..7eb8ae5f2 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/PlanPriorityQueue.java @@ -0,0 +1,86 @@ +package org.simantics.scl.compiler.elaboration.chr.planning; + +import java.util.Arrays; + +public class PlanPriorityQueue { + PrePlanItem[] items = new PrePlanItem[16]; + int size = 0; + + public PrePlanItem head() { + return items[0]; + } + + public void pop() { + items[0].queuePos = -1; + --size; + if (size > 0) { + PrePlanItem e = items[size]; + items[0] = e; + e.queuePos = 0; + adjustDown(e); + } + items[size] = null; + } + + public void add(PrePlanItem e) { + if (size == items.length) + items = Arrays.copyOf(items, size + size / 2); + items[size] = e; + e.queuePos = size; + ++size; + adjustUp(e); + } + + private boolean adjustUp(PrePlanItem e) { + int pos = e.queuePos; + while (pos > 0) { + int upId = (pos - 1) / 2; + PrePlanItem upE = items[upId]; + if (e.compare(upE) >= 0) + break; + items[pos] = upE; + upE.queuePos = pos; + pos = upId; + } + if (e.queuePos != pos) { + items[pos] = e; + e.queuePos = pos; + return true; + } else + return false; + } + + private void adjustDown(PrePlanItem e) { + int pos = e.queuePos; + while (true) { + int downId = pos * 2 + 1; + if (downId >= size) + break; + if (downId + 1 < size + && items[downId].compare(items[downId + 1]) > 0) + ++downId; + PrePlanItem downE = items[downId]; + if (e.compare(downE) > 0) { + items[pos] = downE; + downE.queuePos = pos; + pos = downId; + } else + break; + } + if (e.queuePos != pos) { + items[pos] = e; + e.queuePos = pos; + } + } + + public void adjust(PrePlanItem e) { + if(e.queuePos == -1) + return; + if (!adjustUp(e)) + adjustDown(e); + } + + public boolean isEmpty() { + return size == 0; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/PrePlanItem.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/PrePlanItem.java new file mode 100644 index 000000000..bb8590020 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/PrePlanItem.java @@ -0,0 +1,31 @@ +package org.simantics.scl.compiler.elaboration.chr.planning; + +public abstract class PrePlanItem { + int queuePos; + /* Primary priorities: + * 0 = check + * 1 = functional calculation + * 2 = almost completely bound relation + * 3 = completely inbound relation + */ + public double primaryPriority = Double.POSITIVE_INFINITY; + public int secondaryPriority; + public long location; + + public PrePlanItem(int secondaryPriority) { + this.secondaryPriority = secondaryPriority; + } + + public int compare(PrePlanItem other) { + if(primaryPriority < other.primaryPriority) + return -1; + if(primaryPriority > other.primaryPriority) + return 1; + return Integer.compare(secondaryPriority, other.secondaryPriority); + } + + public abstract void initializeListeners(QueryPlanningContext context); + public abstract void variableSolved(QueryPlanningContext context, int variableId); + + public abstract void generate(QueryPlanningContext context); +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/QueryPlanningContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/QueryPlanningContext.java new file mode 100644 index 000000000..c083b8fc9 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/QueryPlanningContext.java @@ -0,0 +1,240 @@ +package org.simantics.scl.compiler.elaboration.chr.planning; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.plan.AccessFactOp; +import org.simantics.scl.compiler.elaboration.chr.plan.ClaimOp; +import org.simantics.scl.compiler.elaboration.chr.plan.ExecuteOp; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp; +import org.simantics.scl.compiler.elaboration.chr.planning.items.CheckPrePlanItem; +import org.simantics.scl.compiler.elaboration.chr.planning.items.EqualsPrePlanItem; +import org.simantics.scl.compiler.elaboration.chr.planning.items.GenericPrePlanItem; +import org.simantics.scl.compiler.elaboration.chr.planning.items.MemberPrePlanItem; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; +import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation; +import org.simantics.scl.compiler.elaboration.expressions.EApplyType; +import org.simantics.scl.compiler.elaboration.expressions.EConstant; +import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant; +import org.simantics.scl.compiler.elaboration.expressions.ELiteral; +import org.simantics.scl.compiler.elaboration.expressions.EVariable; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.Variable; + +import gnu.trove.impl.Constants; +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.procedure.TIntProcedure; +import gnu.trove.set.hash.TIntHashSet; + +public class QueryPlanningContext { + CompilationContext compilationContext; + public PlanPriorityQueue priorityQueue = new PlanPriorityQueue(); + ArrayList variables; + TObjectIntHashMap variableMap; + ArrayList> itemsContainingVariable; + ArrayList planOps = new ArrayList(); + + public QueryPlanningContext(CompilationContext compilationContext, Variable[] variables) { + this.compilationContext = compilationContext; + this.variables = new ArrayList(variables.length*2); + this.variableMap = new TObjectIntHashMap(variables.length, Constants.DEFAULT_LOAD_FACTOR, -1); + itemsContainingVariable = new ArrayList>(variables.length*2); + for(Variable variable : variables) + addVariable(variable); + } + + private void addVariable(Variable variable) { + int id = variables.size(); + variables.add(variable); + variableMap.put(variable, id); + itemsContainingVariable.add(new ArrayList(2)); + } + + public void add(CHRLiteral literal, int secondaryPriority) { + if(literal.relation instanceof SpecialCHRRelation) { + switch((SpecialCHRRelation)literal.relation) { + case CHECK: + addCheck(literal.location, literal.parameters[0], secondaryPriority); + return; + case EQUALS: + addGenericEquals(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority); + return; + case MEMBER: + addMember(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority); + return; + case EXECUTE: + throw new InternalCompilerError(literal.location, "EXECUTE constraint is not allowed in query compilation."); + } + } + + addGenericConstraint(literal, secondaryPriority); + } + + private TIntHashSet getVars(Expression expression, int initialCapacity) { + TIntHashSet variableSet = new TIntHashSet(initialCapacity); + expression.collectVars(variableMap, variableSet); + return variableSet; + } + + private TIntHashSet[] getVars(Expression[] expressions, int initialCapacity) { + TIntHashSet[] variableSets = new TIntHashSet[expressions.length]; + for(int i=0;i getPlanOps() { + return planOps; + } + + private final TIntProcedure BIND_PROCEDURE = new TIntProcedure() { + @Override + public boolean execute(int variableId) { + ArrayList l = itemsContainingVariable.get(variableId); + for(PrePlanItem item : l) + item.variableSolved(QueryPlanningContext.this, variableId); + l.clear(); + return true; + } + }; + + public void bind(TIntHashSet variableSet) { + variableSet.forEach(BIND_PROCEDURE); + } + + public void addPlanOp(PlanOp planOp) { + planOps.add(planOp); + } + + public CompilationContext getCompilationContext() { + return compilationContext; + } + + public void activate(CHRLiteral literal, Expression inputFact, int secondaryPriority) { + Variable[] variables = new Variable[literal.parameters.length]; + for(int i=0;i 1) { + THashSet usedVariables = new THashSet(freeVariableCount); + for(int i=0;i indices; + + // Query plans + public ArrayList plans = new ArrayList(); + + public static class IndexInfo { + public final int indexMask; + public final String indexName; + public final Constant firstFact; + public final Constant nextFact; + + public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) { + this.indexMask = indexMask; + this.indexName = indexName; + this.firstFact = firstFact; + this.nextFact = nextFact; + } + } + + public CHRConstraint(long location, String name, Type[] parameterTypes) { + this.location = location; + this.name = name; + this.parameterTypes = parameterTypes; + } + + public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) { + JavaTypeTranslator jtt = context.javaTypeTranslator; + + this.parentRuleset = parentRuleset; + this.factClassName = parentRuleset.storeClassName + "$" + name; + TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + name); + this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY); + this.factTypeDesc = TypeDesc.forClass(factClassName); + + Type[] constructorTypes = new Type[parameterTypes.length+1]; + constructorTypes[0] = Types.INTEGER; + for(int i=0;i(Math.min(10, 1 << parameterTypes.length)); + + if(context.module != null) // for unit testing + context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc)); + } + + @Override + public TVar[] getTypeVariables() { + return TVar.EMPTY_ARRAY; + } + + @Override + public Type[] getParameterTypes() { + return parameterTypes; + } + + @Override + public String toString() { + return name; + } + + public Collection getIndices() { + return indices.valueCollection(); + } + + public boolean mayBeRemoved() { + return removeProcedure != null; + } + + private IndexInfo createIndexInfo(CompilationContext context, int indexMask) { + ArrayList keyTypeList = new ArrayList(parameterTypes.length+1); + keyTypeList.add(parentRuleset.storeType); + for(int i=0;i>i)&1)==1) + keyTypeList.add(parameterTypes[i]); + String indexName = nameOfIndex(indexMask, parameterTypes.length); + Constant accessIndex; + if(indexMask == 0) { + accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType}, + null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null); + } + else { + Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]); + accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes); + } + return new IndexInfo( + indexMask, + indexName, + accessIndex, + new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType}, + null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null) + ); + } + + public Constant accessComponent(int i) { + return accessors[i]; + } + + public IVal fetchFromIndex(CompilationContext context, int boundMask) { + IndexInfo indexInfo = indices.get(boundMask); + if(indexInfo == null) { + indexInfo = createIndexInfo(context, boundMask); + indices.put(boundMask, indexInfo); + } + return indexInfo.firstFact; + } + + public Constant nextElement(CompilationContext context, int boundMask) { + IndexInfo indexInfo = indices.get(boundMask); + if(indexInfo == null) { + indexInfo = createIndexInfo(context, boundMask); + indices.put(boundMask, indexInfo); + } + return indexInfo.nextFact; + } + + + public static String nameOfIndex(int indexMask, int length) { + char[] chars = new char[length]; + for(int i=0;i>i)&1) == 1 ? 'b' : 'f'; + return new String(chars); + } + + public void setMayBeRemoved() { + if(removeProcedure == null) { + removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType}, + new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)}, + new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}), + null); + isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType); + } + } + + public int getMinimumPriority() { + return plans.get(0).priority; + } + + public boolean isPassive() { + return plans.isEmpty(); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/ExternalCHRRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/ExternalCHRRelation.java new file mode 100644 index 000000000..1ee4726eb --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/ExternalCHRRelation.java @@ -0,0 +1,29 @@ +package org.simantics.scl.compiler.elaboration.chr.relations; + +import org.simantics.scl.compiler.elaboration.chr.CHRRelation; +import org.simantics.scl.compiler.elaboration.relations.SCLRelation; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; + +public class ExternalCHRRelation implements CHRRelation { + public final SCLRelation relation; + + public ExternalCHRRelation(SCLRelation relation) { + this.relation = relation; + } + + @Override + public TVar[] getTypeVariables() { + return relation.getTypeVariables(); + } + + @Override + public Type[] getParameterTypes() { + return relation.getParameterTypes(); + } + + @Override + public String toString() { + return relation.toString(); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/SpecialCHRRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/SpecialCHRRelation.java new file mode 100644 index 000000000..dac751480 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/SpecialCHRRelation.java @@ -0,0 +1,31 @@ +package org.simantics.scl.compiler.elaboration.chr.relations; + +import org.simantics.scl.compiler.elaboration.chr.CHRRelation; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; + +public enum SpecialCHRRelation implements CHRRelation { + EQUALS(A, A), + MEMBER(A, Types.list(A)), + CHECK(Types.BOOLEAN), + EXECUTE(Types.UNIT); + + private final TVar[] typeVariables; + private final Type[] parameterTypes; + + private SpecialCHRRelation(Type ... parameterTypes) { + this.typeVariables = Types.freeVarsArray(parameterTypes); + this.parameterTypes = parameterTypes; + } + + @Override + public TVar[] getTypeVariables() { + return typeVariables; + } + + @Override + public Type[] getParameterTypes() { + return parameterTypes; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/UnresolvedCHRRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/UnresolvedCHRRelation.java new file mode 100644 index 000000000..28944ce49 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/UnresolvedCHRRelation.java @@ -0,0 +1,26 @@ +package org.simantics.scl.compiler.elaboration.chr.relations; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.elaboration.chr.CHRRelation; +import org.simantics.scl.compiler.internal.parsing.Symbol; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; + +public class UnresolvedCHRRelation extends Symbol implements CHRRelation { + public String name; + + public UnresolvedCHRRelation(long location, String name) { + this.location = location; + this.name = name; + } + + @Override + public Type[] getParameterTypes() { + throw new InternalCompilerError("Encountered unresolved CHRRelation during type checking."); + } + + @Override + public TVar[] getTypeVariables() { + throw new InternalCompilerError("Encountered unresolved CHRRelation during type checking."); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java new file mode 100644 index 000000000..14106711d --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java @@ -0,0 +1,142 @@ +package org.simantics.scl.compiler.elaboration.chr.translation; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.CHRQuery; +import org.simantics.scl.compiler.elaboration.chr.CHRRule; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; +import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation; +import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.expressions.EApply; +import org.simantics.scl.compiler.elaboration.expressions.EBinary; +import org.simantics.scl.compiler.elaboration.expressions.EVar; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement; +import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement; +import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment; +import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator; +import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard; +import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier; +import org.simantics.scl.compiler.environment.AmbiguousNameException; +import org.simantics.scl.compiler.environment.Environments; +import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.internal.parsing.types.TypeAst; + +public class CHRTranslation { + + private static CHRLiteral convertExpression(boolean isHead, Expression expression) { + if(isHead) + return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false); + else + return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false); + } + + private static CHRLiteral convertConstraint(boolean remove, boolean negated, Expression expression) { + ArrayList parameters = new ArrayList(4); + while(expression instanceof EApply) { + EApply apply = (EApply)expression; + for(int i=apply.parameters.length-1;i>=0;--i) + parameters.add(apply.parameters[i]); + expression = apply.function; + } + EVar var = (EVar)expression; + Expression[] parametersArray = new Expression[parameters.size()]; + for(int i=0,j=parametersArray.length-1;i head = new ArrayList(statement.head.length); + for(ListQualifier qualifier : statement.head) { + CHRLiteral literal = convertListQualifier(context, true, qualifier); + if(literal != null) + head.add(literal); + } + ArrayList body = new ArrayList(statement.body.length); + for(ListQualifier qualifier : statement.body) { + CHRLiteral literal = convertListQualifier(context, false, qualifier); + if(literal != null) + body.add(literal); + } + return new CHRRule(statement.location, + new CHRQuery(head.toArray(new CHRLiteral[head.size()])), + new CHRQuery(body.toArray(new CHRLiteral[body.size()])), + null); + } + + public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) { + return new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes)); + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/SimplificationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/SimplificationContext.java index 90e93f3d0..bd01859c9 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/SimplificationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/SimplificationContext.java @@ -2,6 +2,8 @@ package org.simantics.scl.compiler.elaboration.contexts; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.constants.Constant; import org.simantics.scl.compiler.elaboration.expressions.Case; import org.simantics.scl.compiler.elaboration.expressions.EApply; @@ -31,19 +33,10 @@ import gnu.trove.list.array.TLongArrayList; import gnu.trove.map.hash.THashMap; public class SimplificationContext implements EnvironmentalContext { + CompilationContext compilationContext; Environment environment; ErrorLog errorLog; - public static final Name MAP_LIST = Name.create("Prelude", "mapList"); - public static final Name GUARD_LIST = Name.create("Prelude", "guardList"); - public static final Name CONCAT_MAP = Name.create("Prelude", "concatMap"); - public static final Name EMPTY_LIST = Name.create("Prelude", "emptyList"); - public static final Name SINGLETON_LIST = Name.create("Prelude", "singletonList"); - public static final Name APPEND_LIST = Name.create("Prelude", "appendList"); - public static final Name ADD_LIST = Name.create("Prelude", "addList"); - public static final Name FROM_INTEGER = Name.create("Prelude", "fromInteger"); - public static final Name FROM_DOUBLE = Name.create("Prelude", "fromDouble"); - THashMap constants = new THashMap(); THashMap inlinedVariables = new THashMap(); @@ -52,11 +45,11 @@ public class SimplificationContext implements EnvironmentalContext { JavaTypeTranslator javaTypeTranslator; JavaReferenceValidator validator; - public SimplificationContext(Environment environment, ErrorLog errorLog, - JavaTypeTranslator javaTypeTranslator, JavaReferenceValidator validator) { - this.environment = environment; - this.errorLog = errorLog; - this.javaTypeTranslator = javaTypeTranslator; + public SimplificationContext(CompilationContext compilationContext, JavaReferenceValidator validator) { + this.compilationContext = compilationContext; + this.environment = compilationContext.environment; + this.errorLog = compilationContext.errorLog; + this.javaTypeTranslator = compilationContext.javaTypeTranslator; this.validator = validator; } @@ -167,20 +160,20 @@ public class SimplificationContext implements EnvironmentalContext { public Expression mapList(Expression f, Expression l) { try { MultiFunction mfun = Types.matchFunction(f.getType(), 1); - return apply(getConstant(MAP_LIST, new Type[] {mfun.parameterTypes[0], mfun.returnType}), f, l); + return apply(getConstant(Names.Prelude_mapList, new Type[] {mfun.parameterTypes[0], mfun.returnType}), f, l); } catch (MatchException e) { throw new InternalCompilerError(e); } } public Expression guardList(Expression cond) { - return apply(getConstant(GUARD_LIST), cond); + return apply(getConstant(Names.Prelude_guardList), cond); } public Expression concatMap(Expression f, Expression l) { try { MultiFunction mfun = Types.matchFunction(f.getType(), 1); - return apply(getConstant(CONCAT_MAP, new Type[] { + return apply(getConstant(Names.Prelude_concatMap, new Type[] { mfun.parameterTypes[0], mfun.effect, Types.matchApply(Types.LIST, mfun.returnType)} ), f, l); @@ -190,11 +183,11 @@ public class SimplificationContext implements EnvironmentalContext { } public Expression emptyList(Type type) { - return getConstant(EMPTY_LIST, type); + return getConstant(Names.Prelude_emptyList, type); } public Expression singletonList(Expression e) { - return apply(getConstant(SINGLETON_LIST, e.getType()), e); + return apply(getConstant(Names.Prelude_singletonList, e.getType()), e); } public Expression match(Expression scrutinee, Expression pattern, Expression value) { @@ -244,7 +237,7 @@ public class SimplificationContext implements EnvironmentalContext { return new EApply( Locations.NO_LOCATION, Types.PROC, - getConstant(Name.create("Prelude", "iterList"), variable.getType(), Types.PROC, Types.tupleConstructor(0)), + getConstant(Names.Prelude_iterList, variable.getType(), Types.PROC, Types.tupleConstructor(0)), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), list @@ -257,7 +250,7 @@ public class SimplificationContext implements EnvironmentalContext { return new EApply( Locations.NO_LOCATION, Types.PROC, - getConstant(Name.create("Vector", "iterVector"), variable.getType(), Types.PROC, Types.tupleConstructor(0)), + getConstant(Names.Vector_iterVector, variable.getType(), Types.PROC, Types.tupleConstructor(0)), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), vector @@ -271,4 +264,8 @@ public class SimplificationContext implements EnvironmentalContext { result[i] = new EVariable(parameters[i]); return result; } + + public CompilationContext getCompilationContext() { + return compilationContext; + } } \ No newline at end of file diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java index b5f9f93e9..41f807592 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java @@ -4,8 +4,11 @@ import java.util.ArrayList; import java.util.Arrays; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.common.precedence.Associativity; import org.simantics.scl.compiler.common.precedence.Precedence; +import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import org.simantics.scl.compiler.elaboration.expressions.Case; import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous; import org.simantics.scl.compiler.elaboration.expressions.EConstant; @@ -24,12 +27,10 @@ import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.elaboration.query.pre.PreQuery; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.environment.AmbiguousNameException; -import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.environment.Environments; import org.simantics.scl.compiler.environment.LocalEnvironment; import org.simantics.scl.compiler.environment.Namespace; import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter; -import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst; import org.simantics.scl.compiler.top.SCLCompilerConfiguration; @@ -58,6 +59,10 @@ public class TranslationContext extends TypeTranslationContext implements Enviro TIntArrayList relationFrames = new TIntArrayList(); ArrayList relationEntries = new ArrayList(); + THashMap chrConstraints = new THashMap(); + TIntArrayList chrConstraintFrames = new TIntArrayList(); + ArrayList chrConstraintEntries = new ArrayList(); + static class Entry { String name; Variable variable; @@ -76,14 +81,23 @@ public class TranslationContext extends TypeTranslationContext implements Enviro } } - public TranslationContext(ErrorLog errorLog, - Environment environment, LocalEnvironment localEnvironment) { - super(errorLog, environment); + static class CHRConstraintEntry { + String name; + CHRConstraint constraint; + public CHRConstraintEntry(String name, CHRConstraint constraint) { + this.name = name; + this.constraint = constraint; + } + } + + public TranslationContext(CompilationContext compilationContext, LocalEnvironment localEnvironment) { + super(compilationContext); this.localEnvironment = localEnvironment; } public static boolean isConstructorName(String name) { - char firstChar = name.charAt(0); + int p = name.lastIndexOf('.'); + char firstChar = name.charAt(p<0 ? 0 : p+1); return Character.isUpperCase(firstChar); } @@ -338,6 +352,26 @@ public class TranslationContext extends TypeTranslationContext implements Enviro } } + public void pushCHRConstraintFrame() { + chrConstraintFrames.add(chrConstraintEntries.size()); + } + + public void popCHRConstraintFrame(ArrayList constraints) { + int frame = chrConstraintFrames.removeAt(chrConstraintFrames.size()-1); + int i = chrConstraintEntries.size(); + while(i > frame) { + --i; + CHRConstraintEntry entry = chrConstraintEntries.remove(i); + CHRConstraint newConstraint; + if(entry.constraint == null) + newConstraint = chrConstraints.remove(entry.name); + else + newConstraint = chrConstraints.put(entry.name, entry.constraint); + if(newConstraint.implicitlyDeclared) + constraints.add(newConstraint); + } + } + public void pushExistentialFrame() { pushFrame(); existentialFrames.add(new THashSet()); @@ -372,6 +406,11 @@ public class TranslationContext extends TypeTranslationContext implements Enviro SCLRelation oldRelation = relations.put(name, relation); relationEntries.add(new RelationEntry(name, oldRelation)); } + + public void newCHRConstraint(String name, CHRConstraint constraint) { + CHRConstraint oldConstraint = chrConstraints.put(name, constraint); + chrConstraintEntries.add(new CHRConstraintEntry(name, oldConstraint)); + } public Precedence getPrecedence(Name op) { Precedence prec = environment.getValue(op).getPrecedence(); @@ -382,55 +421,55 @@ public class TranslationContext extends TypeTranslationContext implements Enviro } private SCLValue resolveValueIn(long location, Namespace namespace, final String name) throws AmbiguousNameException { - SCLValue value = namespace.getValue(name); - if(value == null) { - StringBuilder message = new StringBuilder(); - message.append("Couldn't resolve variable ").append(name).append("."); - - final THashSet candidateNames = new THashSet(4); - namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, - new TObjectProcedure() { - @Override - public boolean execute(SCLValue value) { - if(value == null) { - new Exception().printStackTrace(); - return true; - } - String valueName = value.getName().name; - if(name.equalsIgnoreCase(valueName)) - candidateNames.add(valueName); - return true; - } - }); - if(localEnvironment != null) - localEnvironment.forNames(new TObjectProcedure() { - @Override - public boolean execute(String valueName) { - if(name.equalsIgnoreCase(valueName)) - candidateNames.add(valueName); - return true; - } - }); - - if(candidateNames.size() > 0) { - message.append(" Did you mean "); - String[] ns = candidateNames.toArray(new String[candidateNames.size()]); - Arrays.sort(ns); - for(int i=0;i 0) { - message.append(", "); - if(i == ns.length-1) - message.append("or "); - } - message.append(ns[i]); + SCLValue value = namespace.getValue(name); + if(value == null) { + StringBuilder message = new StringBuilder(); + message.append("Couldn't resolve variable ").append(name).append("."); + + final THashSet candidateNames = new THashSet(4); + namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, + new TObjectProcedure() { + @Override + public boolean execute(SCLValue value) { + if(value == null) { + new Exception().printStackTrace(); + return true; } - message.append('?'); + String valueName = value.getName().name; + if(name.equalsIgnoreCase(valueName)) + candidateNames.add(valueName); + return true; } - - errorLog.log(location, message.toString()); - return null; + }); + if(localEnvironment != null) + localEnvironment.forNames(new TObjectProcedure() { + @Override + public boolean execute(String valueName) { + if(name.equalsIgnoreCase(valueName)) + candidateNames.add(valueName); + return true; + } + }); + + if(candidateNames.size() > 0) { + message.append(" Did you mean "); + String[] ns = candidateNames.toArray(new String[candidateNames.size()]); + Arrays.sort(ns); + for(int i=0;i 0) { + message.append(", "); + if(i == ns.length-1) + message.append("or "); + } + message.append(ns[i]); + } + message.append('?'); } - return value; + + errorLog.log(location, message.toString()); + return null; + } + return value; } public Case translateCase(Expression lhs, Expression rhs) { @@ -496,11 +535,9 @@ public class TranslationContext extends TypeTranslationContext implements Enviro cases); } - private static final Name BIND = Name.create("Prelude", ">>="); - public SCLValue getBindFunction() { if(bindFunction == null) { - bindFunction = getEnvironment().getValue(BIND); + bindFunction = getEnvironment().getValue(Names.Prelude_bind); } return bindFunction; } @@ -522,6 +559,10 @@ public class TranslationContext extends TypeTranslationContext implements Enviro return null; } } + + public CHRConstraint resolveCHRConstraint(String name) { + return chrConstraints.get(name); + } @Override public SCLValue getValue(Name name) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java index b9dbb4be8..927720611 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java @@ -1,5 +1,6 @@ package org.simantics.scl.compiler.elaboration.contexts; +import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException; @@ -17,15 +18,18 @@ import gnu.trove.map.hash.THashMap; public class TypeTranslationContext { + CompilationContext compilationContext; + Environment environment; ErrorLog errorLog; THashMap typeVariables = new THashMap(); - public TypeTranslationContext(ErrorLog errorLog, Environment environment) { - this.errorLog = errorLog; - this.environment = environment; + public TypeTranslationContext(CompilationContext compilationContext) { + this.compilationContext = compilationContext; + this.errorLog = compilationContext.errorLog; + this.environment = compilationContext.environment; } /** @@ -106,7 +110,7 @@ public class TypeTranslationContext { } public Kind getKind(TCon con) { - return environment.getTypeConstructor(con).kind; + return environment.getTypeDescriptor(con).getKind(); } /** diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypingContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypingContext.java index 850f077db..ac004eab6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypingContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypingContext.java @@ -3,12 +3,10 @@ package org.simantics.scl.compiler.elaboration.contexts; import java.util.ArrayList; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.constants.NoRepConstant; import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous; import org.simantics.scl.compiler.elaboration.expressions.EApply; -import org.simantics.scl.compiler.elaboration.expressions.EConstant; -import org.simantics.scl.compiler.elaboration.expressions.EError; import org.simantics.scl.compiler.elaboration.expressions.ELiteral; import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder; import org.simantics.scl.compiler.elaboration.expressions.EVariable; @@ -17,7 +15,6 @@ import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.errors.ErrorLog; -import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint; import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintEnvironment; import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintSolver; @@ -42,9 +39,9 @@ import org.simantics.scl.compiler.types.util.TypeUnparsingContext; import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; -public class TypingContext implements EnvironmentalContext { +public class TypingContext { - private ErrorLog errorLog; + private CompilationContext compilationContext; // Subsumption private ArrayList effectSubsumptions = new ArrayList(); @@ -71,11 +68,10 @@ public class TypingContext implements EnvironmentalContext { //TypeUnparsingContext tuc = new TypeUnparsingContext(); Environment environment; - THashMap constants = new THashMap(); - public TypingContext(ErrorLog errorLog, Environment environment) { - this.errorLog = errorLog; - this.environment = environment; + public TypingContext(CompilationContext compilationContext) { + this.compilationContext = compilationContext; + this.environment = compilationContext.environment; } /** @@ -94,7 +90,7 @@ public class TypingContext implements EnvironmentalContext { try { Types.unify(a, Types.NO_EFFECTS); } catch(UnificationException e) { - errorLog.log(loc, "No side-effects allowed here."); + compilationContext.errorLog.log(loc, "No side-effects allowed here."); return; } } @@ -336,7 +332,7 @@ public class TypingContext implements EnvironmentalContext { try { subsume(sub.loc, a, b); } catch (UnificationException e) { - errorLog.log(sub.loc, "Type " + a + " is not a subtype of " + b + "."); + compilationContext.errorLog.log(sub.loc, "Type " + a + " is not a subtype of " + b + "."); } nontrivialSubs = true; } @@ -361,7 +357,7 @@ public class TypingContext implements EnvironmentalContext { try { Types.unify(sub.a, sub.b); } catch (UnificationException e) { - errorLog.log(sub.loc, "Unification of types failed."); + compilationContext.errorLog.log(sub.loc, "Unification of types failed."); return false; } @@ -386,7 +382,7 @@ public class TypingContext implements EnvironmentalContext { if(type instanceof TMetaVar) return ((TMetaVar)type).getKind() == Kinds.EFFECT; else if(type instanceof TCon) - return environment.getTypeConstructor((TCon)type).kind == Kinds.EFFECT; + return environment.getTypeDescriptor((TCon)type).getKind() == Kinds.EFFECT; else if(type instanceof TVar) return ((TVar)type).getKind() == Kinds.EFFECT; else if(type instanceof TUnion) @@ -398,7 +394,7 @@ public class TypingContext implements EnvironmentalContext { public void solveSubsumptions(long globalLoc) { if(expandSubsumptions()) - new SubSolver(errorLog, effectSubsumptions, potentialSingletonEffects, globalLoc).solve(); + new SubSolver(compilationContext.errorLog, effectSubsumptions, potentialSingletonEffects, globalLoc).solve(); } public void declareEffect(long loc, Type effect) { @@ -415,7 +411,7 @@ public class TypingContext implements EnvironmentalContext { } public ErrorLog getErrorLog() { - return errorLog; + return compilationContext.errorLog; } public boolean isInPattern() { @@ -470,7 +466,7 @@ public class TypingContext implements EnvironmentalContext { public void typeError(long loc, Type requiredType, Type givenType) { TypeUnparsingContext tuc = new TypeUnparsingContext(); - errorLog.log(loc, "Expected <" + requiredType.toString(tuc) + "> got <" + givenType.toString(tuc) + ">."); + compilationContext.errorLog.log(loc, "Expected <" + requiredType.toString(tuc) + "> got <" + givenType.toString(tuc) + ">."); } public Expression solveConstraints(Environment environment, Expression expression) { @@ -486,33 +482,20 @@ public class TypingContext implements EnvironmentalContext { expression); for(Constraint c : red.unsolvedConstraints) - errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">."); + compilationContext.errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">."); } else expression = expression.decomposeMatching(); return expression; } - - public SCLValue getValue(Name name) { - if(constants.containsKey(name)) - return constants.get(name); - SCLValue value = environment.getValue(name); - if(value == null) - errorLog.log(Locations.NO_LOCATION, "Couldn't find " + name + "."); - constants.put(name, value); - return value; - } - - public Expression getConstant(Name name, Type ... typeParameters) { - SCLValue value = getValue(name); - if(value == null) - return new EError(Locations.NO_LOCATION); - return new EConstant(value, typeParameters); - } public Environment getEnvironment() { - return environment; + return compilationContext.environment; + } + + public CompilationContext getCompilationContext() { + return compilationContext; } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EApply.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EApply.java index 8df327362..1de0944eb 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EApply.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EApply.java @@ -37,8 +37,8 @@ import gnu.trove.set.hash.THashSet; import gnu.trove.set.hash.TIntHashSet; public class EApply extends Expression { - Expression function; - Expression[] parameters; + public Expression function; + public Expression[] parameters; Type effect = Types.NO_EFFECTS; public EApply(Expression function, Expression ... parameters) { @@ -397,4 +397,19 @@ public class EApply extends Expression { public Expression accept(ExpressionTransformer transformer) { return transformer.transform(this); } + + @Override + public boolean equalsExpression(Expression expression) { + if(expression.getClass() != getClass()) + return false; + EApply other = (EApply)expression; + if(parameters.length != other.parameters.length) + return false; + if(!function.equalsExpression(other.function)) + return false; + for(int i=0;i vars) { - vars.add(var); - pattern.collectFreeVariables(vars); + throw new InternalCompilerError(location, "Cannot collect free variables for a pattern."); + } + + @Override + public void removeFreeVariables(THashSet vars) { + vars.remove(var); + pattern.removeFreeVariables(vars); } @Override diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java index e74dde7f6..58274a7a0 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java @@ -3,7 +3,7 @@ package org.simantics.scl.compiler.elaboration.expressions; import java.util.ArrayList; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.common.precedence.Associativity; import org.simantics.scl.compiler.common.precedence.Precedence; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; @@ -46,8 +46,6 @@ public class EBinary extends ASTExpression { public Expression resolve(TranslationContext context) { return parseOperators(context).resolve(context); } - - private static final Name NEG = Name.create("Prelude", "neg"); public Expression parseOperators(TranslationContext context) { ArrayList output = new ArrayList(); @@ -87,7 +85,7 @@ public class EBinary extends ASTExpression { } if(negation != null && ops.isEmpty()) { if(opPrec.level <= NEGATION_LEVEL) { - SCLValue neg = context.getEnvironment().getValue(NEG); + SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg); if(neg == null) { context.getErrorLog().log(location, "Couldn't resolve variable neg."); @@ -112,7 +110,7 @@ public class EBinary extends ASTExpression { output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r)); } if(negation != null) { - SCLValue neg = context.getEnvironment().getValue(NEG); + SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg); if(neg == null) { context.getErrorLog().log(location, "Couldn't resolve variable neg."); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java index ff1312540..fb5c2bdfa 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java @@ -5,11 +5,16 @@ import java.util.LinkedList; import java.util.List; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; +import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement; +import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement; import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement; import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement; import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement; import org.simantics.scl.compiler.elaboration.expressions.block.Statement; +import org.simantics.scl.compiler.elaboration.expressions.block.StatementGroup; import org.simantics.scl.compiler.errors.Locations; public class EBlock extends ASTExpression { @@ -34,10 +39,8 @@ public class EBlock extends ASTExpression { @Override public Expression resolve(TranslationContext context) { - if(statements.isEmpty()) { - context.getErrorLog().log(location, "Block must contain at least one statement."); - return new EError(location); - } + if(statements.isEmpty()) + throw new InternalCompilerError(); int i = statements.size()-1; Statement last = statements.get(i); if(!(last instanceof GuardStatement)) { @@ -48,21 +51,25 @@ public class EBlock extends ASTExpression { Expression in = ((GuardStatement)last).value; while(--i >= 0) { Statement cur = statements.get(i); - if(cur instanceof RuleStatement) { - int endId = i+1; - while(i>0 && statements.get(i-1) instanceof RuleStatement) - --i; - in = extractRules(i, endId, in); - } - else if(cur instanceof LetStatement && ((LetStatement)cur).pattern.isFunctionPattern()) { + StatementGroup group = cur.getStatementGroup(); + if(group == null) + in = cur.toExpression(context, monadic, in); + else { int endId = i+1; - while(i>0 && (cur = statements.get(i-1)) instanceof LetStatement && - ((LetStatement)cur).pattern.isFunctionPattern()) + while(i>0 && statements.get(i-1).getStatementGroup() == group) --i; - in = extractLet(i, endId, in); + switch(group) { + case LetFunction: + in = extractLet(i, endId, in); + break; + case Rule: + in = extractRules(i, endId, in); + break; + case CHR: + in = extractCHRRules(context, i, endId, in); + break; + } } - else - in = cur.toExpression(context, monadic, in); } return in.resolve(context); } @@ -70,6 +77,21 @@ public class EBlock extends ASTExpression { private Expression extractRules(int begin, int end, Expression in) { return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in); } + + private Expression extractCHRRules(TranslationContext context, int begin, int end, Expression in) { + CHRRuleset ruleset = new CHRRuleset(); + ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location); + for(int i=begin;i allRefs, TIntHashSet refs) { + ruleset.collectRefs(allRefs, refs); + in.collectRefs(allRefs, refs); + } + @Override + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + ruleset.collectVars(allVars, vars); + in.collectVars(allVars, vars); + } + @Override + public void forVariables(VariableProcedure procedure) { + ruleset.forVariables(procedure); + in.forVariables(procedure); + } + @Override + protected void updateType() throws MatchException { + setType(in.getType()); + } + @Override + public IVal toVal(Environment env, CodeWriter w) { + ruleset.generateCode(w); + return in.toVal(env, w); + } + @Override + public void collectFreeVariables(THashSet vars) { + ruleset.collectFreeVariables(vars); + in.collectFreeVariables(vars); + } + @Override + public Expression resolve(TranslationContext context) { + context.pushFrame(); + context.pushCHRConstraintFrame(); + ruleset.resolve(context); + in = in.resolve(context); + context.popCHRConstraintFrame(ruleset.constraints); + context.popFrame(); + return this; + } + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + this.location = loc; + ruleset.setLocationDeep(loc); + in.setLocationDeep(loc); + } + } + @Override + public Expression decorate(ExpressionDecorator decorator) { + in = in.decorate(decorator); + return this; + } + @Override + public void collectEffects(THashSet effects) { + ruleset.collectEffects(effects); + in.collectEffects(effects); + } + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public Expression inferType(TypingContext context) { + ruleset.checkType(context); + in = in.inferType(context); + return this; + } + + @Override + public Expression simplify(SimplificationContext context) { + ruleset.simplify(context); + ruleset.compile(context); + in = in.simplify(context); + return this; + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public IExpression toIExpression(ExpressionInterpretationContext context) { + throw new UnsupportedOperationException(); + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EConstant.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EConstant.java index 590cbbd96..068c6c874 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EConstant.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EConstant.java @@ -232,7 +232,7 @@ public class EConstant extends Expression { return this; } else - return applyPUnit(context); + return applyPUnit(context.getCompilationContext()); } @Override @@ -283,4 +283,11 @@ public class EConstant extends Expression { return transformer.transform(this); } + @Override + public boolean equalsExpression(Expression expression) { + if(expression.getClass() != getClass()) + return false; + EConstant other = (EConstant)expression; + return value == other.value && Types.equals(typeParameters, other.typeParameters); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java index b49999c06..faadca33e 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java @@ -1,6 +1,6 @@ package org.simantics.scl.compiler.elaboration.expressions; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; @@ -80,10 +80,6 @@ public class EFieldAccess extends SimplifiableExpression { accessor.collectFreeVariables(vars); } - private static final Name CHILD = Name.create("Simantics/Variables", "child_"); - private static final Name PROPERTY = Name.create("Simantics/Variables", "property"); - private static final Name PROPERTY_VALUE = Name.create("Simantics/Variables", "untypedPropertyValue"); - @Override public Expression simplify(SimplificationContext context) { // Simplify subexpressions @@ -99,7 +95,7 @@ public class EFieldAccess extends SimplifiableExpression { result = new EApply( getLocation(), Types.READ_GRAPH, - context.getConstant(CHILD), + context.getConstant(Names.Simantics_Variables_child_), result, accessor.asExpression() ); @@ -107,7 +103,7 @@ public class EFieldAccess extends SimplifiableExpression { result = new EApply( getLocation(), Types.READ_GRAPH, - context.getConstant(PROPERTY), + context.getConstant(Names.Simantics_Variables_property), result, accessor.asExpression() ); @@ -117,7 +113,7 @@ public class EFieldAccess extends SimplifiableExpression { result = new EApply( getLocation(), Types.READ_GRAPH, - context.getConstant(PROPERTY_VALUE, getType()), + context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()), result, accessor.asExpression() ); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java index e1ccd53dd..b714d7678 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java @@ -9,12 +9,14 @@ import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.codegen.references.IVal; import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; +import org.simantics.scl.compiler.internal.interpreted.IConstant; import org.simantics.scl.compiler.internal.interpreted.IExpression; import org.simantics.scl.compiler.internal.interpreted.IIf; import org.simantics.scl.compiler.top.ExpressionInterpretationContext; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; +import org.simantics.scl.runtime.tuple.Tuple0; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.THashSet; @@ -23,7 +25,7 @@ import gnu.trove.set.hash.TIntHashSet; public class EIf extends Expression { public Expression condition; public Expression then_; - public Expression else_; + public Expression else_; // may be null public EIf(Expression condition, Expression then_, Expression else_) { this.condition = condition; @@ -41,7 +43,8 @@ public class EIf extends Expression { public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { condition.collectRefs(allRefs, refs); then_.collectRefs(allRefs, refs); - else_.collectRefs(allRefs, refs); + if(else_ != null) + else_.collectRefs(allRefs, refs); } @Override @@ -49,7 +52,8 @@ public class EIf extends Expression { TIntHashSet vars) { condition.collectVars(allVars, vars); then_.collectVars(allVars, vars); - else_.collectVars(allVars, vars); + if(else_ != null) + else_.collectVars(allVars, vars); } @Override @@ -60,20 +64,20 @@ public class EIf extends Expression { @Override public IVal toVal(Environment env, CodeWriter w) { IVal conditionVal = condition.toVal(env, w); - - CodeWriter thenBlock = w.createBlock(); - CodeWriter elseBlock = w.createBlock(); - CodeWriter joinPoint = w.createBlock(getType()); - - w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation()); - + CodeWriter thenBlock = w.createBlock(); + if(else_ != null) { + CodeWriter elseBlock = w.createBlock(); + w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation()); + + IVal elseVal = else_.toVal(env, elseBlock); + elseBlock.jump(joinPoint.getContinuation(), elseVal); + } + else { + w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation()); + } IVal thenVal = then_.toVal(env, thenBlock); thenBlock.jump(joinPoint.getContinuation(), thenVal); - - IVal elseVal = else_.toVal(env, elseBlock); - elseBlock.jump(joinPoint.getContinuation(), elseVal); - w.continueAs(joinPoint); return w.getParameters()[0]; @@ -83,14 +87,16 @@ public class EIf extends Expression { public void collectFreeVariables(THashSet vars) { condition.collectFreeVariables(vars); then_.collectFreeVariables(vars); - else_.collectFreeVariables(vars); + if(else_ != null) + else_.collectFreeVariables(vars); } @Override public Expression simplify(SimplificationContext context) { condition = condition.simplify(context); then_ = then_.simplify(context); - else_ = else_.simplify(context); + if(else_ != null) + else_ = else_.simplify(context); return this; } @@ -98,7 +104,8 @@ public class EIf extends Expression { public Expression resolve(TranslationContext context) { condition = condition.resolve(context); then_ = then_.resolve(context); - else_ = else_.resolve(context); + if(else_ != null) + else_ = else_.resolve(context); return this; } @@ -106,14 +113,17 @@ public class EIf extends Expression { public Expression replace(ReplaceContext context) { return new EIf(condition.replace(context), then_.replace(context), - else_.replace(context)); + else_ == null ? null : else_.replace(context)); } @Override public Expression checkBasicType(TypingContext context, Type requiredType) { condition = condition.checkType(context, Types.BOOLEAN); then_ = then_.checkType(context, requiredType); - else_ = else_.checkType(context, requiredType); + if(else_ != null) + else_ = else_.checkType(context, requiredType); + else + context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used."); return this; } @@ -121,7 +131,8 @@ public class EIf extends Expression { public Expression checkIgnoredType(TypingContext context) { condition = condition.checkType(context, Types.BOOLEAN); then_ = then_.checkIgnoredType(context); - else_ = else_.checkIgnoredType(context); + if(else_ != null) + else_ = else_.checkIgnoredType(context); return this; } @@ -129,20 +140,22 @@ public class EIf extends Expression { public Expression decorate(ExpressionDecorator decorator) { condition = condition.decorate(decorator); then_ = then_.decorate(decorator); - else_ = else_.decorate(decorator); + if(else_ != null) + else_ = else_.decorate(decorator); return decorator.decorate(this); } @Override public boolean isEffectful() { - return condition.isEffectful() || then_.isEffectful() || else_.isEffectful(); + return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful()); } @Override public void collectEffects(THashSet effects) { condition.collectEffects(effects); then_.collectEffects(effects); - else_.collectEffects(effects); + if(else_ != null) + else_.collectEffects(effects); } @Override @@ -151,7 +164,8 @@ public class EIf extends Expression { location = loc; condition.setLocationDeep(loc); then_.setLocationDeep(loc); - else_.setLocationDeep(loc); + if(else_ != null) + else_.setLocationDeep(loc); } } @@ -162,26 +176,16 @@ public class EIf extends Expression { @Override public IExpression toIExpression(ExpressionInterpretationContext target) { - return new IIf(condition.toIExpression(target), then_.toIExpression(target), else_.toIExpression(target)); - } - - public Expression getCondition() { - return condition; - } - - public Expression getThen() { - return then_; - } - - public Expression getElse() { - return else_; + return new IIf(condition.toIExpression(target), then_.toIExpression(target), + else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE)); } @Override public void forVariables(VariableProcedure procedure) { condition.forVariables(procedure); then_.forVariables(procedure); - else_.forVariables(procedure); + if(else_ != null) + else_.forVariables(procedure); } @Override public Expression accept(ExpressionTransformer transformer) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIntegerLiteral.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIntegerLiteral.java index 101e00b84..0834c4905 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIntegerLiteral.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIntegerLiteral.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.constants.DoubleConstant; import org.simantics.scl.compiler.constants.FloatConstant; import org.simantics.scl.compiler.constants.IntegerConstant; @@ -90,7 +91,7 @@ public class EIntegerLiteral extends SimplifiableExpression { if(primitive != null) return primitive; return context.apply( - context.getConstant(SimplificationContext.FROM_INTEGER, getType()), + context.getConstant(Names.Prelude_fromInteger, getType()), constraint.simplify(context), context.literal(new IntegerConstant(Integer.parseInt(value))) ); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELiteral.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELiteral.java index 15201e7f0..0d00a65d2 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELiteral.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELiteral.java @@ -140,4 +140,12 @@ public class ELiteral extends Expression { return transformer.transform(this); } + @Override + public boolean equalsExpression(Expression expression) { + if(expression.getClass() != getClass()) + return false; + ELiteral other = (ELiteral)expression; + return value.equals(other.value); + } + } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERange.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERange.java index 50e4edd6a..2eaa5a208 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERange.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERange.java @@ -1,6 +1,6 @@ package org.simantics.scl.compiler.elaboration.expressions; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.errors.Locations; @@ -13,14 +13,12 @@ public class ERange extends ASTExpression { this.from = from; this.to = to; } - - private static final Name RANGE = Name.create("Prelude", "range"); @Override public Expression resolve(TranslationContext context) { from = from.resolve(context); to = to.resolve(context); - SCLValue rangeFunction = context.getEnvironment().getValue(RANGE); + SCLValue rangeFunction = context.getEnvironment().getValue(Names.Prelude_range); return new EApply(location, new EConstant(rangeFunction), from, to); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERealLiteral.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERealLiteral.java index f2e17aa00..bbc9d52ba 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERealLiteral.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERealLiteral.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.constants.DoubleConstant; import org.simantics.scl.compiler.constants.FloatConstant; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; @@ -84,7 +85,7 @@ public class ERealLiteral extends SimplifiableExpression { if(primitive != null) return primitive; return context.apply( - context.getConstant(SimplificationContext.FROM_DOUBLE, getType()), + context.getConstant(Names.Prelude_fromDouble, getType()), constraint.simplify(context), context.literal(new DoubleConstant(Double.parseDouble(value))) ); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERuleset.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERuleset.java index 02b8c9ddc..9e863a7a6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERuleset.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERuleset.java @@ -21,7 +21,7 @@ import java.util.ArrayList; import java.util.Set; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor; @@ -36,7 +36,6 @@ import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator import org.simantics.scl.compiler.internal.elaboration.utils.ForcedClosure; import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents; import org.simantics.scl.compiler.top.SCLCompilerConfiguration; -import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; @@ -191,15 +190,6 @@ public class ERuleset extends SimplifiableExpression { Variable handleFunc; } - public static final TCon MSet = Types.con("MSet", "T"); - private static final Name MSet_add = Name.create("MSet", "add"); - private static final Name MSet_create = Name.create("MSet", "create"); - - private static final TCon MList = Types.con("MList", "T"); - private static final Name MList_add = Name.create("MList", "add"); - private static final Name MList_create = Name.create("MList", "create"); - private static final Name MList_removeLast = Name.create("MList", "removeLast"); - public Expression compile(TypingContext context) { // Create a map from relations to their ids TObjectIntHashMap relationsToIds = new TObjectIntHashMap(relations.length, @@ -284,7 +274,7 @@ public class ERuleset extends SimplifiableExpression { LocalRelation relation = relations[i]; Type[] parameterTypes = relation.getParameterTypes(); stacks[i] = newVar("stack" + relation.getName(), - Types.apply(MList, Types.tuple(parameterTypes)) + Types.apply(Names.MList_T, Types.tuple(parameterTypes)) ); } @@ -305,7 +295,7 @@ public class ERuleset extends SimplifiableExpression { ArrayList seedExpressions = new ArrayList(); for(DatalogRule rule : rules) { int id = diffables.get(rule.headRelation).id; - Expression appendExp = apply(context, Types.PROC, MList_add, Types.tuple(rule.headRelation.getParameterTypes()), + Expression appendExp = apply(context.getCompilationContext(), Types.PROC, Names.MList_add, Types.tuple(rule.headRelation.getParameterTypes()), var(stacks[id]), tuple(rule.headParameters) ); @@ -349,7 +339,7 @@ public class ERuleset extends SimplifiableExpression { for(Expression updateExpression : updateExpressions[i]) handleRow = seq(updateExpression, handleRow); handleRow = if_( - apply(context, Types.PROC, MSet_add, rowType, + apply(context.getCompilationContext(), Types.PROC, Names.MSet_add, rowType, var(relation.table), var(row)), handleRow, tuple() @@ -361,7 +351,7 @@ public class ERuleset extends SimplifiableExpression { apply(Types.PROC, var(loops[(i+1)%relations.length]), addInteger(var(counter), integer(-1))) ); Expression body = matchWithDefault( - apply(context, Types.PROC, MList_removeLast, rowType, var(stacks[i])), + apply(context.getCompilationContext(), Types.PROC, Names.MList_removeLast, rowType, var(stacks[i])), Just(as(row, tuple(vars(parameters)))), handleRow, failure); @@ -376,7 +366,7 @@ public class ERuleset extends SimplifiableExpression { // Create stacks for(int i=0;i 1) { + context.getErrorLog().log(location, "String interpolation can be a pattern only if has one hole."); + return new EError(); + } + return new EApply(new ELiteral(new StringInterpolation(strings)), expressions); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVariable.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVariable.java index ca87d72c4..666bc2aca 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVariable.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVariable.java @@ -149,7 +149,7 @@ public class EVariable extends Expression { return this; } else - return applyPUnit(context); + return applyPUnit(context.getCompilationContext()); } @Override @@ -202,5 +202,13 @@ public class EVariable extends Expression { public Expression accept(ExpressionTransformer transformer) { return transformer.transform(this); } + + @Override + public boolean equalsExpression(Expression expression) { + if(expression.getClass() != getClass()) + return false; + EVariable other = (EVariable)expression; + return variable == other.variable; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EViewPattern.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EViewPattern.java new file mode 100644 index 000000000..268ee8ea8 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EViewPattern.java @@ -0,0 +1,137 @@ +package org.simantics.scl.compiler.elaboration.expressions; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.contexts.TypingContext; +import org.simantics.scl.compiler.environment.Environment; +import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; +import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; +import org.simantics.scl.compiler.types.exceptions.MatchException; +import org.simantics.scl.compiler.types.util.MultiFunction; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class EViewPattern extends Expression { + public Expression expression; + public Expression pattern; + + public EViewPattern(Expression expression, Expression pattern) { + this.expression = expression; + this.pattern = pattern; + } + + @Override + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + expression.collectRefs(allRefs, refs); + pattern.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + expression.collectVars(allVars, vars); + pattern.collectVars(allVars, vars); + } + + @Override + public void forVariables(VariableProcedure procedure) { + expression.forVariables(procedure); + pattern.forVariables(procedure); + } + + @Override + public Expression inferType(TypingContext context) { + context.setInPattern(false); + expression = expression.inferType(context); + context.setInPattern(true); + MultiFunction mfun; + try { + mfun = Types.matchFunction(expression.getType(), 1); + } catch (MatchException e) { + context.getErrorLog().log(expression.location, "Expected a function as a transformation expression."); + return new EError(location); + } + setType(mfun.parameterTypes[0]); + pattern.checkType(context, mfun.returnType); + return this; + } + + @Override + protected void updateType() throws MatchException { + MultiFunction mfun = Types.matchFunction(expression.getType(), 1); + setType(mfun.parameterTypes[0]); + } + + @Override + public IVal toVal(Environment env, CodeWriter w) { + throw new InternalCompilerError(location, "EViewPattern.toVal should not be invoked."); + } + + @Override + public void collectFreeVariables(THashSet vars) { + throw new InternalCompilerError(location, "Cannot collect free variables for a pattern."); + } + + @Override + public void removeFreeVariables(THashSet vars) { + expression.collectFreeVariables(vars); + pattern.removeFreeVariables(vars); + } + + @Override + public Expression resolve(TranslationContext context) { + context.getErrorLog().log("View pattern cannot occur only in patterns. Maybe you are missing '\\' in front of a lambda experssion?"); + return new EError(location); + } + + @Override + public Expression resolveAsPattern(TranslationContext context) { + expression = expression.resolve(context); + pattern = pattern.resolveAsPattern(context); + return this; + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + expression.setLocationDeep(loc); + pattern.setLocationDeep(loc); + } + } + + @Override + public Expression decorate(ExpressionDecorator decorator) { + expression = expression.decorate(decorator); + return this; + } + + @Override + public void collectEffects(THashSet effects) { + expression.collectEffects(effects); + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public Expression simplify(SimplificationContext context) { + expression = expression.simplify(context); + pattern = pattern.simplify(context); + return this; + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java index e01098c12..9a5fefb9f 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java @@ -207,6 +207,8 @@ public abstract class Expression extends Symbol implements Typed { public abstract void collectFreeVariables(THashSet vars); public Expression simplify(SimplificationContext context) { + System.out.println("#############################"); + System.out.println(this); throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method."); } @@ -376,4 +378,9 @@ public abstract class Expression extends Symbol implements Typed { } public abstract Expression accept(ExpressionTransformer transformer); + + // TODO implement for all expressions + public boolean equalsExpression(Expression expression) { + return false; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java index baeedd0f0..50f081499 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java @@ -9,7 +9,9 @@ public interface ExpressionTransformer { Expression transform(EBinary expression); Expression transform(EBind expression); Expression transform(EBlock expression); + Expression transform(ECHRRuleset expression); Expression transform(EConstant expression); + Expression transform(ECoveringBranchPoint expression); Expression transform(EEnforce expression); Expression transform(EEntityTypeAnnotation expression); Expression transform(EEquations expression); @@ -29,7 +31,6 @@ public interface ExpressionTransformer { Expression transform(EPlaceholder expression); Expression transform(EPreLet expression); Expression transform(EPreRuleset expression); - Expression transform(ECoveringBranchPoint expression); Expression transform(ERange expression); Expression transform(ERealLiteral expression); Expression transform(ERecord expression); @@ -42,6 +43,7 @@ public interface ExpressionTransformer { Expression transform(ETypeAnnotation expression); Expression transform(EVar expression); Expression transform(EVariable expression); + Expression transform(EViewPattern expression); Expression transform(EWhen expression); Expression transform(GuardedExpressionGroup expression); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java index 4fa4efaea..34f45dd0a 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java @@ -6,6 +6,7 @@ public interface ExpressionVisitor { void visit(EApplyType expression); void visit(EAsPattern expression); void visit(EBind expression); + void visit(ECHRRuleset echrRuleset); void visit(EConstant expression); void visit(ECoveringBranchPoint expression); void visit(EEnforce expression); @@ -32,6 +33,7 @@ public interface ExpressionVisitor { void visit(ETransformation expression); void visit(ETypeAnnotation expression); void visit(EVariable expression); + void visit(EViewPattern expression); void visit(EWhen expression); void visit(GuardedExpressionGroup expression); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expressions.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expressions.java index 10d9bcb63..e8fd80d7c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expressions.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expressions.java @@ -234,7 +234,7 @@ public class Expressions { } public static Expression isZeroInteger(Expression value) { - return apply(Types.NO_EFFECTS, new ELiteral(new JavaComparisonToZeroOperation("==")), value); + return apply(Types.NO_EFFECTS, new ELiteral(JavaComparisonToZeroOperation.IEQUAL), value); } public static Expression addInteger(Expression a, Expression b) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java index 1a2f451ee..2fc6d1e7e 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java @@ -1,5 +1,7 @@ package org.simantics.scl.compiler.elaboration.expressions; +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.CHRRule; import org.simantics.scl.compiler.elaboration.equation.EqBasic; import org.simantics.scl.compiler.elaboration.equation.EqGuard; import org.simantics.scl.compiler.elaboration.equation.Equation; @@ -79,6 +81,13 @@ EquationVisitor { return expression; } + @Override + public Expression transform(EViewPattern expression) { + expression.expression = expression.expression.accept(this); + expression.pattern = expression.pattern.accept(this); + return expression; + } + @Override public Expression transform(EBlock expression) { for(Statement statement : expression.statements) @@ -109,6 +118,20 @@ EquationVisitor { statement.body = statement.body.accept(this); } + @Override + public Expression transform(ECHRRuleset expression) { + expression.in = expression.in.accept(this); + for(CHRRule rule : expression.ruleset.rules) { + for(CHRLiteral lit : rule.head.literals) + for(int i=0;i "); + expression.pattern.accept(this); + b.append(')'); + } @Override public void visit(ELambdaType expression) { @@ -494,4 +511,38 @@ public class ExpressionToStringVisitor implements ExpressionVisitor, QueryVisito public void visit(EEquations eEquations) { b.append("eq"); } + + @Override + public void visit(ECHRRuleset echrRuleset) { + b.append("CHRRuleset"); + } + + public void visit(CHRRule rule) { + visit(rule.head); + b.append(" => "); + visit(rule.body); + } + + public void visit(CHRQuery query) { + boolean first = true; + for(CHRLiteral literal : query.literals) { + if(first) + first = false; + else + b.append(", "); + visit(literal); + } + } + + public void visit(CHRLiteral literal) { + if(literal.passive && literal.relation instanceof CHRConstraint) + b.append("@passive "); + if(literal.killAfterMatch) + b.append('-'); + b.append(literal.relation); + for(Expression parameter : literal.parameters) { + b.append(' '); + showPar(parameter); + } + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java index 0dee9f9ce..7935257ac 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java @@ -4,6 +4,9 @@ import org.cojen.classfile.TypeDesc; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.scl.compiler.common.datatypes.Constructor; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.common.precedence.Associativity; +import org.simantics.scl.compiler.common.precedence.Precedence; import org.simantics.scl.compiler.constants.BooleanConstant; import org.simantics.scl.compiler.constants.Constant; import org.simantics.scl.compiler.constants.JavaStaticField; @@ -56,6 +59,8 @@ public class Builtins extends ConcreteModule { public static SCLValue Nothing; public static SCLValue Just; + public static SCLValue EQUALS; + private Builtins() { super(Types.BUILTIN); @@ -63,45 +68,45 @@ public class Builtins extends ConcreteModule { StandardTypeConstructor Boolean = new StandardTypeConstructor(Types.BOOLEAN, Kinds.STAR, TypeDesc.BOOLEAN); Boolean.documentation = "Data type representing truth values `True` and `False`."; - addTypeConstructor("Boolean", Boolean); - addTypeConstructor("Byte", new StandardTypeConstructor(Types.BYTE, Kinds.STAR, TypeDesc.BYTE, + addTypeDescriptor("Boolean", Boolean); + addTypeDescriptor("Byte", new StandardTypeConstructor(Types.BYTE, Kinds.STAR, TypeDesc.BYTE, "8-bit signed integer")); - addTypeConstructor("Character", new StandardTypeConstructor(Types.CHARACTER, Kinds.STAR, TypeDesc.CHAR, + addTypeDescriptor("Character", new StandardTypeConstructor(Types.CHARACTER, Kinds.STAR, TypeDesc.CHAR, "16-bit Unicode character.")); - addTypeConstructor("Short", new StandardTypeConstructor(Types.SHORT, Kinds.STAR, TypeDesc.SHORT, + addTypeDescriptor("Short", new StandardTypeConstructor(Types.SHORT, Kinds.STAR, TypeDesc.SHORT, "16-bit signed integer")); - addTypeConstructor("Integer", new StandardTypeConstructor(Types.INTEGER, Kinds.STAR, TypeDesc.INT, + addTypeDescriptor("Integer", new StandardTypeConstructor(Types.INTEGER, Kinds.STAR, TypeDesc.INT, "32-bit signed integer")); - addTypeConstructor("Long", new StandardTypeConstructor(Types.LONG, Kinds.STAR, TypeDesc.LONG, + addTypeDescriptor("Long", new StandardTypeConstructor(Types.LONG, Kinds.STAR, TypeDesc.LONG, "64-bit signed integer")); - addTypeConstructor("Float", new StandardTypeConstructor(Types.FLOAT, Kinds.STAR, TypeDesc.FLOAT, + addTypeDescriptor("Float", new StandardTypeConstructor(Types.FLOAT, Kinds.STAR, TypeDesc.FLOAT, "32-bit floating point number")); - addTypeConstructor("Double", new StandardTypeConstructor(Types.DOUBLE, Kinds.STAR, TypeDesc.DOUBLE, + addTypeDescriptor("Double", new StandardTypeConstructor(Types.DOUBLE, Kinds.STAR, TypeDesc.DOUBLE, "64-bit floating point number")); - addTypeConstructor("String", new StandardTypeConstructor(Types.STRING, Kinds.STAR, TypeDesc.STRING, + addTypeDescriptor("String", new StandardTypeConstructor(Types.STRING, Kinds.STAR, TypeDesc.STRING, "Unicode string")); - addTypeConstructor("BooleanArray", new StandardTypeConstructor(Types.BOOLEAN_ARRAY, Kinds.STAR, TypeDesc.forClass(boolean[].class))); - addTypeConstructor("ByteArray", new StandardTypeConstructor(Types.BYTE_ARRAY, Kinds.STAR, TypeDesc.forClass(byte[].class))); - addTypeConstructor("CharacterArray", new StandardTypeConstructor(Types.CHARACTER_ARRAY, Kinds.STAR, TypeDesc.forClass(char[].class))); - addTypeConstructor("ShortArray", new StandardTypeConstructor(Types.SHORT_ARRAY, Kinds.STAR, TypeDesc.forClass(short[].class))); - addTypeConstructor("IntegerArray", new StandardTypeConstructor(Types.INTEGER_ARRAY, Kinds.STAR, TypeDesc.forClass(int[].class))); - addTypeConstructor("LongArray", new StandardTypeConstructor(Types.LONG_ARRAY, Kinds.STAR, TypeDesc.forClass(long[].class))); - addTypeConstructor("FloatArray", new StandardTypeConstructor(Types.FLOAT_ARRAY, Kinds.STAR, TypeDesc.forClass(float[].class))); - addTypeConstructor("DoubleArray", new StandardTypeConstructor(Types.DOUBLE_ARRAY, Kinds.STAR, TypeDesc.forClass(double[].class))); + addTypeDescriptor("BooleanArray", new StandardTypeConstructor(Types.BOOLEAN_ARRAY, Kinds.STAR, TypeDesc.forClass(boolean[].class))); + addTypeDescriptor("ByteArray", new StandardTypeConstructor(Types.BYTE_ARRAY, Kinds.STAR, TypeDesc.forClass(byte[].class))); + addTypeDescriptor("CharacterArray", new StandardTypeConstructor(Types.CHARACTER_ARRAY, Kinds.STAR, TypeDesc.forClass(char[].class))); + addTypeDescriptor("ShortArray", new StandardTypeConstructor(Types.SHORT_ARRAY, Kinds.STAR, TypeDesc.forClass(short[].class))); + addTypeDescriptor("IntegerArray", new StandardTypeConstructor(Types.INTEGER_ARRAY, Kinds.STAR, TypeDesc.forClass(int[].class))); + addTypeDescriptor("LongArray", new StandardTypeConstructor(Types.LONG_ARRAY, Kinds.STAR, TypeDesc.forClass(long[].class))); + addTypeDescriptor("FloatArray", new StandardTypeConstructor(Types.FLOAT_ARRAY, Kinds.STAR, TypeDesc.forClass(float[].class))); + addTypeDescriptor("DoubleArray", new StandardTypeConstructor(Types.DOUBLE_ARRAY, Kinds.STAR, TypeDesc.forClass(double[].class))); - addTypeConstructor("Array", new StandardTypeConstructor(Types.con(Types.BUILTIN, "Array"), Kinds.STAR_TO_STAR, TypeDesc.forClass(Object[].class))); + addTypeDescriptor("Array", new StandardTypeConstructor(Types.con(Types.BUILTIN, "Array"), Kinds.STAR_TO_STAR, TypeDesc.forClass(Object[].class))); - addTypeConstructor("Maybe", MaybeType.INSTANCE); + addTypeDescriptor("Maybe", MaybeType.INSTANCE); - addTypeConstructor("Variant", new StandardTypeConstructor(Types.VARIANT, Kinds.STAR, TypeDesc.forClass(Variant.class))); + addTypeDescriptor("Variant", new StandardTypeConstructor(Types.VARIANT, Kinds.STAR, TypeDesc.forClass(Variant.class))); addEffectConstructor("Proc", new EffectConstructor(Types.PROC)); - //addTypeConstructor("->", new StandardTypeConstructor(Kinds.STAR_TO_STAR_TO_STAR, Constants.FUNCTION)); - addTypeConstructor("[]", new StandardTypeConstructor(Types.LIST, Kinds.STAR_TO_STAR, Constants.LIST)); - addTypeConstructor("@", new StandardTypeConstructor(Types.PUNIT, Kinds.STAR, Constants.TUPLE[0])); - addTypeConstructor("TypeProxy", new StandardTypeConstructor(Types.TYPE_PROXY, Kinds.STAR_TO_STAR, Constants.TUPLE[0])); + //addTypeDescriptor("->", new StandardTypeConstructor(Kinds.STAR_TO_STAR_TO_STAR, Constants.FUNCTION)); + addTypeDescriptor("[]", new StandardTypeConstructor(Types.LIST, Kinds.STAR_TO_STAR, Constants.LIST)); + addTypeDescriptor("@", new StandardTypeConstructor(Types.PUNIT, Kinds.STAR, Constants.TUPLE[0])); + addTypeDescriptor("TypeProxy", new StandardTypeConstructor(Types.TYPE_PROXY, Kinds.STAR_TO_STAR, Constants.TUPLE[0])); // *** Tuples *** @@ -114,7 +119,7 @@ public class Builtins extends ConcreteModule { TCon constructor = Types.tupleConstructor(arity); StandardTypeConstructor typeConstructor = new StandardTypeConstructor(constructor, tupleKind, Constants.TUPLE[arity]); - addTypeConstructor(constructor.name, typeConstructor); + addTypeDescriptor(constructor.name, typeConstructor); Type returnType = Types.apply(constructor, vars); typeConstructor.setType(constructor, vars); Constant cons; @@ -181,12 +186,12 @@ public class Builtins extends ConcreteModule { Fundep.EMPTY_ARRAY); addTypeClass("VecComp", VecCompC); - addTypeConstructor("Vector", new VectorType(Types.VECTOR)); + addTypeDescriptor("Vector", new VectorType(Types.VECTOR)); addValue("getVector", new GetVector(Types.NO_EFFECTS, Types.VECTOR)); addValue("lengthVector", new LengthVector(Types.VECTOR)); //addValue("createVectorFromList", CreateVectorFromList.INSTANCE); - addTypeConstructor("MVector", new VectorType(Types.MVECTOR)); + addTypeDescriptor("MVector", new VectorType(Types.MVECTOR)); addValue("createMVector", CreateMVector.INSTANCE); addValue("createMVectorProto", CreateMVectorProto.INSTANCE); addValue("getMVector", new GetVector(Types.PROC, Types.MVECTOR)); @@ -219,7 +224,7 @@ public class Builtins extends ConcreteModule { x.createOccurrence())); runProcFunction.addBlock(block); - SCLConstant runProc = new SCLConstant(Name.create(Types.BUILTIN, "runProc"), runProcFunction.getType()); + SCLConstant runProc = new SCLConstant(Names.Builtin_runProc, runProcFunction.getType()); runProc.setDefinition(runProcFunction); runProc.setInlineArity(1, 0xffffffff); runProc.setBase(new JavaStaticMethod("org/simantics/scl/runtime/procedure/Procedures", @@ -267,18 +272,18 @@ public class Builtins extends ConcreteModule { Types.NO_EFFECTS, TypeDesc.forClass(TUnion.class), Type, -1)); - /*addValue("TUnion", new JavaStaticMethod( + addValue("TUnion2", new JavaStaticMethod( "org/simantics/scl/compiler/types/Types", "union", Types.NO_EFFECTS, - Type, Types.list(Type)));*/ + Type, Type, Type)); StandardTypeConstructor TypeC = new StandardTypeConstructor(Type, Kinds.STAR, TypeDesc.forClass("org/simantics/scl/compiler/types/Type")); TypeC.setType(Type); TypeC.isOpen = true; TypeC.documentation = "Represents an SCL data type."; - addTypeConstructor("Type", TypeC); + addTypeDescriptor("Type", TypeC); // typeOf :: Typeable a => a -> Type addValue("typeOf", TypeOfConstant.INSTANCE) @@ -311,7 +316,7 @@ public class Builtins extends ConcreteModule { BindingC.setType(Types.BINDING, A); BindingC.documentation = "`Binding` represents a data type in the form supported by Databoard library. " + "It is used to serialize and deserialize values."; - addTypeConstructor("Binding", BindingC); + addTypeDescriptor("Binding", BindingC); // typeOf :: Typeable a => a -> TypeReps addValue("binding", BindingConstant.INSTANCE) @@ -328,13 +333,18 @@ public class Builtins extends ConcreteModule { addRelation("Execute10", new ExecuteRelation(10)); } - addValue("newEq", EqualsFunction.INSTANCE); - addValue("newHash", HashCodeFunction.INSTANCE); + { + EQUALS = new SCLValue(Names.Builtin_equals, EqualsFunction.INSTANCE); + EQUALS.setPrecedence(new Precedence(4, Associativity.NONASSOC)); + addValue(EQUALS); + addValue("hashCode", HashCodeFunction.INSTANCE); + } + // Coverage { StandardTypeConstructor branchPoint = new StandardTypeConstructor(Types.BRANCH_POINT, Kinds.STAR, TypeDesc.forClass(BranchPoint.class)); - addTypeConstructor("BranchPoint", branchPoint); + addTypeDescriptor("BranchPoint", branchPoint); addValue("visitBranchPoint", VisitBranchPoint.INSTANCE); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/EqualsFunction.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/EqualsFunction.java index 3a4087c89..c2d3e6d0f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/EqualsFunction.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/EqualsFunction.java @@ -2,7 +2,9 @@ package org.simantics.scl.compiler.elaboration.java; import org.cojen.classfile.TypeDesc; import org.objectweb.asm.Label; +import org.simantics.scl.compiler.constants.ComparisonFunction; import org.simantics.scl.compiler.constants.FunctionValue; +import org.simantics.scl.compiler.internal.codegen.continuations.Cont; import org.simantics.scl.compiler.internal.codegen.references.Val; import org.simantics.scl.compiler.internal.codegen.utils.Constants; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; @@ -11,7 +13,7 @@ import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.kinds.Kinds; -public class EqualsFunction extends FunctionValue { +public class EqualsFunction extends FunctionValue implements ComparisonFunction { private static final TVar A = Types.var(Kinds.STAR); public static final EqualsFunction INSTANCE = new EqualsFunction(); @@ -43,4 +45,32 @@ public class EqualsFunction extends FunctionValue { mb.invokeStatic("java/util/Objects", "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]); return Types.BOOLEAN; } + + @Override + public String toString() { + return "=="; + } + + @Override + public void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_) { + parameters[0].push(mb); + parameters[1].push(mb); + TypeDesc parameterType = mb.getJavaTypeTranslator().getTypeDesc(parameters[0]); + if(parameterType.isPrimitive()) { + if(parameterType.equals(TypeDesc.VOID)) { + mb.jump(then_); + } + else { + mb.ifComparisonBranch(mb.getLabel(then_), "==", parameterType); + mb.jump(else_); + mb.ensureExists(then_); + } + } + else { + mb.invokeStatic("java/util/Objects", "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]); + mb.ifZeroComparisonBranch(mb.getLabel(else_), "=="); + mb.jump(then_); + mb.ensureExists(else_); + } + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/ListConstructor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/ListConstructor.java index 0f3f8f2d3..b67416eb6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/ListConstructor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/ListConstructor.java @@ -95,7 +95,7 @@ public class ListConstructor extends FunctionValue { @Override public String toString() { - return "[...]"; + return "[.." + arity + "..]"; } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/MemberRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/MemberRelation.java index 6c22babec..a022d1b37 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/MemberRelation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/MemberRelation.java @@ -1,6 +1,6 @@ package org.simantics.scl.compiler.elaboration.java; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expression; @@ -65,9 +65,8 @@ public class MemberRelation extends AbstractRelation { case BB: context.condition( new EApply( - context.getConstant(Name.create("Prelude", "elem"), typeParameters), + context.getConstant(Names.Prelude_elem, typeParameters), new Expression[] { - context.getEvidence(location, Types.pred(Types.EQ, typeParameters[0])), new EVariable(parameters[0]), new EVariable(parameters[1]) } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/OptionalRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/OptionalRelation.java index 3276e0f22..ef30deb43 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/OptionalRelation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/OptionalRelation.java @@ -1,6 +1,6 @@ package org.simantics.scl.compiler.elaboration.java; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expression; @@ -65,9 +65,8 @@ public class OptionalRelation extends AbstractRelation { case BB: context.condition( new EApply( - context.getConstant(Name.create("Prelude", "elemMaybe"), typeParameters), + context.getConstant(Names.Prelude_elemMaybe, typeParameters), new Expression[] { - context.getEvidence(location, Types.pred(Types.EQ, typeParameters[0])), new EVariable(parameters[0]), new EVariable(parameters[1]) } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeAlias.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeAlias.java index ce888324c..f0d852b1c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeAlias.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeAlias.java @@ -1,25 +1,37 @@ package org.simantics.scl.compiler.elaboration.modules; +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.kinds.Kind; -public class TypeAlias { - TCon con; - +public class TypeAlias extends TypeDescriptor { public TVar[] parameters; public Type body; + public String documentation; - public TypeAlias(TCon con, int arity) { - this.con = con; + public TypeAlias(TCon name, int arity) { + super(name); this.parameters = new TVar[arity]; } - public TCon getCon() { - return con; - } - public int getArity() { return parameters.length; } + + @Override + public Kind getKind() { + throw new InternalCompilerError("Unsupported method TypeAlias.getKind invoked."); + } + + @Override + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + + @Override + public String getDocumentation() { + return documentation; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeConstructor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeConstructor.java index e3adf5ba8..016a0b780 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeConstructor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeConstructor.java @@ -13,10 +13,9 @@ import org.simantics.scl.compiler.types.kinds.KArrow; import org.simantics.scl.compiler.types.kinds.Kind; import org.simantics.scl.compiler.types.kinds.Kinds; -public abstract class TypeConstructor { +public abstract class TypeConstructor extends TypeDescriptor { public Kind kind; - public TCon name; public TVar[] parameters; public Type type; @@ -30,11 +29,12 @@ public abstract class TypeConstructor { public boolean isOpen = true; public TypeConstructor(Kind kind) { + super(null); this.kind = kind; } public TypeConstructor(TCon name, Kind kind) { - this.name = name; + super(name); this.kind = kind; ArrayList vars = new ArrayList(2); @@ -48,6 +48,7 @@ public abstract class TypeConstructor { } public TypeConstructor(TCon name, TVar ... parameters) { + super(name); setType(name, parameters); Kind kind = Kinds.STAR; for(int i = parameters.length-1;i>=0;--i) @@ -60,14 +61,25 @@ public abstract class TypeConstructor { this.parameters = parameters; this.type = Types.apply(name, parameters); } - + public void setConstructors(Constructor ... constructors) { this.constructors = constructors; } public abstract TypeDesc construct(JavaTypeTranslator translator, Type[] parameters); + @Override public void setDocumentation(String documentation) { this.documentation = documentation; } + + @Override + public Kind getKind() { + return kind; + } + + @Override + public String getDocumentation() { + return documentation; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeDescriptor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeDescriptor.java new file mode 100644 index 000000000..d9e6615ef --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/modules/TypeDescriptor.java @@ -0,0 +1,14 @@ +package org.simantics.scl.compiler.elaboration.modules; + +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.compiler.types.kinds.Kind; + +public abstract class TypeDescriptor { + public TCon name; + public TypeDescriptor(TCon name) { + this.name = name; + } + public abstract Kind getKind(); + public abstract void setDocumentation(String documentation); + public abstract String getDocumentation(); +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/QNegation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/QNegation.java index 373efa413..030d419f7 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/QNegation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/QNegation.java @@ -1,6 +1,6 @@ package org.simantics.scl.compiler.elaboration.query; -import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.QueryTransformer; @@ -60,7 +60,7 @@ public class QNegation extends QAbstractModifier { @Override public void generate(QueryCompilationContext context) { context.condition(new EApply( - context.getConstant(Name.create("Prelude", "not"), Type.EMPTY_ARRAY), + context.getConstant(Names.Prelude_not, Type.EMPTY_ARRAY), innerContext.getContinuation())); } }); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/EnforcingContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/EnforcingContext.java index 66f8070a9..384deeeea 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/EnforcingContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/EnforcingContext.java @@ -1,5 +1,6 @@ package org.simantics.scl.compiler.elaboration.query.compilation; +import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.errors.ErrorLog; @@ -26,4 +27,8 @@ public class EnforcingContext { context.addConstraintDemand(evidence); return evidence; } + + public CompilationContext getCompilationContext() { + return context.getCompilationContext(); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/QueryCompilationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/QueryCompilationContext.java index f0f5b1227..d454c63eb 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/QueryCompilationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/QueryCompilationContext.java @@ -8,8 +8,9 @@ import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.constants.BooleanConstant; -import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.elaboration.expressions.Case; import org.simantics.scl.compiler.elaboration.expressions.EApply; @@ -23,16 +24,13 @@ import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.java.Builtins; -import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.types.TPred; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; -public class QueryCompilationContext implements EnvironmentalContext { - private static final Name EQUALS = Name.create("Prelude", "=="); - +public class QueryCompilationContext { TypingContext context; QueryCompilationMode mode; Type resultType; @@ -72,7 +70,7 @@ public class QueryCompilationContext implements EnvironmentalContext { } case GET_ALL: { try { - return new EApply(context.getConstant(Name.create("Prelude", "appendList"), + return new EApply(context.getCompilationContext().getConstant(Names.Prelude_appendList, Types.matchApply(Types.LIST, a.getType())), a, b); } catch (MatchException e) { throw new InternalCompilerError(); @@ -96,9 +94,8 @@ public class QueryCompilationContext implements EnvironmentalContext { condition(new EApply( location, Types.PROC, - context.getConstant(EQUALS, type), + context.getCompilationContext().getConstant(Names.Builtin_equals, type), new Expression[] { - getEvidence(location, Types.pred(Types.EQ, type)), a, b } @@ -132,7 +129,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Prelude", "iterList"), variable.getType(), Types.PROC, Types.tupleConstructor(0)), + context.getCompilationContext().getConstant(Names.Prelude_iterList, variable.getType(), Types.PROC, Types.tupleConstructor(0)), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), list @@ -143,7 +140,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Prelude", "any"), variable.getType(), Types.PROC), + context.getCompilationContext().getConstant(Names.Prelude_any, variable.getType(), Types.PROC), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), list @@ -154,7 +151,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Prelude", "concatMap"), variable.getType(), Types.PROC, + context.getCompilationContext().getConstant(Names.Prelude_concatMap, variable.getType(), Types.PROC, Types.matchApply(Types.LIST, continuation.getType())), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), @@ -166,7 +163,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Prelude", "mapFirst"), variable.getType(), Types.PROC, + context.getCompilationContext().getConstant(Names.Prelude_mapFirst, variable.getType(), Types.PROC, Types.matchApply(Types.MAYBE, continuation.getType())), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), @@ -188,7 +185,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Vector", "iterVector"), variable.getType(), Types.PROC, continuation.getType()), + context.getCompilationContext().getConstant(Names.Vector_iterVector, variable.getType(), Types.PROC, continuation.getType()), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), vector @@ -199,7 +196,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Vector", "anyVector"), variable.getType(), Types.PROC), + context.getCompilationContext().getConstant(Names.Vector_anyVector, variable.getType(), Types.PROC), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), vector @@ -210,7 +207,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Vector", "concatMapVector"), variable.getType(), Types.PROC, + context.getCompilationContext().getConstant(Names.Vector_concatMapVector, variable.getType(), Types.PROC, Types.matchApply(Types.LIST, continuation.getType())), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), @@ -222,7 +219,7 @@ public class QueryCompilationContext implements EnvironmentalContext { continuation = new EApply( Locations.NO_LOCATION, Types.PROC, - context.getConstant(Name.create("Vector", "mapFirstVector"), variable.getType(), Types.PROC, + context.getCompilationContext().getConstant(Names.Vector_mapFirstVector, variable.getType(), Types.PROC, Types.matchApply(Types.MAYBE, continuation.getType())), new Expression[] { new ESimpleLambda(Types.PROC, variable, continuation), @@ -237,20 +234,17 @@ public class QueryCompilationContext implements EnvironmentalContext { } } - private static final Name MSet_iter = Name.create("MSet", "iter"); - private static final Name MSet_mapFirst = Name.create("MSet", "mapFirst"); - public void iterateMSet(Variable variable, Expression set) { try { switch(mode) { case ITERATE: - continuation = apply(context, Types.PROC, MSet_iter, variable.getType(), Types.PROC, continuation.getType(), + continuation = apply(context.getCompilationContext(), Types.PROC, Names.MSet_iter, variable.getType(), Types.PROC, continuation.getType(), lambda(Types.PROC, variable, continuation), set ); break; case GET_FIRST: - continuation = apply(context, Types.PROC, MSet_mapFirst, variable.getType(), Types.PROC, + continuation = apply(context.getCompilationContext(), Types.PROC, Names.MSet_mapFirst, variable.getType(), Types.PROC, Types.matchApply(Types.MAYBE, continuation.getType()), lambda(Types.PROC, variable, continuation), set @@ -270,7 +264,7 @@ public class QueryCompilationContext implements EnvironmentalContext { } public Expression getConstant(Name name, Type[] typeParameters) { - return context.getConstant(name, typeParameters); + return context.getCompilationContext().getConstant(name, typeParameters); } public QueryCompilationContext createCheckContext() { @@ -316,8 +310,7 @@ public class QueryCompilationContext implements EnvironmentalContext { return evidence; } - @Override - public SCLValue getValue(Name name) { - return context.getValue(name); + public CompilationContext getCompilationContext() { + return context.getCompilationContext(); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/AbstractRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/AbstractRelation.java index 3d2a1e4e8..54acd32f3 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/AbstractRelation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/AbstractRelation.java @@ -1,8 +1,10 @@ package org.simantics.scl.compiler.elaboration.relations; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.types.Type; public abstract class AbstractRelation implements SCLRelation { @@ -16,4 +18,15 @@ public abstract class AbstractRelation implements SCLRelation { public Expression generateEnforce(long location, EnforcingContext context, Type[] typeParameters, Variable[] parameters) { throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce."); } + + @Override + public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce."); + } + + @Override + public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables, + Expression[] expressions) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate."); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/ConcreteRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/ConcreteRelation.java index 83714f26b..a38df0bcd 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/ConcreteRelation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/ConcreteRelation.java @@ -3,6 +3,7 @@ package org.simantics.scl.compiler.elaboration.relations; import java.util.ArrayList; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expression; @@ -12,6 +13,7 @@ import org.simantics.scl.compiler.elaboration.query.Query; import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext; import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.internal.parsing.Symbol; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; @@ -147,4 +149,14 @@ public class ConcreteRelation extends Symbol implements SCLRelation { return name; } + @Override + public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce."); + } + + @Override + public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables, + Expression[] expressions) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate."); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/LocalRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/LocalRelation.java index 0a193d6c1..3fbeef755 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/LocalRelation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/LocalRelation.java @@ -7,8 +7,7 @@ import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var import static org.simantics.scl.compiler.elaboration.expressions.Expressions.vars; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; -import org.simantics.scl.compiler.common.names.Name; -import org.simantics.scl.compiler.elaboration.expressions.ERuleset; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expressions; import org.simantics.scl.compiler.elaboration.expressions.Variable; @@ -39,7 +38,7 @@ public class LocalRelation extends AbstractRelation { private void createTable() { this.table = newVar("table" + name, - Types.apply(ERuleset.MSet, Types.tuple(parameterTypes))); + Types.apply(Names.MSet_T, Types.tuple(parameterTypes))); } public int getArity() { @@ -74,8 +73,6 @@ public class LocalRelation extends AbstractRelation { return 0; } - private static final Name MSet_contains = Name.create("MSet", "contains"); - private static final Name EQ = Name.create("Prelude", "=="); @Override public void generate(long location, QueryCompilationContext context, @@ -83,8 +80,8 @@ public class LocalRelation extends AbstractRelation { if(table == null) throw new InternalCompilerError(location, "Variable table is undefined."); if(boundVariables + 1 == 1 << parameters.length) - context.condition(apply(context, Types.PROC, - MSet_contains, Types.tuple(parameterTypes), + context.condition(apply(context.getCompilationContext(), Types.PROC, + Names.MSet_contains, Types.tuple(parameterTypes), var(table), tuple(vars(parameters)) )); @@ -98,9 +95,8 @@ public class LocalRelation extends AbstractRelation { Variable row = new Variable("row", Types.tuple(parameterTypes)); for(int i=0;i>i)&1) == 1) - context.condition(apply(context, Types.NO_EFFECTS, - EQ, parameterTypes[i], - context.getEvidence(location, Types.pred(Types.EQ, parameterTypes[i])), + context.condition(apply(context.getCompilationContext(), Types.NO_EFFECTS, + Names.Builtin_equals, parameterTypes[i], var(aux[i]), var(parameters[i]) )); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/SCLRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/SCLRelation.java index 7b2f2a19e..9642762cb 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/SCLRelation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/SCLRelation.java @@ -1,9 +1,11 @@ package org.simantics.scl.compiler.elaboration.relations; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; @@ -40,4 +42,16 @@ public interface SCLRelation { Type[] typeParameters, Variable[] parameters); + void generateIterate( + PlanContext context, + CodeWriter w, + long location, + int boundMask, + Variable[] variables, + Expression[] expressions); + void generateEnforce( + PlanContext context, + CodeWriter w, + long location, + Expression[] parameters); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/TransitiveClosureRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/TransitiveClosureRelation.java index c9fa469d2..42eb9530d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/TransitiveClosureRelation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/TransitiveClosureRelation.java @@ -9,6 +9,7 @@ import static org.simantics.scl.compiler.elaboration.expressions.Expressions.tup import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expression; @@ -67,9 +68,13 @@ public class TransitiveClosureRelation extends AbstractRelation implements Compo type = type.replace(getTypeVariables(), typeParameters); Expression continuation = context.getContinuation(); + System.out.println("continuation = " + continuation + " :: " + continuation.getType()); Variable set = new Variable("set", Types.apply(Types.con("MSet", "T"), type)); Variable f = new Variable("f", Types.functionE(type, Types.PROC, continuation.getType())); Variable innerSolved = new Variable("tcTemp", solved.getType()); + System.out.println("set :: " + set.getType()); + System.out.println("f :: " + f.getType()); + System.out.println("tcTemp :: " + innerSolved.getType()); QueryCompilationContext newContext = context.createSubcontext(new EApply( new EVariable(f), new EVariable(innerSolved) @@ -91,14 +96,14 @@ public class TransitiveClosureRelation extends AbstractRelation implements Compo innerParameters, boundVariables); continuation = context.disjunction(continuation, newContext.getContinuation()); - continuation = if_(apply(context, Types.PROC, Name.create("MSet", "add"), type, + continuation = if_(apply(context.getCompilationContext(), Types.PROC, Names.MSet_add, type, var(set), var(solved)), continuation, context.failure()); continuation = lambda(Types.PROC, solved, continuation); continuation = letRec(f, continuation, apply(var(f), var(bound))); continuation = let(set, - apply(context, Types.PROC, Name.create("MSet", "create"), type, tuple()), + apply(context.getCompilationContext(), Types.PROC, Names.MSet_create, type, tuple()), continuation); context.setContinuation(continuation); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/AbstractEnvironment.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/AbstractEnvironment.java index e91e39444..d6929232a 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/AbstractEnvironment.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/AbstractEnvironment.java @@ -6,10 +6,9 @@ import java.util.Collections; import org.simantics.scl.compiler.common.names.Name; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor; @@ -45,11 +44,11 @@ public abstract class AbstractEnvironment implements Environment { } @Override - public TypeConstructor getTypeConstructor(TCon type) { + public TypeDescriptor getTypeDescriptor(TCon type) { Module module = getModule(type.module); if(module == null) return null; - return module.getTypeConstructor(type.name); + return module.getTypeDescriptor(type.name); } @Override @@ -60,14 +59,6 @@ public abstract class AbstractEnvironment implements Environment { return module.getEffectConstructor(type.name); } - @Override - public TypeAlias getTypeAlias(TCon type) { - Module module = getModule(type.module); - if(module == null) - return null; - return module.getTypeAlias(type.name); - } - @Override public TypeClass getTypeClass(TCon type) { Module module = getModule(type.module); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/EmptyNamespace.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/EmptyNamespace.java index ed08b7b69..f40221eb5 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/EmptyNamespace.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/EmptyNamespace.java @@ -3,7 +3,6 @@ package org.simantics.scl.compiler.environment; import java.util.function.Consumer; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; @@ -39,10 +38,9 @@ public enum EmptyNamespace implements Namespace { throws AmbiguousNameException { return null; } - + @Override - public TypeConstructor getTypeConstructor(String name) - throws AmbiguousNameException { + public TypeConstructor getTypeDescriptor(String name) throws AmbiguousNameException { return null; } @@ -57,11 +55,6 @@ public enum EmptyNamespace implements Namespace { return null; } - @Override - public TypeAlias getTypeAlias(String name) throws AmbiguousNameException { - return null; - } - @Override public MappingRelation getMappingRelation(String name) throws AmbiguousNameException { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java index 70c62062d..b25fc7209 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java @@ -5,10 +5,9 @@ import java.util.Collection; import org.simantics.scl.compiler.common.names.Name; import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.elaboration.rules.TransformationRule; @@ -21,9 +20,8 @@ public interface Environment extends EnvironmentalContext { SCLValue getValue(Name name); SCLRelation getRelation(Name name); SCLEntityType getEntityType(Name name); - TypeConstructor getTypeConstructor(TCon type); + TypeDescriptor getTypeDescriptor(TCon type); EffectConstructor getEffectConstructor(TCon type); - TypeAlias getTypeAlias(TCon type); TypeClass getTypeClass(TCon type); Collection getInstances(TCon typeClass); void collectRules(Collection rules); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java index 5a55a6ca1..4328d15e0 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java @@ -6,17 +6,16 @@ import java.util.List; import java.util.function.Consumer; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.elaboration.rules.MappingRelation; import org.simantics.scl.compiler.elaboration.rules.TransformationRule; import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter; -import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor; import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException; import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl; @@ -80,8 +79,8 @@ public class Environments { * @return A TypeConstructor instance, or null if not found. * @throws AmbiguousNameException if the same name is found in multiple imported modules. */ - public static TypeConstructor getTypeConstructor(Environment environment, String localName) throws AmbiguousNameException { - return getEnvironmentEntry(environment, localName, getTypeConstructor); + public static TypeDescriptor getTypeDescriptor(Environment environment, String localName) throws AmbiguousNameException { + return getEnvironmentEntry(environment, localName, getTypeDescriptor); } /** @@ -107,18 +106,6 @@ public class Environments { public static TypeClass getTypeClass(Environment environment, String localName) throws AmbiguousNameException { return getEnvironmentEntry(environment, localName, getTypeClass); } - - /** - * Get the TypeAlias object representing a type alias defined in a given environment. - * The name can be a local name or a fully scoped name with modules separated by periods. - * @param environment the environment - * @param localName the name to be searched for - * @return A TypeAlias instance, or null if not found. - * @throws AmbiguousNameException if the same name is found in multiple imported modules. - */ - public static TypeAlias getTypeAlias(Environment environment, String localName) throws AmbiguousNameException { - return getEnvironmentEntry(environment, localName, getTypeAlias); - } /** * Get the Name object representing an SCL value defined in a given environment. @@ -144,12 +131,12 @@ public class Environments { * @return A TCon instance, or null if not found. * @throws AmbiguousNameException if the same name is used in multiple imported modules. */ - public static TCon getTypeConstructorName(Environment environment, String localName) throws AmbiguousNameException { - TypeConstructor typeConstructor = getTypeConstructor(environment, localName); - if(typeConstructor == null) + public static TCon getTypeDescriptorName(Environment environment, String localName) throws AmbiguousNameException { + TypeDescriptor typeDescriptor = getTypeDescriptor(environment, localName); + if(typeDescriptor == null) return null; else - return typeConstructor.name; + return typeDescriptor.name; } /** @@ -193,19 +180,20 @@ public class Environments { */ public static Type getType(Environment environment, String typeText) throws SCLExpressionCompilationException { SCLParserImpl parser = new SCLParserImpl(new StringReader(typeText)); - ErrorLog errorLog = new ErrorLog(); + CompilationContext compilationContext = new CompilationContext(); + compilationContext.environment = environment; try { TypeAst typeAst = (TypeAst)parser.parseType(); - TypeTranslationContext context = new TypeTranslationContext(errorLog, environment); + TypeTranslationContext context = new TypeTranslationContext(compilationContext); Type type = context.toType(typeAst); - if(errorLog.isEmpty()) + if(compilationContext.errorLog.isEmpty()) return type; } catch(SCLSyntaxErrorException e) { - errorLog.log(e.location, e.getMessage()); + compilationContext.errorLog.log(e.location, e.getMessage()); } catch(Exception e) { - errorLog.log(e); + compilationContext.errorLog.log(e); } - throw new SCLExpressionCompilationException(errorLog.getErrors()); + throw new SCLExpressionCompilationException(compilationContext.errorLog.getErrors()); } /** @@ -324,10 +312,10 @@ public class Environments { } }; - private static final NamespaceValueAccessor getTypeConstructor = new NamespaceValueAccessor() { + private static final NamespaceValueAccessor getTypeDescriptor = new NamespaceValueAccessor() { @Override - public TypeConstructor get(Namespace ns, String name) throws AmbiguousNameException { - return ns.getTypeConstructor(name); + public TypeDescriptor get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getTypeDescriptor(name); } }; @@ -345,13 +333,6 @@ public class Environments { } }; - private static final NamespaceValueAccessor getTypeAlias = new NamespaceValueAccessor() { - @Override - public TypeAlias get(Namespace ns, String name) throws AmbiguousNameException { - return ns.getTypeAlias(name); - } - }; - private static T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor accessor) throws AmbiguousNameException { Namespace namespace = environment.getLocalNamespace(); int curPos = 0; @@ -359,9 +340,10 @@ public class Environments { int pos = localName.indexOf('.', curPos); if(pos < 0) return accessor.get(namespace, localName.substring(curPos)); - namespace = namespace.getNamespace(localName.substring(curPos, pos)); - if(namespace == null) - return null; + Namespace newNamespace = namespace.getNamespace(localName.substring(curPos, pos)); + if(newNamespace == null) + return accessor.get(namespace, localName.substring(curPos)); + namespace = newNamespace; curPos = pos + 1; } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java index 921b9029d..3253931fe 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java @@ -3,9 +3,8 @@ package org.simantics.scl.compiler.environment; import java.util.function.Consumer; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.elaboration.rules.MappingRelation; @@ -52,13 +51,13 @@ public interface Namespace { SCLEntityType getEntityType(String name) throws AmbiguousNameException; /** - * Get a TypeConstructor for a given name. The same instance is returned on each call. + * Get a TypeDescriptor for a given name. The same instance is returned on each call. * @param name the name of a defined entity type - * @return The return value is a TypeConstructor provided by any source included in the namespace, + * @return The return value is a TypeDescriptor provided by any source included in the namespace, * or null if the name is not found. * @exception AmbiguousNameException if the name matches with multiple imported modules. */ - TypeConstructor getTypeConstructor(String name) throws AmbiguousNameException; + TypeDescriptor getTypeDescriptor(String name) throws AmbiguousNameException; /** * Get an EffectConstructor for a given name. The same instance is returned on each call. @@ -78,15 +77,6 @@ public interface Namespace { */ TypeClass getTypeClass(String name) throws AmbiguousNameException; - /** - * Get a TypeAlias for a given name. The same instance is returned on each call. - * @param name the name of a defined entity type - * @return The return value is a TypeAlias provided by any source included in the namespace, - * or null if the name is not found. - * @exception AmbiguousNameException if the name matches with multiple imported modules. - */ - TypeAlias getTypeAlias(String name) throws AmbiguousNameException; - TransformationRule getRule(String name) throws AmbiguousNameException; MappingRelation getMappingRelation(String name) throws AmbiguousNameException; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java index 98666c11a..6dac77acf 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java @@ -4,9 +4,8 @@ import java.util.ArrayList; import java.util.function.Consumer; import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeClass; -import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; import org.simantics.scl.compiler.elaboration.rules.MappingRelation; @@ -33,13 +32,6 @@ public class NamespaceImpl implements Namespace { this.module = module; this.filter = filter; } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("ModuleImport \"").append(module).append("\"").append(" with filter ").append(filter); - return sb.toString(); - } } public NamespaceImpl(THashMap namespaceMap, @@ -138,14 +130,14 @@ public class NamespaceImpl implements Namespace { } @Override - public TypeConstructor getTypeConstructor(String name) + public TypeDescriptor getTypeDescriptor(String name) throws AmbiguousNameException { - TypeConstructor result = null, temp; + TypeDescriptor result = null, temp; Module resultModule = null; ArrayList conflictingModules = null; for(ModuleImport moduleImport : moduleImports) { Module module = moduleImport.module; - temp = module.getTypeConstructor(name); + temp = module.getTypeDescriptor(name); if(temp != null) { if(result != null) { if(conflictingModules == null) { @@ -220,33 +212,6 @@ public class NamespaceImpl implements Namespace { return result; } - @Override - public TypeAlias getTypeAlias(String name) throws AmbiguousNameException { - TypeAlias result = null, temp; - Module resultModule = null; - ArrayList conflictingModules = null; - for(ModuleImport moduleImport : moduleImports) { - Module module = moduleImport.module; - temp = module.getTypeAlias(name); - if(temp != null) { - if(result != null) { - if(conflictingModules == null) { - conflictingModules = new ArrayList(2); - conflictingModules.add(resultModule.getName()); - } - conflictingModules.add(module.getName()); - } - else { - result = temp; - resultModule = module; - } - } - } - if(conflictingModules != null) - throw new AmbiguousNameException(conflictingModules, name); - return result; - } - @Override public MappingRelation getMappingRelation(String name) throws AmbiguousNameException { MappingRelation result = null, temp; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java index 853f316ee..34f6578e3 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java @@ -1,6 +1,7 @@ package org.simantics.scl.compiler.internal.codegen.analysis; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.constants.SCLConstant; import org.simantics.scl.compiler.internal.codegen.references.Val; import org.simantics.scl.compiler.internal.codegen.references.ValRef; @@ -58,8 +59,6 @@ public class LoopAnalysis { return isLoopingBlockWithBreaker(apply.getParent(), breaker); } } - - private static final Name BUILD = Name.create("Prelude", "build"); private static boolean isAppliedAtMostOnce(LetApply apply, ValRef funRef, SSAFunction function) { ValRef applyFunctionRef = apply.getFunction(); @@ -70,7 +69,7 @@ public class LoopAnalysis { if(!(applyFunction instanceof SCLConstant)) return false; // Not necessarily the right answer Name name = ((SCLConstant)applyFunction).getName(); - if(name == BUILD) + if(name == Names.Prelude_build) return true; return false; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/StatementBrowser.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/StatementBrowser.java index e580c7c79..8de2c37c8 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/StatementBrowser.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/StatementBrowser.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.internal.codegen.analysis; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.constants.SCLConstant; import org.simantics.scl.compiler.internal.codegen.continuations.ContRef; import org.simantics.scl.compiler.internal.codegen.references.BoundVar; @@ -147,10 +148,8 @@ public abstract class StatementBrowser { } } - private static final Name BUILD = Name.create("Prelude", "build"); - private static boolean callsOnlyOnce(Name name, int arity) { - if(name == BUILD) + if(name == Names.Prelude_build) return arity == 1; else return false; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerator.java new file mode 100644 index 000000000..bd7059ee2 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerator.java @@ -0,0 +1,648 @@ +package org.simantics.scl.compiler.internal.codegen.chr; + +import java.util.ArrayList; + +import org.cojen.classfile.TypeDesc; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; +import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo; +import org.simantics.scl.compiler.internal.codegen.references.BoundVar; +import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator; +import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils; +import org.simantics.scl.compiler.internal.codegen.utils.Constants; +import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable; +import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase; +import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; + +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.set.hash.THashSet; + +public class CHRCodeGenerator { + + public static final TypeDesc FACT_ID_TYPE = TypeDesc.INT; + public static final String CHRHashIndex_name = "org/simantics/scl/runtime/chr/CHRHashIndex"; + public static final TypeDesc CHRHashIndex = TypeDesc.forClass(CHRHashIndex_name); + public static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue"; + public static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name); + public static final String Fact_name = "org/simantics/scl/runtime/chr/Fact"; + public static final TypeDesc Fact = TypeDesc.forClass(Fact_name); + public static final String QUEUE = "queue"; + + private static class StoreInitialization { + final int access; + final String fieldName; + final TypeDesc fieldType; + final String className; + public StoreInitialization(int access, String fieldName, TypeDesc fieldType, String className) { + this.access = access; + this.fieldName = fieldName; + this.fieldType = fieldType; + this.className = className; + } + } + + public static void generateStore(ModuleBuilder moduleBuilder, CHRRuleset ruleset) { + ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.storeClassName, "java/lang/Object"); + if(ruleset.parameters == null) + ruleset.parameters = new BoundVar[0]; + ruleset.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.parameters); + + ArrayList hashIndexInitializations = new ArrayList<>(); + for(CHRConstraint constraint : ruleset.constraints) + generateFact(storeClassBuilder, constraint, hashIndexInitializations); + + // Fields + for(int i=0;i hashIndexInitializations) { + CHRRuleset ruleset = constraint.parentRuleset; + boolean supportsRemoval = constraint.mayBeRemoved(); + + ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder(); + JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator(); + TypeDesc storeTypeDesc = storeClassBuilder.getType(); + TypeDesc[] storeTypeDescArray = new TypeDesc[] { storeTypeDesc }; + + String factClassName = storeClassBuilder.getClassName() + "$" + constraint.name; + TypeDesc factTypeDesc = TypeDesc.forClass(factClassName); + ClassBuilder factClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, factClassName, "java/lang/Object", Fact_name); + + // Fields + + /* public int id; + public int c0; // key + public int c1; + public ExampleFact bfPrev; + public ExampleFact bfNext; + */ + TypeDesc[] parameterTypeDescs = jtt.toTypeDescs(constraint.parameterTypes); + factClassBuilder.addField(Opcodes.ACC_PUBLIC, "id", FACT_ID_TYPE); + for(int i=0;i getParameterTypeDescs = new ArrayList(constraint.parameterTypes.length); + for(int i=0;i>i)&1)==1) + getParameterTypeDescs.add(parameterTypeDescs[i]); + MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, constraint.name + "$" + indexInfo.indexName, factTypeDesc, + getParameterTypeDescs.toArray(new TypeDesc[getParameterTypeDescs.size()])); + mb.loadThis(); + mb.loadField(storeClassBuilder.getClassName(), constraint.name + "$temp", factTypeDesc); + LocalVariable tempFactVar = mb.createLocalVariable("temp", factTypeDesc); + mb.storeLocal(tempFactVar); + int parameterId=0; + for(int i=0;i>i)&1)==1) { + mb.loadLocal(tempFactVar); + mb.loadLocal(mb.getParameter(parameterId++)); + mb.storeField(factClassName, "c"+i, parameterTypeDescs[i]); + } + + mb.loadThis(); + mb.loadField(storeClassBuilder.getClassName(), constraint.name + "$" + indexInfo.indexName, CHRHashIndex); + mb.loadLocal(tempFactVar); + mb.invokeVirtual(CHRHashIndex_name, supportsRemoval ? "getEqual" : "getEqualNoRemovals", TypeDesc.OBJECT, Constants.OBJECTS[1]); + mb.checkCast(factTypeDesc); + + mb.returnValue(factTypeDesc); + mb.finish(); + } + } + } + + // Method: add + + { + MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "add", TypeDesc.VOID, storeTypeDescArray); + LocalVariable storeParameter = mb.getParameter(0); + for(IndexInfo indexInfo : constraint.getIndices()) { + String linkedListPrev = indexInfo.indexName + "Prev"; + String linkedListNext = indexInfo.indexName + "Next"; + String storeHashIndexName = constraint.name + "$" + indexInfo.indexName; + + // public void add(ExampleStore store) { + // bfNext = (ExampleFact)store.ExampleFact_bfIndex.addFreshAndReturnOld(this); + // if(bfNext != null) + // bfNext.bfPrev = this; + // } + + if(indexInfo.indexMask == 0) { + mb.loadThis(); + mb.loadLocal(storeParameter); + mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc); + if(supportsRemoval) + mb.dupX1(); + mb.storeField(factClassName, linkedListNext, factTypeDesc); + if(supportsRemoval) { + Label cont = new Label(); + mb.ifNullBranch(cont, true); + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + mb.loadThis(); + mb.storeField(factClassName, linkedListPrev, factTypeDesc); + mb.setLocation(cont); + } + mb.loadLocal(storeParameter); + mb.loadThis(); + mb.storeField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc); + } + else { + // bfNext = (ExampleFact)store.ExampleFact_bfIndex.addFreshAndReturnOld(this); + mb.loadThis(); + mb.loadLocal(storeParameter); + mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, CHRHashIndex); + mb.loadThis(); + mb.invokeVirtual(CHRHashIndex_name, supportsRemoval ? "addFreshAndReturnOld" : "addFreshAndReturnOld", TypeDesc.OBJECT, Constants.OBJECTS[1]); + mb.checkCast(factTypeDesc); + if(supportsRemoval) + mb.dupX1(); + mb.storeField(factClassName, linkedListNext, factTypeDesc); + // leaves bfNext on the stack + + //if(bfNext != null) + // bfNext.bfPrev = this; + if(supportsRemoval) { + Label cont = new Label(); + mb.ifNullBranch(cont, true); + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + mb.loadThis(); + mb.storeField(factClassName, linkedListPrev, factTypeDesc); + mb.setLocation(cont); + } + } + } + if(!constraint.isPassive()) { + mb.loadLocal(storeParameter); + mb.loadField(storeClassBuilder.getClassName(), QUEUE, FactActivationQueue); + mb.loadConstant(constraint.getMinimumPriority()); + mb.loadThis(); + mb.invokeVirtual(FactActivationQueue_name, "add", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT, Fact}); + } + mb.returnVoid(); + mb.finish(); + } + + // Method: remove + + if(supportsRemoval) { + // public void remove(ExampleStore store) { + // if(bfPrev == null) { + // if(bfNext == null) + // store.ExampleFact_bfIndex.removeKnownToExistKey(this); + // else { + // bfNext.bfPrev = null; + // store.ExampleFact_bfIndex.replaceKnownToExistKey(this, bfNext); + // } + // } + // else { + // bfPrev.bfNext = bfNext; + // if(bfNext != null) + // bfNext.bfPrev = bfPrev; + // } + // } + + MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "remove", TypeDesc.VOID, storeTypeDescArray); + LocalVariable storeParameter = mb.getParameter(0); + for(IndexInfo indexInfo : constraint.getIndices()) { + String linkedListPrev = indexInfo.indexName + "Prev"; + String linkedListNext = indexInfo.indexName + "Next"; + String storeHashIndexName = constraint.name + "$" + indexInfo.indexName; + + Label nextIndex = mb.createLabel(); + + // if(bfPrev == null) { + mb.loadThis(); + mb.loadField(factClassName, linkedListPrev, factTypeDesc); + Label else1 = new Label(); + mb.ifNullBranch(else1, false); + + // if(bfNext == null) + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + Label else2 = new Label(); + mb.ifNullBranch(else2, false); + + // store.ExampleFact_bfIndex.removeKnownToExistKey(this); + if(indexInfo.indexMask == 0) { + mb.loadLocal(storeParameter); + mb.loadNull(); + mb.storeField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc); + } + else { + mb.loadLocal(storeParameter); + mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, CHRHashIndex); + mb.loadThis(); + mb.invokeVirtual(CHRHashIndex_name, "removeKnownToExistKey", TypeDesc.VOID, Constants.OBJECTS[1]); + } + mb.branch(nextIndex); + + // else { + mb.setLocation(else2); + // bfNext.bfPrev = null; + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + mb.loadNull(); + mb.storeField(factClassName, linkedListPrev, factTypeDesc); + // store.ExampleFact_bfIndex.replaceKnownToExistKey(this, bfNext); + if(indexInfo.indexMask == 0) { + mb.loadLocal(storeParameter); + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + mb.storeField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc); + } + else { + mb.loadLocal(storeParameter); + mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, CHRHashIndex); + mb.loadThis(); + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + mb.invokeVirtual(CHRHashIndex_name, "replaceKnownToExistKey", TypeDesc.VOID, Constants.OBJECTS[2]); + } + mb.branch(nextIndex); + // } + + // else { + mb.setLocation(else1); + // bfPrev.bfNext = bfNext; + mb.loadThis(); + mb.loadField(factClassName, linkedListPrev, factTypeDesc); + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + mb.storeField(factClassName, linkedListNext, factTypeDesc); + // if(bfNext != null) + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + Label else3 = new Label(); + mb.ifNullBranch(else3, true); + // bfNext.bfPrev = bfPrev; + mb.loadThis(); + mb.loadField(factClassName, linkedListNext, factTypeDesc); + mb.loadThis(); + mb.loadField(factClassName, linkedListPrev, factTypeDesc); + mb.storeField(factClassName, linkedListPrev, factTypeDesc); + mb.setLocation(else3); + mb.branch(nextIndex); + // } + + mb.setLocation(nextIndex); + } + mb.loadThis(); + mb.loadConstant(-1); + mb.storeField(factClassName, "id", FACT_ID_TYPE); + mb.returnVoid(); + mb.finish(); + } + + // Method: isAlive + + { + // @Override + // public boolean isAlive() { + // return id >= 0; + // } + + MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "isAlive", TypeDesc.BOOLEAN, Constants.EMPTY_TYPEDESC_ARRAY); + if(supportsRemoval) { + mb.loadThis(); + mb.loadField(factClassName, "id", FACT_ID_TYPE); + + Label thenBranch = mb.createLabel(); + mb.ifZeroComparisonBranch(thenBranch, "<"); + mb.loadConstant(true); + mb.returnValue(TypeDesc.BOOLEAN); + + mb.setLocation(thenBranch); + mb.loadConstant(false); + mb.returnValue(TypeDesc.BOOLEAN); + } + else { + mb.loadConstant(true); + mb.returnValue(TypeDesc.BOOLEAN); + } + mb.finish(); + } + + // activate parts + + THashSet usedParameters = new THashSet(); + for(int i=0;i { + if(valRef.getBinding() instanceof BoundVar) + usedParameters.add((BoundVar)valRef.getBinding()); + }); + for(int j=0;j labels = new ArrayList