From: Tuukka Lehtonen Date: Wed, 28 Dec 2016 14:52:02 +0000 (+0200) Subject: Merge "Remove unused import in DeleteHandler" X-Git-Tag: v1.26.0~8 X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=593a8f75d9dbc363234002dc500c346afbeba040;hp=05e9ccefa08e1407b49940c32b1239b171d0008e Merge "Remove unused import in DeleteHandler" --- diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..146504cda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +*.java text +*.pgraph text +*.scl text +*.xml text +*.svg text +MANIFEST.MF text + +*.tg binary +*.png binary +*.gif binary \ No newline at end of file diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index 2d97f0e0d..19c1651ea 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -3,6 +3,6 @@ org.eclipse.tycho.extras tycho-pomless - 0.25.0 + 0.26.0 \ No newline at end of file diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java index 51db52efc..b2a30953c 100644 --- a/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java +++ b/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java @@ -70,7 +70,7 @@ public class ClusterManager { info.acquireMutex(); try { info.makeResident(); - return info.getCSSIds(); + return info.getCCSIds(); } finally { info.releaseMutex(); } diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java index 05f9c8de0..90af336aa 100644 --- a/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java +++ b/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java @@ -122,10 +122,10 @@ public class GraphClientImpl2 implements Database.Session { mainProgram.mutex.release(); } } catch (IllegalAcornStateException | ProCoreException e) { - Logger.defaultLogError(e); + Logger.defaultLogError("Snapshotting failed", e); unexpectedClose = true; } catch (InterruptedException e) { - Logger.defaultLogError(e); + Logger.defaultLogError("Snapshotting interrupted", e); } finally { try { if(tr != null) @@ -135,11 +135,11 @@ public class GraphClientImpl2 implements Database.Session { try { support.close(); } catch (DatabaseException e1) { - Logger.defaultLogError(e1); + Logger.defaultLogError("Failed to close database as a safety measure due to failed snapshotting", e1); } } } catch (ProCoreException e) { - Logger.defaultLogError(e); + Logger.defaultLogError("Failed to end snapshotting write transaction", e); } } } @@ -239,18 +239,17 @@ public class GraphClientImpl2 implements Database.Session { @Override public long cancelCommit(long transactionId, long changeSetId, byte[] metadata, OnChangeSetUpdate onChangeSetUpdate) throws ProCoreException { - UnsupportedOperationException e = new UnsupportedOperationException("org.simantics.acorn.GraphClientImpl2.cancelCommit() is not supported operation! Closing down to prevent further havoc"); - clusters.notSafeToMakeSnapshot(new IllegalAcornStateException(e)); - throw e; -// System.err.println("GraphClientImpl2.cancelCommit() called!! this is experimental and might cause havoc!"); -// try { -// undo(new long[] {changeSetId}, onChangeSetUpdate); -// } catch (SDBException e) { -// e.printStackTrace(); -// throw new ProCoreException(e); -// } -// clusters.state.headChangeSetId++; -// return clusters.state.headChangeSetId; + // Accept and finalize current transaction and then undo it + acceptCommit(transactionId, changeSetId, metadata); + + try { + undo(new long[] {changeSetId+1}, onChangeSetUpdate); + clusters.state.headChangeSetId++; + return clusters.state.headChangeSetId; + } catch (SDBException e) { + Logger.defaultLogError("Failed to undo cancelled transaction", e); + throw new ProCoreException(e); + } } @Override @@ -622,10 +621,11 @@ public class GraphClientImpl2 implements Database.Session { ArrayList ccss = clusters.getChanges(id); for(int j=0;j { LRU.insert(this, accessTime); } - public ArrayList getCSSIds() throws AcornAccessVerificationException { + public ArrayList getCCSIds() throws AcornAccessVerificationException { if(VERIFY) verifyAccess(); return clusterChangeSetIds; } diff --git a/bundles/org.simantics.desktop.product/simantics-desktop.product b/bundles/org.simantics.desktop.product/simantics-desktop.product index af09f04b7..109d06cc5 100644 --- a/bundles/org.simantics.desktop.product/simantics-desktop.product +++ b/bundles/org.simantics.desktop.product/simantics-desktop.product @@ -26,10 +26,10 @@ org.eclipse.e4.ui.css.theme.e4_classic -Xmx500M -Xshare:off -XX:MaxPermSize=192m --Djava.net.preferIPv4Stack=true -Dorg.simantics.workbench.application.showFastViewBars=false -Dorg.simantics.workbench.application.showPerspectiveBar=false -Dorg.simantics.workbench.application.excludePerspectiveFromTitle=true +-Djava.util.Arrays.useLegacyMergeSort=true -Declipse.workaround.bug467000=true -Dorg.osgi.framework.os.name=win32 @@ -60,6 +60,7 @@ org.eclipse.e4.ui.css.theme.e4_classic + 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.workbench/META-INF/MANIFEST.MF b/bundles/org.simantics.modeling.ui.workbench/META-INF/MANIFEST.MF index e5a9cf6b1..5adc0cb6d 100644 --- a/bundles/org.simantics.modeling.ui.workbench/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.modeling.ui.workbench/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: General Modeling Workbench Contributions Bundle-SymbolicName: org.simantics.modeling.ui.workbench;singleton:=true -Bundle-Version: 1.25.0.qualifier +Bundle-Version: 1.26.0.qualifier Bundle-Vendor: Semantum Oy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.ui 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/GraphModuleSourceRepository.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java index 3edc7bfea..10a217b9d 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java @@ -1,210 +1,204 @@ -package org.simantics.modeling.scl; - -import java.util.Collection; - -import org.simantics.Simantics; -import org.simantics.db.ReadGraph; -import org.simantics.db.RequestProcessorSpecific; -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.UnaryRead; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.procedure.SyncListener; -import org.simantics.db.request.Read; -import org.simantics.layer0.Layer0; -import org.simantics.modeling.ModelingUtils; -import org.simantics.scl.compiler.module.repository.UpdateListener; -import org.simantics.scl.compiler.source.ModuleSource; -import org.simantics.scl.compiler.source.StringModuleSource; -import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; -import org.simantics.scl.runtime.SCLContext; -import org.simantics.structural2.utils.StructuralUtils; -import org.simantics.scl.runtime.tuple.Tuple0; - -import gnu.trove.procedure.TObjectProcedure; -import gnu.trove.set.hash.THashSet; - -public enum GraphModuleSourceRepository implements ModuleSourceRepository { - INSTANCE; - - @Override - public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) { - if(!moduleName.startsWith("http://")) - return null; - - Object graph = SCLContext.getCurrent().get("graph"); - RequestProcessorSpecific requestProcessor; - if(graph instanceof ReadGraph) - requestProcessor = (ReadGraph)graph; - else - requestProcessor = Simantics.getSession(); - - Read request = new ReadModuleSource(moduleName); - - try { - if(listener != null) - return requestProcessor.syncRequest(request, new ModuleListener(listener, moduleName)); - else - return requestProcessor.syncRequest(request); - } catch (DatabaseException e) { - e.printStackTrace(); - return null; - } - } - - static class ModuleListener implements SyncListener { - UpdateListener listener; - boolean alreadyExecutedOnce; - final String moduleName; - public ModuleListener(UpdateListener listener, String moduleName) { - this.listener = listener; - this.moduleName = moduleName; - } - @Override - public boolean isDisposed() { - return listener == null; - } - private void fireUpdate(ReadGraph graph) { - if(listener != null) { - SCLContext context = SCLContext.getCurrent(); - Object oldGraph = context.put("graph", graph); - try { - listener.notifyAboutUpdate(); - } finally { - listener = null; - context.put("graph", oldGraph); - } - } - } - @Override - public void execute(ReadGraph graph, ModuleSource result) - throws DatabaseException { - if(alreadyExecutedOnce) - fireUpdate(graph); - else - alreadyExecutedOnce = true; - } - @Override - public void exception(ReadGraph graph, Throwable t) - throws DatabaseException { - t.printStackTrace(); - if(alreadyExecutedOnce && listener != null) - fireUpdate(graph); - } - }; - - public static class GraphModuleSource extends StringModuleSource { - - private final boolean immutable; - - public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText, boolean immutable) { - super(moduleName, classLoader, moduleText); - this.immutable = immutable; - } - - @Override - public boolean isUpdateable() { - return !immutable; - } - - @Override - public void update(String newSourceText) { - try { - Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText)); - } catch (DatabaseException e) { - e.printStackTrace(); - } - } - } - - static class ReadModuleSource extends UnaryRead { - public ReadModuleSource(String moduleName) { - super(moduleName); - } - - @Override - public ModuleSource perform(ReadGraph graph) throws DatabaseException { - Resource moduleResource = graph.getPossibleResource(parameter); - if(moduleResource == null) - return null; - Layer0 L0 = Layer0.getInstance(graph); - if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) - return null; - String text = graph.getRelatedValue(moduleResource, L0.SCLModule_definition); - boolean immutable = StructuralUtils.isImmutable(graph, moduleResource); - return new GraphModuleSource(parameter, getClass().getClassLoader(), text, immutable); - } - } - - static class WriteModuleSource extends WriteRequest { - private final String moduleURI; - private final String sourceText; - - public WriteModuleSource(String moduleURI, String sourceText) { - this.moduleURI = moduleURI; - this.sourceText = sourceText; - } - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - Resource moduleResource = graph.getPossibleResource(moduleURI); - if(moduleResource == null) - return; - Layer0 L0 = Layer0.getInstance(graph); - if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) - return; - graph.claimLiteral(moduleResource, L0.SCLModule_definition, sourceText); - } - } - - @Override - public void forAllModules(TObjectProcedure procedure) { - THashSet moduleURIs; - try { - moduleURIs = Simantics.getSession().syncRequest(new Read>() { - @Override - public THashSet perform(ReadGraph graph) - throws DatabaseException { - THashSet result = new THashSet(); - Resource projectResource = Simantics.getProjectResource(); - Layer0 L0 = Layer0.getInstance(graph); - for(Resource model : graph.getObjects(projectResource, L0.ConsistsOf)) { - if(graph.isInstanceOf(model, L0.IndexRoot)) { - for(Resource module : ModelingUtils.searchByType(graph, model, L0.SCLModule)) - result.add(graph.getURI(module)); - } - } - - Collection ontologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); - for (Resource ontology : ontologies) { - for(Resource module : ModelingUtils.searchByType(graph, ontology, L0.SCLModule)) - result.add(graph.getURI(module)); - } - - return result; - } - }); - moduleURIs.forEach(procedure); - } catch (DatabaseException e) { - e.printStackTrace(); - } - } - - @Override - public void checkUpdates() { - } - - @Override - public String getDocumentation(String documentationName) { - return null; - } - - @Override - public void forAllDocumentations(TObjectProcedure procedure) { - } - - @Override - public void clear() { - } -} +package org.simantics.modeling.scl; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessorSpecific; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.procedure.SyncListener; +import org.simantics.db.request.Read; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingUtils; +import org.simantics.scl.compiler.module.repository.UpdateListener; +import org.simantics.scl.compiler.source.ModuleSource; +import org.simantics.scl.compiler.source.StringModuleSource; +import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.structural2.utils.StructuralUtils; +import org.simantics.scl.runtime.tuple.Tuple0; + +import gnu.trove.procedure.TObjectProcedure; +import gnu.trove.set.hash.THashSet; + +public enum GraphModuleSourceRepository implements ModuleSourceRepository { + INSTANCE; + + @Override + public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) { + if(!moduleName.startsWith("http://")) + return null; + + Object graph = SCLContext.getCurrent().get("graph"); + RequestProcessorSpecific requestProcessor; + if(graph instanceof ReadGraph) + requestProcessor = (ReadGraph)graph; + else + requestProcessor = Simantics.getSession(); + + Read request = new ReadModuleSource(moduleName); + + try { + if(listener != null) + return requestProcessor.syncRequest(request, new ModuleListener(listener, moduleName)); + else + return requestProcessor.syncRequest(request); + } catch (DatabaseException e) { + e.printStackTrace(); + return null; + } + } + + static class ModuleListener implements SyncListener { + UpdateListener listener; + boolean alreadyExecutedOnce; + final String moduleName; + public ModuleListener(UpdateListener listener, String moduleName) { + this.listener = listener; + this.moduleName = moduleName; + } + @Override + public boolean isDisposed() { + return listener == null; + } + private void fireUpdate(ReadGraph graph) { + if(listener != null) { + SCLContext context = SCLContext.getCurrent(); + Object oldGraph = context.put("graph", graph); + try { + listener.notifyAboutUpdate(); + } finally { + listener = null; + context.put("graph", oldGraph); + } + } + } + @Override + public void execute(ReadGraph graph, ModuleSource result) + throws DatabaseException { + if(alreadyExecutedOnce) + fireUpdate(graph); + else + alreadyExecutedOnce = true; + } + @Override + public void exception(ReadGraph graph, Throwable t) + throws DatabaseException { + t.printStackTrace(); + if(alreadyExecutedOnce && listener != null) + fireUpdate(graph); + } + }; + + public static class GraphModuleSource extends StringModuleSource { + + private final boolean immutable; + + public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText, boolean immutable) { + super(moduleName, classLoader, moduleText); + this.immutable = immutable; + } + + @Override + public boolean isUpdateable() { + return !immutable; + } + + @Override + public void update(String newSourceText) { + try { + Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText)); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } + + static class ReadModuleSource extends UnaryRead { + public ReadModuleSource(String moduleName) { + super(moduleName); + } + + @Override + public ModuleSource perform(ReadGraph graph) throws DatabaseException { + Resource moduleResource = graph.getPossibleResource(parameter); + if(moduleResource == null) + return null; + Layer0 L0 = Layer0.getInstance(graph); + if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) + return null; + String text = graph.getRelatedValue(moduleResource, L0.SCLModule_definition); + boolean immutable = StructuralUtils.isImmutable(graph, moduleResource); + return new GraphModuleSource(parameter, getClass().getClassLoader(), text, immutable); + } + } + + static class WriteModuleSource extends WriteRequest { + private final String moduleURI; + private final String sourceText; + + public WriteModuleSource(String moduleURI, String sourceText) { + this.moduleURI = moduleURI; + this.sourceText = sourceText; + } + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Resource moduleResource = graph.getPossibleResource(moduleURI); + if(moduleResource == null) + return; + Layer0 L0 = Layer0.getInstance(graph); + if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) + return; + graph.claimLiteral(moduleResource, L0.SCLModule_definition, sourceText); + } + } + + @Override + public void forAllModules(TObjectProcedure procedure) { + THashSet moduleURIs; + try { + moduleURIs = Simantics.getSession().syncRequest(new Read>() { + @Override + public THashSet perform(ReadGraph graph) + throws DatabaseException { + THashSet result = new THashSet(); + Resource projectResource = Simantics.getProjectResource(); + Layer0 L0 = Layer0.getInstance(graph); + for(Resource model : graph.getObjects(projectResource, L0.ConsistsOf)) { + if(graph.isInstanceOf(model, L0.IndexRoot)) { + for(Resource module : ModelingUtils.searchByType(graph, model, L0.SCLModule)) + result.add(graph.getURI(module)); + } + } + + Collection ontologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); + for (Resource ontology : ontologies) { + for(Resource module : ModelingUtils.searchByType(graph, ontology, L0.SCLModule)) + result.add(graph.getURI(module)); + } + + return result; + } + }); + moduleURIs.forEach(procedure); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + @Override + public Collection getModuleNames() { + ArrayList result = new ArrayList<>(); + forAllModules((String name) -> { + result.add(name); + return true; + }); + return result; + } +} 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.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java index a8cefb1fa..6fbcfd8e9 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java @@ -1,73 +1,64 @@ -package org.simantics.modeling.scl; - - -import org.simantics.Simantics; -import org.simantics.db.ReadGraph; -import org.simantics.db.common.request.UnaryRead; -import org.simantics.db.exception.DatabaseException; -import org.simantics.scl.compiler.module.repository.UpdateListener; -import org.simantics.scl.compiler.source.ModuleSource; -import org.simantics.scl.compiler.source.PrecompiledModuleSource; -import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; -import org.simantics.scl.runtime.SCLContext; - -import gnu.trove.procedure.TObjectProcedure; - -public enum OntologyModuleSourceRepository implements ModuleSourceRepository { - INSTANCE; - - static class ModuleSourceRequest extends UnaryRead { - - public ModuleSourceRequest(String moduleName) { - super(moduleName); - } - - @Override - public ModuleSource perform(ReadGraph graph) throws DatabaseException { - return new PrecompiledModuleSource(new OntologyModule(graph, parameter), -1.0); - } - - }; - - @Override - public ModuleSource getModuleSource(final String moduleName, - UpdateListener listener) { - if(!moduleName.startsWith("http://")) - return null; // Don't do a graph request if this cannot be a resource - - ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph"); - - try { - if(graph != null) { - return new PrecompiledModuleSource(new OntologyModule(graph, moduleName), -1.0); - } - - return Simantics.getSession().syncRequest(new ModuleSourceRequest(moduleName)); - } catch(DatabaseException e) { - e.printStackTrace(); - return null; - } - } - - @Override - public void forAllModules(TObjectProcedure procedure) { - } - - @Override - public void checkUpdates() { - } - - @Override - public String getDocumentation(String documentationName) { - return null; - } - - @Override - public void forAllDocumentations(TObjectProcedure procedure) { - } - - @Override - public void clear() { - } - -} +package org.simantics.modeling.scl; + + +import java.util.Collection; +import java.util.Collections; + +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.scl.compiler.module.repository.UpdateListener; +import org.simantics.scl.compiler.source.ModuleSource; +import org.simantics.scl.compiler.source.PrecompiledModuleSource; +import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; +import org.simantics.scl.runtime.SCLContext; + +import gnu.trove.procedure.TObjectProcedure; + +public enum OntologyModuleSourceRepository implements ModuleSourceRepository { + INSTANCE; + + static class ModuleSourceRequest extends UnaryRead { + + public ModuleSourceRequest(String moduleName) { + super(moduleName); + } + + @Override + public ModuleSource perform(ReadGraph graph) throws DatabaseException { + return new PrecompiledModuleSource(new OntologyModule(graph, parameter), -1.0); + } + + }; + + @Override + public ModuleSource getModuleSource(final String moduleName, + UpdateListener listener) { + if(!moduleName.startsWith("http://")) + return null; // Don't do a graph request if this cannot be a resource + + ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph"); + + try { + if(graph != null) { + return new PrecompiledModuleSource(new OntologyModule(graph, moduleName), -1.0); + } + + return Simantics.getSession().syncRequest(new ModuleSourceRequest(moduleName)); + } catch(DatabaseException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public void forAllModules(TObjectProcedure procedure) { + } + + @Override + public Collection getModuleNames() { + return Collections.emptyList(); + } + +} 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..f5834aef1 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) { @@ -1190,7 +1198,7 @@ public class Elaboration { } else if(annotation.id.text.equals("@inline")) { try { - int arity = defs.get(0).lhs.getFunctionDefinitionArity(); + int arity = defs.get(0).lhs.getFunctionDefinitionPatternArity(); int phaseMask = 0xffffffff; if(annotation.parameters.length > 0) { phaseMask = Integer.parseInt(((EIntegerLiteral)annotation.parameters[0]).getValue()); 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..3118142df 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) @@ -206,30 +204,40 @@ public class TypeChecking { Expression expression = value.getExpression(); + int errorCountBeforeTypeChecking = compilationContext.errorLog.getErrorCount(); + int functionArity = expression.getSyntacticFunctionArity(); + try { ArrayList vars = new ArrayList(); type = Types.removeForAll(type, vars); 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()); + + if(compilationContext.errorLog.getErrorCount() != errorCountBeforeTypeChecking) { + int typeArity = Types.getArity(type); + if(typeArity != functionArity) + compilationContext.errorLog.log(value.definitionLocation, "Possible problem: type declaration has " + typeArity + " parameter types, but function definition has " + functionArity + " parameters."); + } + ArrayList demands = context.getConstraintDemand(); if(!demands.isEmpty() || !givenConstraints.isEmpty()) { ReducedConstraints red = 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 +247,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 +344,7 @@ public class TypeChecking { public void typeCheck() { ce = new ConstraintEnvironment(environment); - scheduler = new TypeCheckingScheduler(errorLog, environment); + scheduler = new TypeCheckingScheduler(compilationContext); typeCheckValues(); typeCheckRelations(); @@ -424,7 +432,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/Case.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Case.java index 50eda1c13..4a34cebcf 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Case.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Case.java @@ -1,123 +1,123 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.errors.Locations; -import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; -import org.simantics.scl.compiler.internal.parsing.Symbol; -import org.simantics.scl.compiler.types.Type; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class Case extends Symbol { - public Expression[] patterns; - public Expression value; - - long lhs; - - public Case(Expression[] patterns, Expression value) { - this.patterns = patterns; - this.value = value; - } - - public Case(Expression pattern, Expression value) { - this(new Expression[] {pattern}, value); - } - - public void setLhs(long lhs) { - this.lhs = lhs; - } - - public long getLhs() { - return lhs; - } - - public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { - value.collectRefs(allRefs, refs); - } - - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - value.collectVars(allVars, vars); - } - - public void collectFreeVariables(THashSet vars) { - value.collectFreeVariables(vars); - for(int i=patterns.length-1;i>=0;--i) - patterns[i].removeFreeVariables(vars); - } - - public void resolve(TranslationContext context) { - context.pushFrame(); - for(int i=0;i allRefs, TIntHashSet refs) { + value.collectRefs(allRefs, refs); + } + + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + value.collectVars(allVars, vars); + } + + public void collectFreeVariables(THashSet vars) { + value.collectFreeVariables(vars); + for(int i=patterns.length-1;i>=0;--i) + patterns[i].removeFreeVariables(vars); + } + + public void resolve(TranslationContext context) { + context.pushFrame(); + for(int i=0;i allRefs, TIntHashSet refs) { - function.collectRefs(allRefs, refs); - for(Expression parameter : parameters) - parameter.collectRefs(allRefs, refs); - } - - public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { - function.collectVars(allVars, vars); - for(Expression parameter : parameters) - parameter.collectVars(allVars, vars); - } - - @Override - protected void updateType() throws MatchException { - MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length); - /*for(int i=0;i vars) { - function.collectFreeVariables(vars); - for(Expression parameter : parameters) - parameter.collectFreeVariables(vars); - } - - private void combineApplications() { - if(function instanceof EApply) { - EApply apply = (EApply)function; - if(Types.canonical(apply.effect) == Types.NO_EFFECTS) { - function = apply.function; - parameters = Expression.concat(apply.parameters, parameters); - } - } - } - - @Override - public Expression simplify(SimplificationContext context) { - function = function.simplify(context); - for(int i=0;i parameters) { - function.getParameters(context, parameters); - for(Expression parameter : this.parameters) - parameters.add(parameter); - } - - @Override - public void removeFreeVariables(THashSet vars) { - function.removeFreeVariables(vars); - for(Expression parameter : parameters) - parameter.removeFreeVariables(vars); - } - - @Override - public Expression replace(ReplaceContext context) { - return new EApply( - getLocation(), - effect.replace(context.tvarMap), - function.replace(context), - replace(context, parameters)); - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - function.setLocationDeep(loc); - for(Expression parameter : parameters) - parameter.setLocationDeep(loc); - } - } - - @Override - public int getFunctionDefinitionArity() throws NotPatternException { - return function.getFunctionDefinitionArity() + parameters.length; - } - - @Override - public IExpression toIExpression(ExpressionInterpretationContext target) { - IExpression[] parametersI = toIExpressions(target, parameters); - - Expression function = this.function; - while(function instanceof EApplyType) - function = ((EApplyType)function).expression; - - // Special cases - if(function instanceof EConstant) { - SCLValue functionValue = ((EConstant)function).value; - Name name = functionValue.getName(); - if(name.module.equals("Builtin")) { - IVal val = functionValue.getValue(); - if(val instanceof ListConstructor) { - if(((ListConstructor)val).arity == parametersI.length) - return new IListLiteral(parametersI); - } - } - } - //System.out.println("--> " + function + " " + function.getClass().getSimpleName()); - - // The basic case - return new IApply(function.toIExpression(target), parametersI); - } - - private void inferType(TypingContext context, boolean ignoreResult) { - function = function.inferType(context); - function = context.instantiate(function); - MultiFunction mfun; - try { - mfun = Types.unifyFunction(function.getType(), parameters.length); - } catch (UnificationException e) { - int arity = Types.getArity(function.getType()); - if(arity == 0) - context.getErrorLog().log(location, "Application of non-function."); - else - context.getErrorLog().log(location, "Function of arity " + arity + - " is applied with " + parameters.length + " parameters."); - setType(Types.metaVar(Kinds.STAR)); - for(int i=0;i=0;--i) { - Expression parameter = parameters[i]; - if(parameter.isEffectful()) { - Variable var = new Variable("aNormalTemp" + i, parameter.getType()); - expression = new ESimpleLet(var, parameter, expression); - parameters[i] = new EVariable(var); - } - } - if(function.isEffectful()) { - Variable var = new Variable("aNormalTempF", function.getType()); - expression = new ESimpleLet(var, function, expression); - function = new EVariable(var); - } - return expression; - } - - @Override - public boolean isEffectful() { - if(effect != Types.NO_EFFECTS) - return true; - for(Expression parameter : parameters) - if(parameter.isEffectful()) - return true; - if(function.isEffectful()) - return true; - return false; - } - - @Override - public boolean isFunctionPattern() { - return !isConstructorApplication(); - } - - @Override - public boolean isConstructorApplication() { - return function.isConstructorApplication(); - } - - @Override - public void collectEffects(THashSet effects) { - effects.add(effect); - function.collectEffects(effects); - for(Expression parameter : parameters) - parameter.collectEffects(effects); - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public boolean isFunctionDefinitionLhs() { - try { - EVar patternHead = function.getPatternHead(); - return !Character.isUpperCase(patternHead.name.charAt(0)); - } catch(NotPatternException e) { - return false; - } - } - - @Override - public void forVariables(VariableProcedure procedure) { - function.forVariables(procedure); - for(Expression parameter : parameters) - parameter.forVariables(procedure); - } - - @Override - public boolean isPattern(int arity) { - if(!function.isPattern(arity+parameters.length)) - return false; - for(Expression parameter : parameters) - if(!parameter.isPattern(0)) - return false; - return true; - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } -} +package org.simantics.scl.compiler.elaboration.expressions; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.constants.NoRepConstant; +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.errors.NotPatternException; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs; +import org.simantics.scl.compiler.elaboration.java.ListConstructor; +import org.simantics.scl.compiler.elaboration.macros.MacroRule; +import org.simantics.scl.compiler.elaboration.modules.SCLValue; +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.internal.interpreted.IApply; +import org.simantics.scl.compiler.internal.interpreted.IExpression; +import org.simantics.scl.compiler.internal.interpreted.IListLiteral; +import org.simantics.scl.compiler.top.ExpressionInterpretationContext; +import org.simantics.scl.compiler.types.Skeletons; +import org.simantics.scl.compiler.types.TFun; +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.exceptions.UnificationException; +import org.simantics.scl.compiler.types.kinds.Kinds; +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 EApply extends Expression { + public Expression function; + public Expression[] parameters; + Type effect = Types.NO_EFFECTS; + + public EApply(Expression function, Expression ... parameters) { + this.function = function; + this.parameters = parameters; + } + + public EApply(Expression function, Expression parameter) { + this(function, new Expression[] {parameter}); + } + + public EApply(long loc, Expression function, Expression ... parameters) { + super(loc); + this.function = function; + this.parameters = parameters; + } + + public EApply(long loc, Type effect, Expression function, Expression ... parameters) { + super(loc); + this.effect = effect; + this.function = function; + this.parameters = parameters; + } + + public void set(Expression function, Expression[] parameters) { + this.function = function; + this.parameters = parameters; + } + + public Expression getFunction() { + return function; + } + + public Expression[] getParameters() { + return parameters; + } + + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + function.collectRefs(allRefs, refs); + for(Expression parameter : parameters) + parameter.collectRefs(allRefs, refs); + } + + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + function.collectVars(allVars, vars); + for(Expression parameter : parameters) + parameter.collectVars(allVars, vars); + } + + @Override + protected void updateType() throws MatchException { + MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length); + /*for(int i=0;i vars) { + function.collectFreeVariables(vars); + for(Expression parameter : parameters) + parameter.collectFreeVariables(vars); + } + + private void combineApplications() { + if(function instanceof EApply) { + EApply apply = (EApply)function; + if(Types.canonical(apply.effect) == Types.NO_EFFECTS) { + function = apply.function; + parameters = Expression.concat(apply.parameters, parameters); + } + } + } + + @Override + public Expression simplify(SimplificationContext context) { + function = function.simplify(context); + for(int i=0;i parameters) { + function.getParameters(context, parameters); + for(Expression parameter : this.parameters) + parameters.add(parameter); + } + + @Override + public void removeFreeVariables(THashSet vars) { + function.removeFreeVariables(vars); + for(Expression parameter : parameters) + parameter.removeFreeVariables(vars); + } + + @Override + public Expression replace(ReplaceContext context) { + return new EApply( + getLocation(), + effect.replace(context.tvarMap), + function.replace(context), + replace(context, parameters)); + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + function.setLocationDeep(loc); + for(Expression parameter : parameters) + parameter.setLocationDeep(loc); + } + } + + @Override + public int getFunctionDefinitionPatternArity() throws NotPatternException { + return function.getFunctionDefinitionPatternArity() + parameters.length; + } + + @Override + public IExpression toIExpression(ExpressionInterpretationContext target) { + IExpression[] parametersI = toIExpressions(target, parameters); + + Expression function = this.function; + while(function instanceof EApplyType) + function = ((EApplyType)function).expression; + + // Special cases + if(function instanceof EConstant) { + SCLValue functionValue = ((EConstant)function).value; + Name name = functionValue.getName(); + if(name.module.equals("Builtin")) { + IVal val = functionValue.getValue(); + if(val instanceof ListConstructor) { + if(((ListConstructor)val).arity == parametersI.length) + return new IListLiteral(parametersI); + } + } + } + //System.out.println("--> " + function + " " + function.getClass().getSimpleName()); + + // The basic case + return new IApply(function.toIExpression(target), parametersI); + } + + private void inferType(TypingContext context, boolean ignoreResult) { + function = function.inferType(context); + function = context.instantiate(function); + MultiFunction mfun; + try { + mfun = Types.unifyFunction(function.getType(), parameters.length); + } catch (UnificationException e) { + int arity = Types.getArity(function.getType()); + if(arity == 0) + context.getErrorLog().log(location, "Application of non-function."); + else + context.getErrorLog().log(location, "Function of arity " + arity + + " is applied with " + parameters.length + " parameters."); + setType(Types.metaVar(Kinds.STAR)); + for(int i=0;i=0;--i) { + Expression parameter = parameters[i]; + if(parameter.isEffectful()) { + Variable var = new Variable("aNormalTemp" + i, parameter.getType()); + expression = new ESimpleLet(var, parameter, expression); + parameters[i] = new EVariable(var); + } + } + if(function.isEffectful()) { + Variable var = new Variable("aNormalTempF", function.getType()); + expression = new ESimpleLet(var, function, expression); + function = new EVariable(var); + } + return expression; + } + + @Override + public boolean isEffectful() { + if(effect != Types.NO_EFFECTS) + return true; + for(Expression parameter : parameters) + if(parameter.isEffectful()) + return true; + if(function.isEffectful()) + return true; + return false; + } + + @Override + public boolean isFunctionPattern() { + return !isConstructorApplication(); + } + + @Override + public boolean isConstructorApplication() { + return function.isConstructorApplication(); + } + + @Override + public void collectEffects(THashSet effects) { + effects.add(effect); + function.collectEffects(effects); + for(Expression parameter : parameters) + parameter.collectEffects(effects); + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public boolean isFunctionDefinitionLhs() { + try { + EVar patternHead = function.getPatternHead(); + return !Character.isUpperCase(patternHead.name.charAt(0)); + } catch(NotPatternException e) { + return false; + } + } + + @Override + public void forVariables(VariableProcedure procedure) { + function.forVariables(procedure); + for(Expression parameter : parameters) + parameter.forVariables(procedure); + } + + @Override + public boolean isPattern(int arity) { + if(!function.isPattern(arity+parameters.length)) + return false; + for(Expression parameter : parameters) + if(!parameter.isPattern(0)) + return false; + return true; + } + + @Override + 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..274624aee 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 @@ -1,240 +1,238 @@ -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.precedence.Associativity; -import org.simantics.scl.compiler.common.precedence.Precedence; -import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; -import org.simantics.scl.compiler.elaboration.errors.NotPatternException; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; -import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.errors.Locations; - - - -public class EBinary extends ASTExpression { - public static final int NEGATION_LEVEL = 6; - - public Expression left; - public ArrayList rights = new ArrayList(); - public EVar negation; - - public EBinary(Expression left, EVar negation) { - this.left = left; - this.negation = negation; - } - - private EBinary(Expression left, EVar operator, Expression right) { - this.left = left; - rights.add(new EBinaryRightSide(operator, right)); - } - - public static EBinary create(Expression left, EVar operator, Expression right) { - if(left instanceof EBinary) { - EBinary left_ = (EBinary)left; - left_.rights.add(new EBinaryRightSide(operator, right)); - return left_; - } - else - return new EBinary(left, operator, right); - } - - @Override - 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(); - ArrayList ops = new ArrayList(); - ArrayList opAsts = new ArrayList(); - - EVar negation = this.negation; - - output.add(left); - for(EBinaryRightSide right : rights) { - // Read op - Expression op = context.resolveExpression(right.operator.location, right.operator.name); - if(op == null) - return new EError(location); - Precedence opPrec = op.getPrecedence(); - while(!ops.isEmpty()) { - Expression oldOp = ops.get(ops.size()-1); - Precedence oldOpPrecedence = oldOp.getPrecedence(); - - if(oldOpPrecedence.level < opPrec.level) - break; - if(oldOpPrecedence.level == opPrec.level) { - if(opPrec.associativity == Associativity.RIGHT) - break; - if(opPrec.associativity == Associativity.NONASSOC) { - context.getErrorLog().log(right.operator.location, - "Operator " + right.operator.name + " is not associative."); - return new EError(location); - } - } - - // Pop op - ops.remove(ops.size()-1); - Expression r = output.remove(output.size()-1); - Expression l = output.remove(output.size()-1); - output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r)); - } - if(negation != null && ops.isEmpty()) { - if(opPrec.level <= NEGATION_LEVEL) { - SCLValue neg = context.getEnvironment().getValue(NEG); - if(neg == null) { - context.getErrorLog().log(location, - "Couldn't resolve variable neg."); - return new EError(location); - } - output.set(0, unary(neg, negation, output.get(0))); - negation = null; - } - } - ops.add(op); - opAsts.add(right.operator); - - // Read value - output.add(right.right); - } - - // Pop rest - while(!ops.isEmpty()) { - Expression oldOp = ops.remove(ops.size()-1); - Expression r = output.remove(output.size()-1); - Expression l = output.remove(output.size()-1); - output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r)); - } - if(negation != null) { - SCLValue neg = context.getEnvironment().getValue(NEG); - if(neg == null) { - context.getErrorLog().log(location, - "Couldn't resolve variable neg."); - return new EError(location); - } - output.set(0, unary(neg, negation, output.get(0))); - } - - return output.get(0); - - //System.out.println("parseOperators: " + this); - //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC)); - } - - /* - private Expression parse(TranslationContext context, - Expression lhs, ListIterator it, Precedence minPrec) { - while(it.hasNext()) { - EBinaryRightSide right = it.next(); - SCLValue op = context.resolveValue(right.operator.name); - if(op == null) { - context.getErrorLog().log(right.operator, - "Couldn't resolve variable " + right.operator.name + "."); - return lhs; - } - Precedence opPrec = op.getPrecedence(); - if(minPrec.level > opPrec.level) - break; - Expression rhs = right.right; - while(it.hasNext()) { - EVar var = it.next().operator; - SCLValue nextOp = context.resolveValue(var.name); - if(nextOp == null) { - context.getErrorLog().log(var, - "Couldn't resolve variable " + var.name + "."); - return lhs; - } - it.previous(); - Precedence nextPrec = nextOp.getPrecedence(); - int precDiff = opPrec.level - nextPrec.level; - if(precDiff == 0) { - if(opPrec.associativity == Associativity.LEFT) - break; - else if(opPrec.associativity == Associativity.NONASSOC) { - context.getErrorLog().log(it.next().operator, "Nonassociative operator."); - return lhs; - } - } - else if(precDiff > 0) - break; - rhs = parse(context, rhs, it, nextPrec); - } - lhs = binary(lhs, op, right.operator, rhs); - } - return lhs; - } - */ - private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) { - return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs); - } - - private Expression unary(SCLValue operator, EVar opAst, Expression expression) { - EConstant op = new EConstant(opAst.location, operator); - return new EApply(expression.location /*wrong*/, op, expression); - } - - @Override - public EVar getPatternHead() throws NotPatternException { - if(rights.size() == 1) - return rights.get(0).operator; - else - throw new NotPatternException(this); - } - - @Override - public LhsType getLhsType() throws NotPatternException { - if(rights.size() == 1) - return new FunctionDefinitionLhs(rights.get(0).operator.name); - else - throw new InternalCompilerError(); - } - - @Override - public void getParameters(TranslationContext context, - ArrayList parameters) { - parseOperators(context).getParameters(context, parameters); - } - - public static Expression negate(EVar op, Expression expression) { - if(expression instanceof EBinary) { - ((EBinary)expression).negation = op; - return expression; - } - /*else if(expression instanceof EIntegerLiteral) { - EIntegerLiteral literal = (EIntegerLiteral)expression; - literal.value = -literal.value; - return expression; - }*/ - else - return new EBinary(expression, op); - } - - @Override - public int getFunctionDefinitionArity() throws NotPatternException { - return 2; - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - left.setLocationDeep(loc); - if(negation != null) - negation.setLocationDeep(loc); - for(EBinaryRightSide right : rights) - right.setLocationDeep(loc); - } - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +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.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; +import org.simantics.scl.compiler.elaboration.errors.NotPatternException; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; +import org.simantics.scl.compiler.elaboration.modules.SCLValue; +import org.simantics.scl.compiler.errors.Locations; + + + +public class EBinary extends ASTExpression { + public static final int NEGATION_LEVEL = 6; + + public Expression left; + public ArrayList rights = new ArrayList(); + public EVar negation; + + public EBinary(Expression left, EVar negation) { + this.left = left; + this.negation = negation; + } + + private EBinary(Expression left, EVar operator, Expression right) { + this.left = left; + rights.add(new EBinaryRightSide(operator, right)); + } + + public static EBinary create(Expression left, EVar operator, Expression right) { + if(left instanceof EBinary) { + EBinary left_ = (EBinary)left; + left_.rights.add(new EBinaryRightSide(operator, right)); + return left_; + } + else + return new EBinary(left, operator, right); + } + + @Override + public Expression resolve(TranslationContext context) { + return parseOperators(context).resolve(context); + } + + public Expression parseOperators(TranslationContext context) { + ArrayList output = new ArrayList(); + ArrayList ops = new ArrayList(); + ArrayList opAsts = new ArrayList(); + + EVar negation = this.negation; + + output.add(left); + for(EBinaryRightSide right : rights) { + // Read op + Expression op = context.resolveExpression(right.operator.location, right.operator.name); + if(op == null) + return new EError(location); + Precedence opPrec = op.getPrecedence(); + while(!ops.isEmpty()) { + Expression oldOp = ops.get(ops.size()-1); + Precedence oldOpPrecedence = oldOp.getPrecedence(); + + if(oldOpPrecedence.level < opPrec.level) + break; + if(oldOpPrecedence.level == opPrec.level) { + if(opPrec.associativity == Associativity.RIGHT) + break; + if(opPrec.associativity == Associativity.NONASSOC) { + context.getErrorLog().log(right.operator.location, + "Operator " + right.operator.name + " is not associative."); + return new EError(location); + } + } + + // Pop op + ops.remove(ops.size()-1); + Expression r = output.remove(output.size()-1); + Expression l = output.remove(output.size()-1); + output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r)); + } + if(negation != null && ops.isEmpty()) { + if(opPrec.level <= NEGATION_LEVEL) { + SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg); + if(neg == null) { + context.getErrorLog().log(location, + "Couldn't resolve variable neg."); + return new EError(location); + } + output.set(0, unary(neg, negation, output.get(0))); + negation = null; + } + } + ops.add(op); + opAsts.add(right.operator); + + // Read value + output.add(right.right); + } + + // Pop rest + while(!ops.isEmpty()) { + Expression oldOp = ops.remove(ops.size()-1); + Expression r = output.remove(output.size()-1); + Expression l = output.remove(output.size()-1); + output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r)); + } + if(negation != null) { + SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg); + if(neg == null) { + context.getErrorLog().log(location, + "Couldn't resolve variable neg."); + return new EError(location); + } + output.set(0, unary(neg, negation, output.get(0))); + } + + return output.get(0); + + //System.out.println("parseOperators: " + this); + //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC)); + } + + /* + private Expression parse(TranslationContext context, + Expression lhs, ListIterator it, Precedence minPrec) { + while(it.hasNext()) { + EBinaryRightSide right = it.next(); + SCLValue op = context.resolveValue(right.operator.name); + if(op == null) { + context.getErrorLog().log(right.operator, + "Couldn't resolve variable " + right.operator.name + "."); + return lhs; + } + Precedence opPrec = op.getPrecedence(); + if(minPrec.level > opPrec.level) + break; + Expression rhs = right.right; + while(it.hasNext()) { + EVar var = it.next().operator; + SCLValue nextOp = context.resolveValue(var.name); + if(nextOp == null) { + context.getErrorLog().log(var, + "Couldn't resolve variable " + var.name + "."); + return lhs; + } + it.previous(); + Precedence nextPrec = nextOp.getPrecedence(); + int precDiff = opPrec.level - nextPrec.level; + if(precDiff == 0) { + if(opPrec.associativity == Associativity.LEFT) + break; + else if(opPrec.associativity == Associativity.NONASSOC) { + context.getErrorLog().log(it.next().operator, "Nonassociative operator."); + return lhs; + } + } + else if(precDiff > 0) + break; + rhs = parse(context, rhs, it, nextPrec); + } + lhs = binary(lhs, op, right.operator, rhs); + } + return lhs; + } + */ + private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) { + return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs); + } + + private Expression unary(SCLValue operator, EVar opAst, Expression expression) { + EConstant op = new EConstant(opAst.location, operator); + return new EApply(expression.location /*wrong*/, op, expression); + } + + @Override + public EVar getPatternHead() throws NotPatternException { + if(rights.size() == 1) + return rights.get(0).operator; + else + throw new NotPatternException(this); + } + + @Override + public LhsType getLhsType() throws NotPatternException { + if(rights.size() == 1) + return new FunctionDefinitionLhs(rights.get(0).operator.name); + else + throw new InternalCompilerError(); + } + + @Override + public void getParameters(TranslationContext context, + ArrayList parameters) { + parseOperators(context).getParameters(context, parameters); + } + + public static Expression negate(EVar op, Expression expression) { + if(expression instanceof EBinary) { + ((EBinary)expression).negation = op; + return expression; + } + /*else if(expression instanceof EIntegerLiteral) { + EIntegerLiteral literal = (EIntegerLiteral)expression; + literal.value = -literal.value; + return expression; + }*/ + else + return new EBinary(expression, op); + } + + @Override + public int getFunctionDefinitionPatternArity() throws NotPatternException { + return 2; + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + left.setLocationDeep(loc); + if(negation != null) + negation.setLocationDeep(loc); + for(EBinaryRightSide right : rights) + right.setLocationDeep(loc); + } + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + +} 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..ebe88b499 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..e3bb2fe0a 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 @@ -1,191 +1,199 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.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 gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class EIf extends Expression { - public Expression condition; - public Expression then_; - public Expression else_; - - public EIf(Expression condition, Expression then_, Expression else_) { - this.condition = condition; - this.then_ = then_; - this.else_ = else_; - } - - public EIf(long loc, Expression condition, Expression then_, Expression else_) { - super(loc); - this.condition = condition; - this.then_ = then_; - this.else_ = else_; - } - - public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { - condition.collectRefs(allRefs, refs); - then_.collectRefs(allRefs, refs); - else_.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - condition.collectVars(allVars, vars); - then_.collectVars(allVars, vars); - else_.collectVars(allVars, vars); - } - - @Override - protected void updateType() throws MatchException { - setType(then_.getType()); - } - - @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()); - - 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]; - } - - @Override - public void collectFreeVariables(THashSet vars) { - condition.collectFreeVariables(vars); - then_.collectFreeVariables(vars); - else_.collectFreeVariables(vars); - } - - @Override - public Expression simplify(SimplificationContext context) { - condition = condition.simplify(context); - then_ = then_.simplify(context); - else_ = else_.simplify(context); - return this; - } - - @Override - public Expression resolve(TranslationContext context) { - condition = condition.resolve(context); - then_ = then_.resolve(context); - else_ = else_.resolve(context); - return this; - } - - @Override - public Expression replace(ReplaceContext context) { - return new EIf(condition.replace(context), - then_.replace(context), - 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); - return this; - } - - @Override - public Expression checkIgnoredType(TypingContext context) { - condition = condition.checkType(context, Types.BOOLEAN); - then_ = then_.checkIgnoredType(context); - else_ = else_.checkIgnoredType(context); - return this; - } - - @Override - public Expression decorate(ExpressionDecorator decorator) { - condition = condition.decorate(decorator); - then_ = then_.decorate(decorator); - else_ = else_.decorate(decorator); - return decorator.decorate(this); - } - - @Override - public boolean isEffectful() { - return condition.isEffectful() || then_.isEffectful() || else_.isEffectful(); - } - - @Override - public void collectEffects(THashSet effects) { - condition.collectEffects(effects); - then_.collectEffects(effects); - else_.collectEffects(effects); - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - condition.setLocationDeep(loc); - then_.setLocationDeep(loc); - else_.setLocationDeep(loc); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - @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_; - } - - @Override - public void forVariables(VariableProcedure procedure) { - condition.forVariables(procedure); - then_.forVariables(procedure); - else_.forVariables(procedure); - } - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.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; +import gnu.trove.set.hash.TIntHashSet; + +public class EIf extends Expression { + public Expression condition; + public Expression then_; + public Expression else_; // may be null + + public EIf(Expression condition, Expression then_, Expression else_) { + this.condition = condition; + this.then_ = then_; + this.else_ = else_; + } + + public EIf(long loc, Expression condition, Expression then_, Expression else_) { + super(loc); + this.condition = condition; + this.then_ = then_; + this.else_ = else_; + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + condition.collectRefs(allRefs, refs); + then_.collectRefs(allRefs, refs); + if(else_ != null) + else_.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + condition.collectVars(allVars, vars); + then_.collectVars(allVars, vars); + if(else_ != null) + else_.collectVars(allVars, vars); + } + + @Override + protected void updateType() throws MatchException { + setType(then_.getType()); + } + + @Override + public IVal toVal(Environment env, CodeWriter w) { + IVal conditionVal = condition.toVal(env, w); + CodeWriter joinPoint = w.createBlock(getType()); + 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); + w.continueAs(joinPoint); + + return w.getParameters()[0]; + } + + @Override + public void collectFreeVariables(THashSet vars) { + condition.collectFreeVariables(vars); + then_.collectFreeVariables(vars); + if(else_ != null) + else_.collectFreeVariables(vars); + } + + @Override + public Expression simplify(SimplificationContext context) { + condition = condition.simplify(context); + then_ = then_.simplify(context); + if(else_ != null) + else_ = else_.simplify(context); + return this; + } + + @Override + public Expression resolve(TranslationContext context) { + condition = condition.resolve(context); + then_ = then_.resolve(context); + if(else_ != null) + else_ = else_.resolve(context); + return this; + } + + @Override + public Expression replace(ReplaceContext context) { + return new EIf(condition.replace(context), + then_.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); + 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; + } + + @Override + public Expression checkIgnoredType(TypingContext context) { + condition = condition.checkType(context, Types.BOOLEAN); + then_ = then_.checkIgnoredType(context); + if(else_ != null) + else_ = else_.checkIgnoredType(context); + return this; + } + + @Override + public Expression decorate(ExpressionDecorator decorator) { + condition = condition.decorate(decorator); + then_ = then_.decorate(decorator); + if(else_ != null) + else_ = else_.decorate(decorator); + return decorator.decorate(this); + } + + @Override + public boolean isEffectful() { + return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful()); + } + + @Override + public void collectEffects(THashSet effects) { + condition.collectEffects(effects); + then_.collectEffects(effects); + if(else_ != null) + else_.collectEffects(effects); + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + condition.setLocationDeep(loc); + then_.setLocationDeep(loc); + if(else_ != null) + else_.setLocationDeep(loc); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public IExpression toIExpression(ExpressionInterpretationContext target) { + 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); + if(else_ != null) + else_.forVariables(procedure); + } + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity()); + } +} 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/ELambda.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambda.java index abf4c89da..67a7e1476 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambda.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambda.java @@ -1,215 +1,223 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.errors.Locations; -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.exceptions.UnificationException; -import org.simantics.scl.compiler.types.kinds.Kinds; -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 ELambda extends SimplifiableExpression { - public Case[] cases; - Type effect = Types.NO_EFFECTS; - - public ELambda(Case[] cases) { - this.cases = cases; - } - - public ELambda(Case case_) { - this(new Case[] {case_}); - } - - public ELambda(long loc, Case ... cases) { - super(loc); - this.cases = cases; - } - - public ELambda(long loc, Expression pat, Expression exp) { - this(loc, new Case(new Expression[] {pat}, exp)); - } - - public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { - for(Case case_ : cases) - case_.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - for(Case case_ : cases) - case_.collectVars(allVars, vars); - } - - public Expression decomposeMatching() { - Expression[] patterns = cases[0].patterns; - int arity = patterns.length; - - // Simple cases - if(cases.length == 1 && - !(cases[0].value instanceof GuardedExpressionGroup)) { - boolean noMatchingNeeded = true; - for(int i=0;i=0;--i) { - Variable var = ((EVariable)patterns[i]).getVariable(); - decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed); - effect = Types.NO_EFFECTS; - } - return decomposed; - } - } - - // Complex case - Variable[] vars = new Variable[arity]; - Expression[] scrutinee = new Expression[arity]; - for(int i=0;i=0;--i) { - decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed); - curEffect = Types.NO_EFFECTS; - } - return decomposed; - } - - @Override - protected void updateType() throws MatchException { - setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType())); - } - - @Override - public Expression simplify(SimplificationContext context) { - return decomposeMatching().simplify(context); - } - - @Override - public void collectFreeVariables(THashSet vars) { - for(Case case_ : cases) - case_.collectFreeVariables(vars); - } - - @Override - public Expression resolve(TranslationContext context) { - for(Case case_ : cases) - case_.resolve(context); - return this; - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - for(Case case_ : cases) - case_.setLocationDeep(loc); - } - } - - @Override - public Expression replace(ReplaceContext context) { - Case[] newCases = new Case[cases.length]; - for(int i=0;i effects) { - for(Case case_ : cases) { - for(Expression pattern : case_.patterns) - pattern.collectEffects(effects); - case_.value.collectEffects(effects); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public void forVariables(VariableProcedure procedure) { - for(Case case_ : cases) - case_.forVariables(procedure); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.errors.Locations; +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.exceptions.UnificationException; +import org.simantics.scl.compiler.types.kinds.Kinds; +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 ELambda extends SimplifiableExpression { + public Case[] cases; + Type effect = Types.NO_EFFECTS; + + public ELambda(Case[] cases) { + this.cases = cases; + } + + public ELambda(Case case_) { + this(new Case[] {case_}); + } + + public ELambda(long loc, Case ... cases) { + super(loc); + this.cases = cases; + } + + public ELambda(long loc, Expression pat, Expression exp) { + this(loc, new Case(new Expression[] {pat}, exp)); + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + for(Case case_ : cases) + case_.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + for(Case case_ : cases) + case_.collectVars(allVars, vars); + } + + public Expression decomposeMatching() { + Expression[] patterns = cases[0].patterns; + int arity = patterns.length; + + // Simple cases + if(cases.length == 1 && + !(cases[0].value instanceof GuardedExpressionGroup)) { + boolean noMatchingNeeded = true; + for(int i=0;i=0;--i) { + Variable var = ((EVariable)patterns[i]).getVariable(); + decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed); + effect = Types.NO_EFFECTS; + } + return decomposed; + } + } + + // Complex case + Variable[] vars = new Variable[arity]; + Expression[] scrutinee = new Expression[arity]; + for(int i=0;i=0;--i) { + decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed); + curEffect = Types.NO_EFFECTS; + } + return decomposed; + } + + @Override + protected void updateType() throws MatchException { + setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType())); + } + + @Override + public Expression simplify(SimplificationContext context) { + return decomposeMatching().simplify(context); + } + + @Override + public void collectFreeVariables(THashSet vars) { + for(Case case_ : cases) + case_.collectFreeVariables(vars); + } + + @Override + public Expression resolve(TranslationContext context) { + for(Case case_ : cases) + case_.resolve(context); + return this; + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + for(Case case_ : cases) + case_.setLocationDeep(loc); + } + } + + @Override + public Expression replace(ReplaceContext context) { + Case[] newCases = new Case[cases.length]; + for(int i=0;i effects) { + for(Case case_ : cases) { + for(Expression pattern : case_.patterns) + pattern.collectEffects(effects); + case_.value.collectEffects(effects); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public void forVariables(VariableProcedure procedure) { + for(Case case_ : cases) + case_.forVariables(procedure); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + int result = 0; + for(Case case_ : cases) + result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity()); + return result; + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambdaType.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambdaType.java index 8e9a74cd5..08e47bf95 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambdaType.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambdaType.java @@ -1,129 +1,134 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.internal.interpreted.IExpression; -import org.simantics.scl.compiler.top.ExpressionInterpretationContext; -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.exceptions.MatchException; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class ELambdaType extends Expression { - public TVar[] parameters; - public Expression value; - - public ELambdaType(TVar[] parameters, Expression value) { - super(value.getLocation()); - this.parameters = parameters; - this.value = value; - } - - public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { - value.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - value.collectVars(allVars, vars); - } - - @Override - protected void updateType() throws MatchException { - setType(Types.forAll(parameters, value.getType())); - } - - @Override - public IVal toVal(Environment env, CodeWriter w) { - return lambdaToVal(env, w); - } - - @Override - public void collectFreeVariables(THashSet vars) { - value.collectFreeVariables(vars); - } - - @Override - public Expression simplify(SimplificationContext context) { - value = value.simplify(context); - return this; - } - - @Override - public Expression resolve(TranslationContext context) { - value = value.resolve(context); - return this; - } - - @Override - public Expression replace(ReplaceContext context) { - TVar[] newParameters = new TVar[parameters.length]; - for(int i=0;i effects) { - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - value.setLocationDeep(loc); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public void forVariables(VariableProcedure procedure) { - value.forVariables(procedure); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.internal.interpreted.IExpression; +import org.simantics.scl.compiler.top.ExpressionInterpretationContext; +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.exceptions.MatchException; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class ELambdaType extends Expression { + public TVar[] parameters; + public Expression value; + + public ELambdaType(TVar[] parameters, Expression value) { + super(value.getLocation()); + this.parameters = parameters; + this.value = value; + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + value.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + value.collectVars(allVars, vars); + } + + @Override + protected void updateType() throws MatchException { + setType(Types.forAll(parameters, value.getType())); + } + + @Override + public IVal toVal(Environment env, CodeWriter w) { + return lambdaToVal(env, w); + } + + @Override + public void collectFreeVariables(THashSet vars) { + value.collectFreeVariables(vars); + } + + @Override + public Expression simplify(SimplificationContext context) { + value = value.simplify(context); + return this; + } + + @Override + public Expression resolve(TranslationContext context) { + value = value.resolve(context); + return this; + } + + @Override + public Expression replace(ReplaceContext context) { + TVar[] newParameters = new TVar[parameters.length]; + for(int i=0;i effects) { + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + value.setLocationDeep(loc); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public void forVariables(VariableProcedure procedure) { + value.forVariables(procedure); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + return value.getSyntacticFunctionArity(); + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java index bbbc25c4d..d10066f90 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java @@ -1,257 +1,262 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import java.util.ArrayList; - -import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.BoundVar; -import org.simantics.scl.compiler.internal.codegen.references.IVal; -import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; -import org.simantics.scl.compiler.internal.codegen.writer.RecursiveDefinitionWriter; -import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression; -import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; -import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents; -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.kinds.Kinds; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class ELet extends Expression { - public Assignment[] assignments; - public Expression in; - - public ELet(long loc, Assignment[] assignments, Expression in) { - super(loc); - this.assignments = assignments; - this.in = in; - } - - @Override - public void collectRefs(final TObjectIntHashMap allRefs, final TIntHashSet refs) { - for(Assignment assign : assignments) - assign.value.collectRefs(allRefs, refs); - in.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - for(Assignment assign : assignments) - assign.value.collectVars(allVars, vars); - in.collectVars(allVars, vars); - } - - @Override - protected void updateType() throws MatchException { - setType(in.getType()); - } - - /** - * Splits let - */ - @Override - public Expression simplify(SimplificationContext context) { - - // Simplify assignments - for(Assignment assignment : assignments) { - assignment.value = assignment.value.simplify(context); - } - - // Find strongly connected components - final TObjectIntHashMap allVars = new TObjectIntHashMap( - 2*assignments.length, 0.5f, -1); - - for(int i=0;i components = new ArrayList(Math.max(10, assignments.length)); - new StronglyConnectedComponents(assignments.length) { - @Override - protected int[] findDependencies(int u) { - TIntHashSet vars = new TIntHashSet(); - assignments[u].value.collectVars(allVars, vars); - if(vars.contains(u)) - isRecursive[u] = true; - return vars.toArray(); - } - - @Override - protected void reportComponent(int[] component) { - components.add(component); - } - - }.findComponents(); - - // Simplify in - Expression result = in.simplify(context); - - // Handle each component - for(int j=components.size()-1;j>=0;--j) { - int[] component = components.get(j); - boolean recursive = component.length > 1 || isRecursive[component[0]]; - if(recursive) { - Assignment[] cAssignments = new Assignment[component.length]; - for(int i=0;i vars) { - in.collectFreeVariables(vars); - for(Assignment assign : assignments) - assign.value.collectFreeVariables(vars); - for(Assignment assign : assignments) - assign.pattern.removeFreeVariables(vars); - } - - @Override - public Expression resolve(TranslationContext context) { - throw new InternalCompilerError("ELet should be already resolved."); - } - - @Override - public Expression replace(ReplaceContext context) { - Assignment[] newAssignments = new Assignment[assignments.length]; - for(int i=0;i effects) { - for(Assignment assignment : assignments) { - assignment.pattern.collectEffects(effects); - assignment.value.collectEffects(effects); - } - in.collectEffects(effects); - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - for(Assignment assignment : assignments) - assignment.setLocationDeep(loc); - in.setLocationDeep(loc); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public void forVariables(VariableProcedure procedure) { - for(Assignment assignment : assignments) - assignment.forVariables(procedure); - in.forVariables(procedure); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.BoundVar; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; +import org.simantics.scl.compiler.internal.codegen.writer.RecursiveDefinitionWriter; +import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression; +import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; +import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents; +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.kinds.Kinds; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class ELet extends Expression { + public Assignment[] assignments; + public Expression in; + + public ELet(long loc, Assignment[] assignments, Expression in) { + super(loc); + this.assignments = assignments; + this.in = in; + } + + @Override + public void collectRefs(final TObjectIntHashMap allRefs, final TIntHashSet refs) { + for(Assignment assign : assignments) + assign.value.collectRefs(allRefs, refs); + in.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + for(Assignment assign : assignments) + assign.value.collectVars(allVars, vars); + in.collectVars(allVars, vars); + } + + @Override + protected void updateType() throws MatchException { + setType(in.getType()); + } + + /** + * Splits let + */ + @Override + public Expression simplify(SimplificationContext context) { + + // Simplify assignments + for(Assignment assignment : assignments) { + assignment.value = assignment.value.simplify(context); + } + + // Find strongly connected components + final TObjectIntHashMap allVars = new TObjectIntHashMap( + 2*assignments.length, 0.5f, -1); + + for(int i=0;i components = new ArrayList(Math.max(10, assignments.length)); + new StronglyConnectedComponents(assignments.length) { + @Override + protected int[] findDependencies(int u) { + TIntHashSet vars = new TIntHashSet(); + assignments[u].value.collectVars(allVars, vars); + if(vars.contains(u)) + isRecursive[u] = true; + return vars.toArray(); + } + + @Override + protected void reportComponent(int[] component) { + components.add(component); + } + + }.findComponents(); + + // Simplify in + Expression result = in.simplify(context); + + // Handle each component + for(int j=components.size()-1;j>=0;--j) { + int[] component = components.get(j); + boolean recursive = component.length > 1 || isRecursive[component[0]]; + if(recursive) { + Assignment[] cAssignments = new Assignment[component.length]; + for(int i=0;i vars) { + in.collectFreeVariables(vars); + for(Assignment assign : assignments) + assign.value.collectFreeVariables(vars); + for(Assignment assign : assignments) + assign.pattern.removeFreeVariables(vars); + } + + @Override + public Expression resolve(TranslationContext context) { + throw new InternalCompilerError("ELet should be already resolved."); + } + + @Override + public Expression replace(ReplaceContext context) { + Assignment[] newAssignments = new Assignment[assignments.length]; + for(int i=0;i effects) { + for(Assignment assignment : assignments) { + assignment.pattern.collectEffects(effects); + assignment.value.collectEffects(effects); + } + in.collectEffects(effects); + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + for(Assignment assignment : assignments) + assignment.setLocationDeep(loc); + in.setLocationDeep(loc); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public void forVariables(VariableProcedure procedure) { + for(Assignment assignment : assignments) + assignment.forVariables(procedure); + in.forVariables(procedure); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + return in.getSyntacticFunctionArity(); + } + +} 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/EMatch.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EMatch.java index 11877a60e..d1a96d04a 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EMatch.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EMatch.java @@ -1,213 +1,220 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import java.util.ArrayList; - -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.ssa.exits.Throw; -import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; -import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler; -import org.simantics.scl.compiler.internal.elaboration.matching.Row; -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.kinds.Kinds; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class EMatch extends Expression { - - public Expression[] scrutinee; - public Case[] cases; - - public EMatch(Expression[] scrutinee, Case ... cases) { - this.scrutinee = scrutinee; - this.cases = cases; - } - - public EMatch(Expression scrutinee, Case ... cases) { - this(new Expression[] {scrutinee}, cases); - } - - public EMatch(long loc, Expression[] scrutinee, Case ... cases) { - super(loc); - this.scrutinee = scrutinee; - this.cases = cases; - } - - public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { - for(Expression s : scrutinee) - s.collectRefs(allRefs, refs); - for(Case case_ : cases) - case_.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - for(Expression s : scrutinee) - s.collectVars(allVars, vars); - for(Case case_ : cases) - case_.collectVars(allVars, vars); - } - - @Override - protected void updateType() { - setType(cases[0].value.getType()); - } - - @Override - public IVal toVal(Environment env, CodeWriter w) { - ArrayList rows = new ArrayList(cases.length); - for(Case case_ : cases) - rows.add(new Row(case_.patterns, case_.value)); - - IVal[] scrutineeVals = new IVal[scrutinee.length]; - for(int i=0;i vars) { - for(Expression s : scrutinee) - s.collectFreeVariables(vars); - for(Case case_ : cases) - case_.collectFreeVariables(vars); - } - - @Override - public Expression simplify(SimplificationContext context) { - for(int i=0;i effects) { - for(Expression s : scrutinee) - s.collectEffects(effects); - for(Case case_ : cases) { - for(Expression pattern : case_.patterns) - pattern.collectEffects(effects); - case_.value.collectEffects(effects); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - public Expression[] getScrutinee() { - return scrutinee; - } - - public Case[] getCases() { - return cases; - } - - @Override - public void forVariables(VariableProcedure procedure) { - for(Expression s : scrutinee) - s.forVariables(procedure); - for(Case case_ : cases) - case_.forVariables(procedure); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.ssa.exits.Throw; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; +import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler; +import org.simantics.scl.compiler.internal.elaboration.matching.Row; +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.kinds.Kinds; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class EMatch extends Expression { + + public Expression[] scrutinee; + public Case[] cases; + + public EMatch(Expression[] scrutinee, Case ... cases) { + this.scrutinee = scrutinee; + this.cases = cases; + } + + public EMatch(Expression scrutinee, Case ... cases) { + this(new Expression[] {scrutinee}, cases); + } + + public EMatch(long loc, Expression[] scrutinee, Case ... cases) { + super(loc); + this.scrutinee = scrutinee; + this.cases = cases; + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + for(Expression s : scrutinee) + s.collectRefs(allRefs, refs); + for(Case case_ : cases) + case_.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + for(Expression s : scrutinee) + s.collectVars(allVars, vars); + for(Case case_ : cases) + case_.collectVars(allVars, vars); + } + + @Override + protected void updateType() { + setType(cases[0].value.getType()); + } + + @Override + public IVal toVal(Environment env, CodeWriter w) { + ArrayList rows = new ArrayList(cases.length); + for(Case case_ : cases) + rows.add(new Row(case_.patterns, case_.value)); + + IVal[] scrutineeVals = new IVal[scrutinee.length]; + for(int i=0;i vars) { + for(Expression s : scrutinee) + s.collectFreeVariables(vars); + for(Case case_ : cases) + case_.collectFreeVariables(vars); + } + + @Override + public Expression simplify(SimplificationContext context) { + for(int i=0;i effects) { + for(Expression s : scrutinee) + s.collectEffects(effects); + for(Case case_ : cases) { + for(Expression pattern : case_.patterns) + pattern.collectEffects(effects); + case_.value.collectEffects(effects); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + public Expression[] getScrutinee() { + return scrutinee; + } + + public Case[] getCases() { + return cases; + } + + @Override + public void forVariables(VariableProcedure procedure) { + for(Expression s : scrutinee) + s.forVariables(procedure); + for(Case case_ : cases) + case_.forVariables(procedure); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + int result = 0; + for(Case case_ : cases) + result = Math.max(result, case_.value.getSyntacticFunctionArity()); + return result; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java index 8d8883eae..c78b9f457 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java @@ -1,97 +1,102 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import java.util.ArrayList; -import java.util.List; - -import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; -import org.simantics.scl.compiler.elaboration.errors.NotPatternException; -import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; -import org.simantics.scl.compiler.errors.Locations; - -import gnu.trove.map.hash.THashMap; -import gnu.trove.procedure.TObjectObjectProcedure; - -public class EPreLet extends ASTExpression { - - List assignments; - Expression in; - - public EPreLet(List assignments, Expression in) { - this.assignments = assignments; - this.in = in; - } - - @Override - public Expression resolve(final TranslationContext context) { - context.pushFrame(); - THashMap> functionDefinitions = - new THashMap>(); - ArrayList otherDefinitions = new ArrayList(); - final THashMap localVars = new THashMap(); - try { - for(LetStatement assign : assignments) { - LhsType lhsType = assign.pattern.getLhsType(); - if(!(assign.pattern instanceof EVar) && lhsType instanceof FunctionDefinitionLhs) { - String name = ((FunctionDefinitionLhs)lhsType).functionName; - ArrayList group = functionDefinitions.get(name); - if(group == null) { - group = new ArrayList(2); - functionDefinitions.put(name, group); - } - group.add(assign); - localVars.put(name, context.newVariable(name)); - } - else { - otherDefinitions.add(assign); - assign.pattern = assign.pattern.resolveAsPattern(context); - } - } - } catch (NotPatternException e) { - context.getErrorLog().log(e.getExpression().location, "Not a pattern."); - return new EError(); - } - - final ArrayList as = new ArrayList(functionDefinitions.size() + otherDefinitions.size()); - functionDefinitions.forEachEntry(new TObjectObjectProcedure>() { - @Override - public boolean execute(String name, ArrayList cases) { - as.add(new Assignment( - new EVariable(cases.size()==1 ? cases.get(0).pattern.location : location, localVars.get(name)), - context.translateCases(cases))); - return true; - } - }); - for(LetStatement stat : otherDefinitions) - as.add(new Assignment( - stat.pattern /* already resolved above */, - stat.value.resolve(context))); - Expression inExpr = in.resolve(context); - context.popFrame(); - - ELet result = new ELet(location, as.toArray(new Assignment[as.size()]), inExpr); - /*System.out.println("-----------------------------------------"); - System.out.println(this); - System.out.println("-----------------------------------------"); - System.out.println(result); - System.out.println("-----------------------------------------");*/ - return result; - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - for(LetStatement assignment : assignments) - assignment.setLocationDeep(loc); - in.setLocationDeep(loc); - } - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import java.util.ArrayList; +import java.util.List; + +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.errors.NotPatternException; +import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; +import org.simantics.scl.compiler.errors.Locations; + +import gnu.trove.map.hash.THashMap; +import gnu.trove.procedure.TObjectObjectProcedure; + +public class EPreLet extends ASTExpression { + + List assignments; + Expression in; + + public EPreLet(List assignments, Expression in) { + this.assignments = assignments; + this.in = in; + } + + @Override + public Expression resolve(final TranslationContext context) { + context.pushFrame(); + THashMap> functionDefinitions = + new THashMap>(); + ArrayList otherDefinitions = new ArrayList(); + final THashMap localVars = new THashMap(); + try { + for(LetStatement assign : assignments) { + LhsType lhsType = assign.pattern.getLhsType(); + if(!(assign.pattern instanceof EVar) && lhsType instanceof FunctionDefinitionLhs) { + String name = ((FunctionDefinitionLhs)lhsType).functionName; + ArrayList group = functionDefinitions.get(name); + if(group == null) { + group = new ArrayList(2); + functionDefinitions.put(name, group); + } + group.add(assign); + localVars.put(name, context.newVariable(name)); + } + else { + otherDefinitions.add(assign); + assign.pattern = assign.pattern.resolveAsPattern(context); + } + } + } catch (NotPatternException e) { + context.getErrorLog().log(e.getExpression().location, "Not a pattern."); + return new EError(); + } + + final ArrayList as = new ArrayList(functionDefinitions.size() + otherDefinitions.size()); + functionDefinitions.forEachEntry(new TObjectObjectProcedure>() { + @Override + public boolean execute(String name, ArrayList cases) { + as.add(new Assignment( + new EVariable(cases.size()==1 ? cases.get(0).pattern.location : location, localVars.get(name)), + context.translateCases(cases))); + return true; + } + }); + for(LetStatement stat : otherDefinitions) + as.add(new Assignment( + stat.pattern /* already resolved above */, + stat.value.resolve(context))); + Expression inExpr = in.resolve(context); + context.popFrame(); + + ELet result = new ELet(location, as.toArray(new Assignment[as.size()]), inExpr); + /*System.out.println("-----------------------------------------"); + System.out.println(this); + System.out.println("-----------------------------------------"); + System.out.println(result); + System.out.println("-----------------------------------------");*/ + return result; + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + for(LetStatement assignment : assignments) + assignment.setLocationDeep(loc); + in.setLocationDeep(loc); + } + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + return in.getSyntacticFunctionArity(); + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreRuleset.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreRuleset.java index 74f24ebb8..41880a022 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreRuleset.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreRuleset.java @@ -1,83 +1,88 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; -import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule; -import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement; -import org.simantics.scl.compiler.elaboration.relations.LocalRelation; -import org.simantics.scl.compiler.errors.Locations; - -import gnu.trove.map.hash.THashMap; - -public class EPreRuleset extends ASTExpression { - - RuleStatement[] statements; - Expression in; - - public EPreRuleset(RuleStatement[] statements, Expression in) { - this.statements = statements; - this.in = in; - } - - @Override - public Expression resolve(TranslationContext context) { - THashMap relations = new THashMap(); - DatalogRule[] rules = new DatalogRule[statements.length]; - context.pushRelationFrame(); - try { - for(int i=0;i relations = new THashMap(); + DatalogRule[] rules = new DatalogRule[statements.length]; + context.pushRelationFrame(); + try { + for(int i=0;i 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 allRefs, TIntHashSet refs) { - value.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - value.collectVars(allVars, vars); - } - - public Expression decomposeMatching() { - value = value.decomposeMatching(); - return this; - } - - @Override - protected void updateType() throws MatchException { - setType(Types.functionE(Types.canonical(parameter.type), - effect, value.getType())); - } - - @Override - public IVal toVal(Environment env, CodeWriter w) { - return lambdaToVal(env, w); - } - - @Override - public void collectFreeVariables(THashSet vars) { - value.collectFreeVariables(vars); - vars.remove(parameter); - } - - @Override - public Expression simplify(SimplificationContext context) { - value = value.simplify(context); - return this; - } - - @Override - public Expression resolve(TranslationContext context) { - value = value.resolve(context); - return this; - } - - @Override - public Expression replace(ReplaceContext context) { - Variable newParameter = parameter.copy(); - context.varMap.put(parameter, new EVariable(newParameter)); - ESimpleLambda result = new ESimpleLambda(getLocation(), - newParameter, - effect.replace(context.tvarMap), - value.replace(context)); - // not absolutely needed, but maybe good for performance - context.varMap.remove(parameter); - return result; - } - - public Type getLocalEffect() { - if(SCLCompilerConfiguration.DEBUG) - if(effect == null) - throw new InternalCompilerError(); - return effect; - } - - public void setEffect(Type effect) { - if(effect == null) - throw new InternalCompilerError(); - this.effect = effect; - } - - @Override - public IExpression toIExpression(ExpressionInterpretationContext context) { - // Find parameters of the whole function definition - ArrayList parameters = new ArrayList(2); - parameters.add(parameter); - Expression cur = value; - while(true) { - if(cur instanceof ESimpleLambda) { - ESimpleLambda lambda = (ESimpleLambda)cur; - parameters.add(lambda.parameter); - cur = lambda.value; - } - else if(cur instanceof ELambdaType) { - cur = ((ELambdaType)cur).value; - } - else - break; - - } - - // Free variables; - ExpressionInterpretationContext innerContext = context.createNewContext(); - THashSet freeVariables = cur.getFreeVariables(); - for(Variable parameter : parameters) - freeVariables.remove(parameter); - int i=0; - int[] inheritedVariableIds = new int[freeVariables.size()]; - for(Variable var : freeVariables) { - innerContext.push(var); - inheritedVariableIds[i++] = context.getVariableId(var); - } - - // Parameters - for(Variable parameter : parameters) - innerContext.push(parameter); - - // Construct lambda - IExpression body = cur.toIExpression(innerContext); - return new ILambda(inheritedVariableIds, - parameters.size(), - innerContext.getMaxVariableId(), - body); - } - - public Expression checkBasicType(TypingContext context, Type requiredType) { - MultiFunction mfun; - try { - mfun = Types.unifyFunction(requiredType, 1); - } catch (UnificationException e) { - context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda."); - setType(Types.metaVar(Kinds.STAR)); - return this; - } - - effect = mfun.effect; - context.pushEffectUpperBound(location, mfun.effect); - parameter.setType(mfun.parameterTypes[0]); - value = value.checkType(context, mfun.returnType); - context.popEffectUpperBound(); - return this; - } - - @Override - public Expression inferType(TypingContext context) { - effect = Types.metaVar(Kinds.EFFECT); - context.pushEffectUpperBound(location, effect); - if(parameter.type == null) - parameter.setType(Types.metaVar(Kinds.STAR)); - value = value.checkType(context, Types.metaVar(Kinds.STAR)); - context.popEffectUpperBound(); - return this; - } - - @Override - public Expression decorate(ExpressionDecorator decorator) { - if(decorator.decorateSubstructure(this)) - value = value.decorate(decorator); - return decorator.decorate(this); - } - - @Override - public boolean isEffectful() { - return false; - } - - @Override - public void collectEffects(THashSet effects) { - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - value.setLocationDeep(loc); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - public Expression getValue() { - return value; - } - - public Variable getParameter() { - return parameter; - } - - @Override - public void forVariables(VariableProcedure procedure) { - value.forVariables(procedure); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.internal.interpreted.IExpression; +import org.simantics.scl.compiler.internal.interpreted.ILambda; +import org.simantics.scl.compiler.top.ExpressionInterpretationContext; +import org.simantics.scl.compiler.top.SCLCompilerConfiguration; +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.exceptions.UnificationException; +import org.simantics.scl.compiler.types.kinds.Kinds; +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 ESimpleLambda extends Expression { + public Variable parameter; + public Expression value; + public Type effect = Types.NO_EFFECTS; + + public ESimpleLambda(Variable parameter, Expression value) { + this.parameter = parameter; + this.value = value; + } + + public ESimpleLambda(Type effect, Variable parameter, Expression value) { + this.parameter = parameter; + this.value = value; + this.effect = effect; + } + + public ESimpleLambda(long loc, Variable parameter, Expression value) { + super(loc); + this.parameter = parameter; + this.value = value; + } + + public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) { + super(loc); + this.parameter = parameter; + this.value = value; + this.effect = effect; + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + value.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + value.collectVars(allVars, vars); + } + + public Expression decomposeMatching() { + value = value.decomposeMatching(); + return this; + } + + @Override + protected void updateType() throws MatchException { + setType(Types.functionE(Types.canonical(parameter.type), + effect, value.getType())); + } + + @Override + public IVal toVal(Environment env, CodeWriter w) { + return lambdaToVal(env, w); + } + + @Override + public void collectFreeVariables(THashSet vars) { + value.collectFreeVariables(vars); + vars.remove(parameter); + } + + @Override + public Expression simplify(SimplificationContext context) { + value = value.simplify(context); + return this; + } + + @Override + public Expression resolve(TranslationContext context) { + value = value.resolve(context); + return this; + } + + @Override + public Expression replace(ReplaceContext context) { + Variable newParameter = parameter.copy(); + context.varMap.put(parameter, new EVariable(newParameter)); + ESimpleLambda result = new ESimpleLambda(getLocation(), + newParameter, + effect.replace(context.tvarMap), + value.replace(context)); + // not absolutely needed, but maybe good for performance + context.varMap.remove(parameter); + return result; + } + + public Type getLocalEffect() { + if(SCLCompilerConfiguration.DEBUG) + if(effect == null) + throw new InternalCompilerError(); + return effect; + } + + public void setEffect(Type effect) { + if(effect == null) + throw new InternalCompilerError(); + this.effect = effect; + } + + @Override + public IExpression toIExpression(ExpressionInterpretationContext context) { + // Find parameters of the whole function definition + ArrayList parameters = new ArrayList(2); + parameters.add(parameter); + Expression cur = value; + while(true) { + if(cur instanceof ESimpleLambda) { + ESimpleLambda lambda = (ESimpleLambda)cur; + parameters.add(lambda.parameter); + cur = lambda.value; + } + else if(cur instanceof ELambdaType) { + cur = ((ELambdaType)cur).value; + } + else + break; + + } + + // Free variables; + ExpressionInterpretationContext innerContext = context.createNewContext(); + THashSet freeVariables = cur.getFreeVariables(); + for(Variable parameter : parameters) + freeVariables.remove(parameter); + int i=0; + int[] inheritedVariableIds = new int[freeVariables.size()]; + for(Variable var : freeVariables) { + innerContext.push(var); + inheritedVariableIds[i++] = context.getVariableId(var); + } + + // Parameters + for(Variable parameter : parameters) + innerContext.push(parameter); + + // Construct lambda + IExpression body = cur.toIExpression(innerContext); + return new ILambda(inheritedVariableIds, + parameters.size(), + innerContext.getMaxVariableId(), + body); + } + + public Expression checkBasicType(TypingContext context, Type requiredType) { + MultiFunction mfun; + try { + mfun = Types.unifyFunction(requiredType, 1); + } catch (UnificationException e) { + context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda."); + setType(Types.metaVar(Kinds.STAR)); + return this; + } + + effect = mfun.effect; + context.pushEffectUpperBound(location, mfun.effect); + parameter.setType(mfun.parameterTypes[0]); + value = value.checkType(context, mfun.returnType); + context.popEffectUpperBound(); + return this; + } + + @Override + public Expression inferType(TypingContext context) { + effect = Types.metaVar(Kinds.EFFECT); + context.pushEffectUpperBound(location, effect); + if(parameter.type == null) + parameter.setType(Types.metaVar(Kinds.STAR)); + value = value.checkType(context, Types.metaVar(Kinds.STAR)); + context.popEffectUpperBound(); + return this; + } + + @Override + public Expression decorate(ExpressionDecorator decorator) { + if(decorator.decorateSubstructure(this)) + value = value.decorate(decorator); + return decorator.decorate(this); + } + + @Override + public boolean isEffectful() { + return false; + } + + @Override + public void collectEffects(THashSet effects) { + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + value.setLocationDeep(loc); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + public Expression getValue() { + return value; + } + + public Variable getParameter() { + return parameter; + } + + @Override + public void forVariables(VariableProcedure procedure) { + value.forVariables(procedure); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + return 1 + value.getSyntacticFunctionArity(); + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLet.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLet.java index 8e73b2392..047d77a47 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLet.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLet.java @@ -1,220 +1,224 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.internal.interpreted.IExpression; -import org.simantics.scl.compiler.internal.interpreted.ILet; -import org.simantics.scl.compiler.internal.interpreted.ISeq; -import org.simantics.scl.compiler.top.ExpressionInterpretationContext; -import org.simantics.scl.compiler.types.Type; -import org.simantics.scl.compiler.types.exceptions.MatchException; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class ESimpleLet extends Expression { - Variable variable; // may be null - Expression value; - Expression in; - - public ESimpleLet(Variable variable, Expression value, Expression in) { - if(value == null) - throw new NullPointerException(); - if(in == null) - throw new NullPointerException(); - this.variable = variable; - this.value = value; - this.in = in; - } - - public ESimpleLet(long loc, Variable variable, Expression value, Expression in) { - super(loc); - if(value == null) - throw new NullPointerException(); - if(in == null) - throw new NullPointerException(); - this.variable = variable; - this.value = value; - this.in = in; - } - - public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { - value.collectRefs(allRefs, refs); - in.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - value.collectVars(allVars, vars); - in.collectVars(allVars, vars); - } - - @Override - protected void updateType() throws MatchException { - setType(in.getType()); - } - - @Override - public IVal toVal(Environment env, CodeWriter w) { - IVal valueVal = value.toVal(env, w); - if(variable != null) - variable.setVal(valueVal); - return in.toVal(env, w); - } - - @Override - public void collectFreeVariables(THashSet vars) { - value.collectFreeVariables(vars); - in.collectFreeVariables(vars); - vars.remove(variable); - } - - @Override - public Expression simplify(SimplificationContext context) { - value = value.simplify(context); - if(value instanceof EConstant || value instanceof ELiteral) { - context.addInlinedVariable(variable, value); - return in.simplify(context); - } - in = in.simplify(context); - return this; - } - - @Override - public Expression resolve(TranslationContext context) { - value = value.resolve(context); - in = in.resolve(context); - return this; - } - - @Override - public Expression replace(ReplaceContext context) { - if(variable == null) - return new ESimpleLet(location, - null, - value.replace(context), - in.replace(context)); - else { - Variable newVariable = variable.copy(); - context.varMap.put(variable, new EVariable(newVariable)); - ESimpleLet result = new ESimpleLet(location, newVariable, - value.replace(context), - in.replace(context)); - context.varMap.remove(variable); - return result; - } - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - value.setLocationDeep(loc); - in.setLocationDeep(loc); - } - } - - @Override - public IExpression toIExpression(ExpressionInterpretationContext context) { - if(variable == null) { - IExpression valueI = value.toIExpression(context); - IExpression inI = in.toIExpression(context); - return new ISeq(valueI, inI); - } - else { - IExpression valueI = value.toIExpression(context); - int variableId = context.push(variable); - IExpression inI = in.toIExpression(context); - context.pop(variable); - return new ILet(variableId, valueI, inI); - } - } - - private void checkBinding(TypingContext context) { - if(variable == null) - value = value.checkIgnoredType(context); - else if(variable.getType() == null) { - value = value.inferType(context); - variable.setType(value.getType()); - } - else - value = value.checkType(context, variable.type); - /*else { - if(variable.getType() == null) - variable.setType(Types.metaVar(Kinds.STAR)); - value = value.checkType(context, variable.type); - }*/ - } - - @Override - public Expression inferType(TypingContext context) { - checkBinding(context); - in = in.inferType(context); - return this; - } - - @Override - public Expression checkBasicType(TypingContext context, Type requiredType) { - checkBinding(context); - in = in.checkType(context, requiredType); - return this; - } - - @Override - public Expression checkIgnoredType(TypingContext context) { - checkBinding(context); - in = in.checkIgnoredType(context); - return this; - } - - @Override - public Expression decorate(ExpressionDecorator decorator) { - value = value.decorate(decorator); - in = in.decorate(decorator); - return decorator.decorate(this); - } - - @Override - public void collectEffects(THashSet effects) { - value.collectEffects(effects); - in.collectEffects(effects); - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - public Expression getValue() { - return value; - } - - public Variable getVariable() { - return variable; - } - - public Expression getIn() { - return in; - } - - @Override - public void forVariables(VariableProcedure procedure) { - value.forVariables(procedure); - in.forVariables(procedure); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.internal.interpreted.IExpression; +import org.simantics.scl.compiler.internal.interpreted.ILet; +import org.simantics.scl.compiler.internal.interpreted.ISeq; +import org.simantics.scl.compiler.top.ExpressionInterpretationContext; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.exceptions.MatchException; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class ESimpleLet extends Expression { + Variable variable; // may be null + Expression value; + Expression in; + + public ESimpleLet(Variable variable, Expression value, Expression in) { + if(value == null) + throw new NullPointerException(); + if(in == null) + throw new NullPointerException(); + this.variable = variable; + this.value = value; + this.in = in; + } + + public ESimpleLet(long loc, Variable variable, Expression value, Expression in) { + super(loc); + if(value == null) + throw new NullPointerException(); + if(in == null) + throw new NullPointerException(); + this.variable = variable; + this.value = value; + this.in = in; + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + value.collectRefs(allRefs, refs); + in.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + value.collectVars(allVars, vars); + in.collectVars(allVars, vars); + } + + @Override + protected void updateType() throws MatchException { + setType(in.getType()); + } + + @Override + public IVal toVal(Environment env, CodeWriter w) { + IVal valueVal = value.toVal(env, w); + if(variable != null) + variable.setVal(valueVal); + return in.toVal(env, w); + } + + @Override + public void collectFreeVariables(THashSet vars) { + value.collectFreeVariables(vars); + in.collectFreeVariables(vars); + vars.remove(variable); + } + + @Override + public Expression simplify(SimplificationContext context) { + value = value.simplify(context); + if(value instanceof EConstant || value instanceof ELiteral) { + context.addInlinedVariable(variable, value); + return in.simplify(context); + } + in = in.simplify(context); + return this; + } + + @Override + public Expression resolve(TranslationContext context) { + value = value.resolve(context); + in = in.resolve(context); + return this; + } + + @Override + public Expression replace(ReplaceContext context) { + if(variable == null) + return new ESimpleLet(location, + null, + value.replace(context), + in.replace(context)); + else { + Variable newVariable = variable.copy(); + context.varMap.put(variable, new EVariable(newVariable)); + ESimpleLet result = new ESimpleLet(location, newVariable, + value.replace(context), + in.replace(context)); + context.varMap.remove(variable); + return result; + } + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + value.setLocationDeep(loc); + in.setLocationDeep(loc); + } + } + + @Override + public IExpression toIExpression(ExpressionInterpretationContext context) { + if(variable == null) { + IExpression valueI = value.toIExpression(context); + IExpression inI = in.toIExpression(context); + return new ISeq(valueI, inI); + } + else { + IExpression valueI = value.toIExpression(context); + int variableId = context.push(variable); + IExpression inI = in.toIExpression(context); + context.pop(variable); + return new ILet(variableId, valueI, inI); + } + } + + private void checkBinding(TypingContext context) { + if(variable == null) + value = value.checkIgnoredType(context); + else if(variable.getType() == null) { + value = value.inferType(context); + variable.setType(value.getType()); + } + else + value = value.checkType(context, variable.type); + /*else { + if(variable.getType() == null) + variable.setType(Types.metaVar(Kinds.STAR)); + value = value.checkType(context, variable.type); + }*/ + } + + @Override + public Expression inferType(TypingContext context) { + checkBinding(context); + in = in.inferType(context); + return this; + } + + @Override + public Expression checkBasicType(TypingContext context, Type requiredType) { + checkBinding(context); + in = in.checkType(context, requiredType); + return this; + } + + @Override + public Expression checkIgnoredType(TypingContext context) { + checkBinding(context); + in = in.checkIgnoredType(context); + return this; + } + + @Override + public Expression decorate(ExpressionDecorator decorator) { + value = value.decorate(decorator); + in = in.decorate(decorator); + return decorator.decorate(this); + } + + @Override + public void collectEffects(THashSet effects) { + value.collectEffects(effects); + in.collectEffects(effects); + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + public Expression getValue() { + return value; + } + + public Variable getVariable() { + return variable; + } + + public Expression getIn() { + return in; + } + + @Override + public void forVariables(VariableProcedure procedure) { + value.forVariables(procedure); + in.forVariables(procedure); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + return in.getSyntacticFunctionArity(); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EStringLiteral.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EStringLiteral.java index 79d464b7b..f15e62cbf 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EStringLiteral.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EStringLiteral.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.constants.StringInterpolation; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.modules.SCLValue; @@ -19,7 +19,7 @@ public class EStringLiteral extends ASTExpression { @Override public Expression resolve(TranslationContext context) { Expression[] components = new Expression[expressions.length]; - SCLValue showForPrinting = context.getEnvironment().getValue(Name.create("Prelude", "showForPrinting")); + SCLValue showForPrinting = context.getEnvironment().getValue(Names.Prelude_showForPrinting); 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/EVar.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVar.java index 5ad1e3126..f1c3e31e0 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVar.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVar.java @@ -1,82 +1,82 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import java.util.ArrayList; - -import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; -import org.simantics.scl.compiler.elaboration.errors.NotPatternException; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs; -import org.simantics.scl.compiler.errors.Locations; - -public class EVar extends ASTExpression { - public final String name; - - public EVar(long location, String name) { - this.location = location; - this.name = name; - } - - public EVar(String name) { - this(Locations.NO_LOCATION, name); - } - - @Override - public EVar getPatternHead() { - return this; - } - - @Override - public LhsType getLhsType() throws NotPatternException { - if(TranslationContext.isConstructorName(name)) - return new PatternMatchingLhs(); - else - return new FunctionDefinitionLhs(name); - } - - @Override - protected void collectVariableNames(PatternMatchingLhs lhsType) - throws NotPatternException { - if(!TranslationContext.isConstructorName(name)) - lhsType.variableNames.add(name); - } - - @Override - public Expression resolve(TranslationContext context) { - return context.resolveExpression(location, name); - } - - @Override - public void getParameters(TranslationContext translationContext, - ArrayList parameters) { - } - - @Override - public Expression resolveAsPattern(TranslationContext context) { - return context.resolvePattern(this); - } - - @Override - public int getFunctionDefinitionArity() throws NotPatternException { - if(TranslationContext.isConstructorName(name)) - throw new NotPatternException(this); - else - return 0; - } - - @Override - public boolean isConstructorApplication() { - return TranslationContext.isConstructorName(name); - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) - location = loc; - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } -} +package org.simantics.scl.compiler.elaboration.expressions; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.errors.NotPatternException; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs; +import org.simantics.scl.compiler.errors.Locations; + +public class EVar extends ASTExpression { + public final String name; + + public EVar(long location, String name) { + this.location = location; + this.name = name; + } + + public EVar(String name) { + this(Locations.NO_LOCATION, name); + } + + @Override + public EVar getPatternHead() { + return this; + } + + @Override + public LhsType getLhsType() throws NotPatternException { + if(TranslationContext.isConstructorName(name)) + return new PatternMatchingLhs(); + else + return new FunctionDefinitionLhs(name); + } + + @Override + protected void collectVariableNames(PatternMatchingLhs lhsType) + throws NotPatternException { + if(!TranslationContext.isConstructorName(name)) + lhsType.variableNames.add(name); + } + + @Override + public Expression resolve(TranslationContext context) { + return context.resolveExpression(location, name); + } + + @Override + public void getParameters(TranslationContext translationContext, + ArrayList parameters) { + } + + @Override + public Expression resolveAsPattern(TranslationContext context) { + return context.resolvePattern(this); + } + + @Override + public int getFunctionDefinitionPatternArity() throws NotPatternException { + if(TranslationContext.isConstructorName(name)) + throw new NotPatternException(this); + else + return 0; + } + + @Override + public boolean isConstructorApplication() { + return TranslationContext.isConstructorName(name); + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) + location = loc; + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } +} 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..8adf33936 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 @@ -1,379 +1,395 @@ -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.precedence.Precedence; -import org.simantics.scl.compiler.constants.NoRepConstant; -import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext; -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.errors.NotPatternException; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; -import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs; -import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor; -import org.simantics.scl.compiler.elaboration.query.QAtom; -import org.simantics.scl.compiler.elaboration.relations.SCLRelation; -import org.simantics.scl.compiler.environment.Environment; -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.decomposed.DecomposedExpression; -import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; -import org.simantics.scl.compiler.internal.interpreted.IExpression; -import org.simantics.scl.compiler.internal.parsing.Symbol; -import org.simantics.scl.compiler.top.ExpressionInterpretationContext; -import org.simantics.scl.compiler.types.TForAll; -import org.simantics.scl.compiler.types.TFun; -import org.simantics.scl.compiler.types.TPred; -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.exceptions.MatchException; -import org.simantics.scl.compiler.types.kinds.Kinds; -import org.simantics.scl.compiler.types.util.Typed; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public abstract class Expression extends Symbol implements Typed { - public static final Expression[] EMPTY_ARRAY = new Expression[0]; - - transient - private Type type; - - public Expression() { - } - - public Expression(long loc) { - this.location = loc; - } - - @Override - public Type getType() { - if(type == null) { - try { - updateType(); - } catch (MatchException e) { - throw new InternalCompilerError(e); - } - if(type == null) - throw new InternalCompilerError(getClass().getSimpleName() + - ".updateType couldn't compute its type."); - } - return type; - } - - public void setType(Type type) { - if(type == null) - throw new NullPointerException(); - this.type = type; - } - - /** - * Infers the type of the expression without any context. Adds type - * applications and lambdas if needed. - */ - public Expression inferType(TypingContext context) { - return checkBasicType(context, Types.metaVar(Kinds.STAR)); - } - - public Expression checkBasicType(TypingContext context, Type requiredType) { - return context.subsume(inferType(context), requiredType); - } - - protected Expression applyPUnit(EnvironmentalContext context) { - Type type = Types.canonical(getType()); - if(type instanceof TFun) { - TFun fun = (TFun)type; - if(fun.getCanonicalDomain() == Types.PUNIT) { - EApply result = new EApply(location, this, new ELiteral(NoRepConstant.PUNIT)); - result.effect = fun.getCanonicalEffect(); - return result; - } - } - return this; - } - - public Expression checkIgnoredType(TypingContext context) { - Expression expression = inferType(context); - if(Types.canonical(expression.getType()) != Types.UNIT) - expression = new ESimpleLet(location, null, expression, new ELiteral(NoRepConstant.PUNIT)); - return expression; - } - - /** - * Checks the type of the expression against the given type. Adds type - * applications and lambdas if needed. - */ - public final Expression checkType(TypingContext context, Type requiredType) { - //System.out.println("checkType: " + this + " :: " + requiredType); - if(!context.isInPattern()) { - requiredType = Types.canonical(requiredType); - if(requiredType instanceof TForAll) { - TForAll forAll = (TForAll)requiredType; - TVar var = forAll.var; - TVar newVar = Types.var(var.getKind()); - requiredType = Types.canonical(forAll.type).replace(var, newVar); - return new ELambdaType(new TVar[] {newVar}, checkType(context, requiredType)); - } - while(requiredType instanceof TFun) { - TFun fun = (TFun)requiredType; - if(fun.domain instanceof TPred) { // No need to canonicalize - ArrayList constraints = new ArrayList(2); - while(true) { - constraints.add(new Variable("constraint", fun.domain)); - requiredType = Types.canonical(fun.range); - if(!(requiredType instanceof TFun)) - break; - fun = (TFun)requiredType; - if(!(fun.domain instanceof TPred)) - break; - } - context.pushConstraintFrame(constraints.toArray(new Variable[constraints.size()])); - Expression expression = checkType(context, requiredType); - context.popConstraintFrame(); - for(int i=constraints.size()-1;i>=0;--i) - expression = new ESimpleLambda(constraints.get(i), expression); - return expression; - } - else if(fun.domain == Types.PUNIT) { - context.pushEffectUpperBound(location, fun.effect); - Expression expr = checkType(context, fun.range); - context.popEffectUpperBound(); - - // Wrap - Variable var = new Variable("punit", Types.PUNIT); - return new ESimpleLambda(location, var, fun.effect, expr); - } - else - break; - } - } - return checkBasicType(context, requiredType); - } - - public abstract void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs); - public abstract void collectVars(TObjectIntHashMap allVars, TIntHashSet vars); - public abstract void forVariables(VariableProcedure procedure); - - public Expression decomposeMatching() { - return this; - } - - public String toString() { - StringBuilder b = new StringBuilder(); - ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b); - accept(visitor); - return b.toString(); - } - - protected abstract void updateType() throws MatchException; - - public static class TypeValidationException extends Exception { - private static final long serialVersionUID = 3181298127162041248L; - - long loc; - - public TypeValidationException(long loc) { - this.loc = loc; - } - - public long getLoc() { - return loc; - } - - public TypeValidationException(long loc, Throwable cause) { - super(cause); - this.loc = loc; - } - } - - public static void assertEquals(long loc, Type a, Type b) throws TypeValidationException { - if(!Types.equals(a, b)) - throw new TypeValidationException(loc); - } - - public abstract IVal toVal(Environment env, CodeWriter w); - - public Expression closure(TVar ... vars) { - if(vars.length == 0) - return this; - return new ELambdaType(vars, this); - } - - public abstract void collectFreeVariables(THashSet vars); - - public Expression simplify(SimplificationContext context) { - throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method."); - } - - public abstract Expression resolve(TranslationContext context); - - /** - * Returns head of the pattern. - */ - public EVar getPatternHead() throws NotPatternException { - throw new NotPatternException(this); - } - - public LhsType getLhsType() throws NotPatternException { - throw new NotPatternException(this); - } - - protected void collectVariableNames(PatternMatchingLhs lhsType) throws NotPatternException { - throw new NotPatternException(this); - } - - public void getParameters(TranslationContext translationContext, - ArrayList parameters) { - throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters."); - } - - public Expression resolveAsPattern(TranslationContext context) { - context.getErrorLog().log(location, "Pattern was expected here."); - return new EError(); - } - - public void removeFreeVariables(THashSet vars) { - throw new InternalCompilerError(getClass().getSimpleName() + " is not a pattern."); - } - - public Expression checkTypeAsPattern(TypingContext context, Type requiredType) { - if(context.isInPattern()) - throw new InternalCompilerError("Already in a pattern."); - context.setInPattern(true); - Expression expression = checkType(context, requiredType); - context.setInPattern(false); - return expression; - } - - public THashSet getFreeVariables() { - THashSet result = new THashSet(); - collectFreeVariables(result); - return result; - } - - public static Expression[] concat(Expression[] a, Expression[] b) { - if(a.length == 0) - return b; - if(b.length == 0) - return a; - Expression[] result = new Expression[a.length + b.length]; - for(int i=0;i effects); - - public Type getEffect() { - THashSet effects = new THashSet(); - collectEffects(effects); - return Types.union(effects.toArray(new Type[effects.size()])); - } - - public abstract void accept(ExpressionVisitor visitor); - - public void collectRelationRefs( - final TObjectIntHashMap allRefs, final TIntHashSet refs) { - accept(new StandardExpressionVisitor() { - @Override - public void visit(QAtom query) { - int id = allRefs.get(query.relation); - if(id >= 0) - refs.add(id); - } - }); - } - - public boolean isFunctionDefinitionLhs() { - return false; - } - - public Precedence getPrecedence() { - return Precedence.DEFAULT; - } - - public boolean isPattern(int arity) { - return false; - } - - public abstract Expression accept(ExpressionTransformer transformer); -} +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.precedence.Precedence; +import org.simantics.scl.compiler.constants.NoRepConstant; +import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext; +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.errors.NotPatternException; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; +import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs; +import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor; +import org.simantics.scl.compiler.elaboration.query.QAtom; +import org.simantics.scl.compiler.elaboration.relations.SCLRelation; +import org.simantics.scl.compiler.environment.Environment; +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.decomposed.DecomposedExpression; +import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; +import org.simantics.scl.compiler.internal.interpreted.IExpression; +import org.simantics.scl.compiler.internal.parsing.Symbol; +import org.simantics.scl.compiler.top.ExpressionInterpretationContext; +import org.simantics.scl.compiler.types.TForAll; +import org.simantics.scl.compiler.types.TFun; +import org.simantics.scl.compiler.types.TPred; +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.exceptions.MatchException; +import org.simantics.scl.compiler.types.kinds.Kinds; +import org.simantics.scl.compiler.types.util.Typed; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public abstract class Expression extends Symbol implements Typed { + public static final Expression[] EMPTY_ARRAY = new Expression[0]; + + transient + private Type type; + + public Expression() { + } + + public Expression(long loc) { + this.location = loc; + } + + @Override + public Type getType() { + if(type == null) { + try { + updateType(); + } catch (MatchException e) { + throw new InternalCompilerError(e); + } + if(type == null) + throw new InternalCompilerError(getClass().getSimpleName() + + ".updateType couldn't compute its type."); + } + return type; + } + + public void setType(Type type) { + if(type == null) + throw new NullPointerException(); + this.type = type; + } + + /** + * Infers the type of the expression without any context. Adds type + * applications and lambdas if needed. + */ + public Expression inferType(TypingContext context) { + return checkBasicType(context, Types.metaVar(Kinds.STAR)); + } + + public Expression checkBasicType(TypingContext context, Type requiredType) { + return context.subsume(inferType(context), requiredType); + } + + protected Expression applyPUnit(EnvironmentalContext context) { + Type type = Types.canonical(getType()); + if(type instanceof TFun) { + TFun fun = (TFun)type; + if(fun.getCanonicalDomain() == Types.PUNIT) { + EApply result = new EApply(location, this, new ELiteral(NoRepConstant.PUNIT)); + result.effect = fun.getCanonicalEffect(); + return result; + } + } + return this; + } + + public Expression checkIgnoredType(TypingContext context) { + Expression expression = inferType(context); + if(Types.canonical(expression.getType()) != Types.UNIT) + expression = new ESimpleLet(location, null, expression, new ELiteral(NoRepConstant.PUNIT)); + return expression; + } + + /** + * Checks the type of the expression against the given type. Adds type + * applications and lambdas if needed. + */ + public final Expression checkType(TypingContext context, Type requiredType) { + //System.out.println("checkType: " + this + " :: " + requiredType); + if(!context.isInPattern()) { + requiredType = Types.canonical(requiredType); + if(requiredType instanceof TForAll) { + TForAll forAll = (TForAll)requiredType; + TVar var = forAll.var; + TVar newVar = Types.var(var.getKind()); + requiredType = Types.canonical(forAll.type).replace(var, newVar); + return new ELambdaType(new TVar[] {newVar}, checkType(context, requiredType)); + } + while(requiredType instanceof TFun) { + TFun fun = (TFun)requiredType; + if(fun.domain instanceof TPred) { // No need to canonicalize + ArrayList constraints = new ArrayList(2); + while(true) { + constraints.add(new Variable("constraint", fun.domain)); + requiredType = Types.canonical(fun.range); + if(!(requiredType instanceof TFun)) + break; + fun = (TFun)requiredType; + if(!(fun.domain instanceof TPred)) + break; + } + context.pushConstraintFrame(constraints.toArray(new Variable[constraints.size()])); + Expression expression = checkType(context, requiredType); + context.popConstraintFrame(); + for(int i=constraints.size()-1;i>=0;--i) + expression = new ESimpleLambda(constraints.get(i), expression); + return expression; + } + else if(fun.domain == Types.PUNIT) { + context.pushEffectUpperBound(location, fun.effect); + Expression expr = checkType(context, fun.range); + context.popEffectUpperBound(); + + // Wrap + Variable var = new Variable("punit", Types.PUNIT); + return new ESimpleLambda(location, var, fun.effect, expr); + } + else + break; + } + } + return checkBasicType(context, requiredType); + } + + public abstract void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs); + public abstract void collectVars(TObjectIntHashMap allVars, TIntHashSet vars); + public abstract void forVariables(VariableProcedure procedure); + + public Expression decomposeMatching() { + return this; + } + + public String toString() { + StringBuilder b = new StringBuilder(); + ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b); + accept(visitor); + return b.toString(); + } + + protected abstract void updateType() throws MatchException; + + public static class TypeValidationException extends Exception { + private static final long serialVersionUID = 3181298127162041248L; + + long loc; + + public TypeValidationException(long loc) { + this.loc = loc; + } + + public long getLoc() { + return loc; + } + + public TypeValidationException(long loc, Throwable cause) { + super(cause); + this.loc = loc; + } + } + + public static void assertEquals(long loc, Type a, Type b) throws TypeValidationException { + if(!Types.equals(a, b)) + throw new TypeValidationException(loc); + } + + public abstract IVal toVal(Environment env, CodeWriter w); + + public Expression closure(TVar ... vars) { + if(vars.length == 0) + return this; + return new ELambdaType(vars, this); + } + + 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."); + } + + public abstract Expression resolve(TranslationContext context); + + /** + * Returns head of the pattern. + */ + public EVar getPatternHead() throws NotPatternException { + throw new NotPatternException(this); + } + + public LhsType getLhsType() throws NotPatternException { + throw new NotPatternException(this); + } + + protected void collectVariableNames(PatternMatchingLhs lhsType) throws NotPatternException { + throw new NotPatternException(this); + } + + public void getParameters(TranslationContext translationContext, + ArrayList parameters) { + throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters."); + } + + public Expression resolveAsPattern(TranslationContext context) { + context.getErrorLog().log(location, "Pattern was expected here."); + return new EError(); + } + + public void removeFreeVariables(THashSet vars) { + throw new InternalCompilerError(getClass().getSimpleName() + " is not a pattern."); + } + + public Expression checkTypeAsPattern(TypingContext context, Type requiredType) { + if(context.isInPattern()) + throw new InternalCompilerError("Already in a pattern."); + context.setInPattern(true); + Expression expression = checkType(context, requiredType); + context.setInPattern(false); + return expression; + } + + public THashSet getFreeVariables() { + THashSet result = new THashSet(); + collectFreeVariables(result); + return result; + } + + public static Expression[] concat(Expression[] a, Expression[] b) { + if(a.length == 0) + return b; + if(b.length == 0) + return a; + Expression[] result = new Expression[a.length + b.length]; + for(int i=0;i effects); + + public Type getEffect() { + THashSet effects = new THashSet(); + collectEffects(effects); + return Types.union(effects.toArray(new Type[effects.size()])); + } + + public abstract void accept(ExpressionVisitor visitor); + + public void collectRelationRefs( + final TObjectIntHashMap allRefs, final TIntHashSet refs) { + accept(new StandardExpressionVisitor() { + @Override + public void visit(QAtom query) { + int id = allRefs.get(query.relation); + if(id >= 0) + refs.add(id); + } + }); + } + + public boolean isFunctionDefinitionLhs() { + return false; + } + + public Precedence getPrecedence() { + return Precedence.DEFAULT; + } + + public boolean isPattern(int arity) { + return false; + } + + public abstract Expression accept(ExpressionTransformer transformer); + + // TODO implement for all expressions + public boolean equalsExpression(Expression expression) { + return false; + } + + /** + * This method returns a lower bound for the function arity of the value this expression defines. + * The lower bound is calculated purely looking the syntax of the expression, not the + * types of the constants and variables the expression refers to. + */ + public int getSyntacticFunctionArity() { + return 0; + } +} 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/GuardedExpressionGroup.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/GuardedExpressionGroup.java index 48f72eeac..890d11f8c 100755 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/GuardedExpressionGroup.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/GuardedExpressionGroup.java @@ -1,181 +1,186 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; -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.continuations.ICont; -import org.simantics.scl.compiler.internal.codegen.references.IVal; -import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw; -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 gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class GuardedExpressionGroup extends Expression { - public GuardedExpression[] expressions; - - public GuardedExpressionGroup(GuardedExpression[] expressions) { - this.expressions = expressions; - } - - @Override - public void collectRefs(TObjectIntHashMap allRefs, - TIntHashSet refs) { - for(GuardedExpression expression : expressions) { - for(Expression guard : expression.guards) - guard.collectRefs(allRefs, refs); - expression.value.collectRefs(allRefs, refs); - } - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - for(GuardedExpression expression : expressions) { - for(Expression guard : expression.guards) - guard.collectVars(allVars, vars); - expression.value.collectVars(allVars, vars); - } - } - - @Override - protected void updateType() throws MatchException { - setType(expressions[0].value.getType()); - } - - @Override - public IVal toVal(Environment env, CodeWriter w) { - CodeWriter success = w.createBlock(getType()); - IVal result = success.getParameters()[0]; - CodeWriter failure = w.createBlock(); - compile(env, w, success.getContinuation(), failure.getContinuation()); - w.continueAs(success); - failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString()); - return result; - //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation."); - } - - @Override - public void collectFreeVariables(THashSet vars) { - for(GuardedExpression expression : expressions) { - for(Expression guard : expression.guards) - guard.collectFreeVariables(vars); - expression.value.collectFreeVariables(vars); - } - } - - @Override - public Expression simplify(SimplificationContext context) { - for(GuardedExpression expression : expressions) { - for(int i=0;i effects) { - for(GuardedExpression ge : expressions) { - for(Expression guard : ge.guards) - guard.collectEffects(effects); - ge.value.collectEffects(effects); - } - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - for(GuardedExpression expression : expressions) - expression.setLocationDeep(loc); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public void forVariables(VariableProcedure procedure) { - for(GuardedExpression expression : expressions) - expression.forVariables(procedure); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } -} +package org.simantics.scl.compiler.elaboration.expressions; + +import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; +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.continuations.ICont; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw; +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 gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class GuardedExpressionGroup extends Expression { + public GuardedExpression[] expressions; + + public GuardedExpressionGroup(GuardedExpression[] expressions) { + this.expressions = expressions; + } + + @Override + public void collectRefs(TObjectIntHashMap allRefs, + TIntHashSet refs) { + for(GuardedExpression expression : expressions) { + for(Expression guard : expression.guards) + guard.collectRefs(allRefs, refs); + expression.value.collectRefs(allRefs, refs); + } + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + for(GuardedExpression expression : expressions) { + for(Expression guard : expression.guards) + guard.collectVars(allVars, vars); + expression.value.collectVars(allVars, vars); + } + } + + @Override + protected void updateType() throws MatchException { + setType(expressions[0].value.getType()); + } + + @Override + public IVal toVal(Environment env, CodeWriter w) { + CodeWriter success = w.createBlock(getType()); + IVal result = success.getParameters()[0]; + CodeWriter failure = w.createBlock(); + compile(env, w, success.getContinuation(), failure.getContinuation()); + w.continueAs(success); + failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString()); + return result; + //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation."); + } + + @Override + public void collectFreeVariables(THashSet vars) { + for(GuardedExpression expression : expressions) { + for(Expression guard : expression.guards) + guard.collectFreeVariables(vars); + expression.value.collectFreeVariables(vars); + } + } + + @Override + public Expression simplify(SimplificationContext context) { + for(GuardedExpression expression : expressions) { + for(int i=0;i effects) { + for(GuardedExpression ge : expressions) { + for(Expression guard : ge.guards) + guard.collectEffects(effects); + ge.value.collectEffects(effects); + } + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + for(GuardedExpression expression : expressions) + expression.setLocationDeep(loc); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public void forVariables(VariableProcedure procedure) { + for(GuardedExpression expression : expressions) + expression.forVariables(procedure); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + + @Override + public int getSyntacticFunctionArity() { + return expressions[0].value.getSyntacticFunctionArity(); + } +} 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/errors/ErrorLog.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/errors/ErrorLog.java index 13e80fc6d..2287f919b 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/errors/ErrorLog.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/errors/ErrorLog.java @@ -61,4 +61,8 @@ public class ErrorLog { public String toString() { return getErrorsAsString(); } + + public int getErrorCount() { + return errors.size(); + } } 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