public static Datatype readFileType(File file) throws IOException {
BinaryFile rf = new BinaryFile( file, "r" );
try {
- Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class );
- return (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( rf );
+ return (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
} finally {
rf.close();
}
public static Object readFile(File file, Binding binding) throws IOException {
BinaryFile rf = new BinaryFile( file, "r" );
try {
- Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class );
- Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( rf );
+ Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
if (type.equals(binding.type())) {
return Bindings.getSerializerUnchecked( binding ).deserialize(rf);
rf.close();
}
}
+
+ public static Object readFileTypeAdapting(File file, Binding binding) throws IOException {
+ BinaryFile rf = new BinaryFile( file, "r" );
+ try {
+ Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
+
+ if (type.equals(binding.type())) {
+ return Bindings.getSerializerUnchecked( binding ).deserialize(rf);
+ } else {
+ try {
+ Binding fileContentBinding = Bindings.getMutableBinding(type);
+ Adapter adapter = Bindings.getTypeAdapter(fileContentBinding, binding);
+ Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize(rf);
+ return adapter.adapt( value );
+ } catch (AdapterConstructionException e) {
+ throw new IOException(e);
+ } catch (AdaptException e) {
+ throw new IOException(e);
+ }
+ }
+ } finally {
+ rf.close();
+ }
+ }
/**
* Read a file to an object.
public static void readFile(File file, RecordBinding binding, Object dst) throws IOException {
BinaryFile rf = new BinaryFile( file, "r" );
try {
- Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class );
- Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( rf );
+ Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
if (type.equals(binding.type())) {
Serializer s = Bindings.getSerializerUnchecked( binding );
*/
public static Object readFile(InputStream is, Binding binding) throws IOException {
BinaryReadable readable = InputStreamReadable.readFully( is );
- Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class );
- Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( readable );
+ Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( readable );
if (!type.equals(binding.type())) {
try {
*/
public static Object readFile(InputStream is, long streamLength, Binding binding) throws IOException {
BinaryReadable readable = new InputStreamReadable( is, streamLength );
- Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class );
- Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( readable );
+ Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( readable );
if (!type.equals(binding.type())) {
try {
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.layer0.request;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.simantics.datatypes.literal.GUID;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.ResourceRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.layer0.Layer0;
+
+/**
+ * Get a map from GUIDs to the children of the given resource.
+ */
+public final class ChildrenByIdentifier extends ResourceRead<Map<GUID, Resource>> {
+ public ChildrenByIdentifier(Resource resource) {
+ super(resource);
+ }
+
+ @Override
+ public Map<GUID, Resource> perform(ReadGraph graph) throws DatabaseException {
+ Map<GUID, Resource> result = new HashMap<>();
+ Layer0 L0 = Layer0.getInstance(graph);
+ Collection<Resource> children = graph.getObjects(resource, L0.ConsistsOf);
+ for (Resource child : children) {
+ GUID guid = graph.getPossibleRelatedValue(child, L0.identifier, GUID.BINDING);
+ if (guid != null)
+ result.put(guid, child);
+ }
+
+ return result;
+ }
+}
import org.simantics.diagram.stubs.DiagramResource;
import org.simantics.diagram.synchronization.ErrorHandler;
import org.simantics.g2d.canvas.ICanvasContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.THashMap;
*/
public class DiagramContentRequest extends BaseRequest<Resource, DiagramContents> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DiagramContentRequest.class);
+
int previousElementCount = 32;
ErrorHandler errorHandler;
// These help loading result.elements in the correct order.
final AtomicInteger index = new AtomicInteger();
final TIntArrayList unrecognizedElementIndices = new TIntArrayList();
-
+
+ if (!g.hasStatement(data)) {
+ LOGGER.warn("Most likely diagram is being removed and therefore ordered list can not be found for {}", data);
+ return new DiagramContents(); // or null, I don't know
+ }
Collection<Resource> components = OrderedSetUtils.toList(g, data);
DiagramContents res = g.syncRequest((AsyncRead<DiagramContents>)(graph, procedure) -> {
import org.simantics.diagram.stubs.DiagramResource;
import org.simantics.layer0.Layer0;
import org.simantics.scenegraph.profile.Group;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* @author Tuukka Lehtonen
*/
public class TypeGroup implements Group {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TypeGroup.class);
+
private final Collection<Resource> types;
private final String name;
// for (Resource t : types)
// System.out.println("\t" + NameUtils.getSafeName(graph, t, true));
- Collection<Resource> elements = graph.syncRequest(new OrderedSet(realDiagram));
- for (Resource element : elements) {
-// System.out.println("checking element " + NameUtils.getSafeName(graph, element, true));
- Collection<Resource> elementTypes = graph.getTypes(element);
- if (!Collections.disjoint(types, elementTypes))
- result.add(element);
+ if (graph.hasStatement(realDiagram)) {
+ Collection<Resource> elements = graph.syncRequest(new OrderedSet(realDiagram));
+ for (Resource element : elements) {
+ // System.out.println("checking element " + NameUtils.getSafeName(graph, element, true));
+ Collection<Resource> elementTypes = graph.getTypes(element);
+ if (!Collections.disjoint(types, elementTypes))
+ result.add(element);
+ }
+ } else {
+ LOGGER.warn("Most likely after deleting a diagram or something therefore no ordered set can be found for {}", realDiagram);
}
-
return result;
}
SCLContext sclContext = SCLContext.getCurrent();
Object oldGraph = sclContext.get("graph");
try {
- CompileSCLMonitorRequest compileSCLMonitorRequest = new CompileSCLMonitorRequest(graph, context) {
- @Override
- protected String getExpressionText(ReadGraph graph) throws DatabaseException {
- return expression;
- }
- };
+ CompileSCLMonitorRequest compileSCLMonitorRequest = new ValidationCompilationRequest(graph, context, expression);
Function1<Variable,Object> exp = graph.syncRequest(compileSCLMonitorRequest);
sclContext.put("graph", graph);
//return exp.apply(context.getParent(graph));
return 100.0;
}
+ private static final class ValidationCompilationRequest extends CompileSCLMonitorRequest {
+ private final String expression;
+
+ private ValidationCompilationRequest(ReadGraph graph, Variable context, String expression)
+ throws DatabaseException {
+ super(graph, context);
+ this.expression = expression;
+ }
+
+ @Override
+ protected String getExpressionText(ReadGraph graph) throws DatabaseException {
+ return expression;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + 37 * expression.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj) && ((ValidationCompilationRequest)obj).expression.equals(expression);
+ }
+ }
+
}
\ No newline at end of file
return false;
if (DatabaseJob.inProgress())
return false;
- IResourceEditorInput input = (IResourceEditorInput) activeEditor.getEditorInput();
- return TypicalPropertyTester.isTypicalInstanceEditor(Simantics.getSession(), input.getResource());
+ if (activeEditor.getEditorInput() instanceof IResourceEditorInput) {
+ IResourceEditorInput input = (IResourceEditorInput) activeEditor.getEditorInput();
+ return TypicalPropertyTester.isTypicalInstanceEditor(Simantics.getSession(), input.getResource());
+ } else {
+ return false;
+ }
}
@Execute
return false;
if (DatabaseJob.inProgress())
return false;
- IResourceEditorInput input = (IResourceEditorInput) activeEditor.getEditorInput();
- return TypicalPropertyTester.isTypicalMasterEditor(Simantics.getSession(), input.getResource());
+ if (activeEditor.getEditorInput() instanceof IResourceEditorInput) {
+ IResourceEditorInput input = (IResourceEditorInput) activeEditor.getEditorInput();
+ return TypicalPropertyTester.isTypicalMasterEditor(Simantics.getSession(), input.getResource());
+ } else {
+ return false;
+ }
}
@Execute
#430121
"""
-addSubscription :: Variable -> <WriteGraph,ReadGraph> Subscription
+addSubscription :: Variable -> <WriteGraph> Subscription
addSubscription variable = do
model = modelOfVariable variable
default = defaultSubscriptionFolder model
*******************************************************************************/
package org.simantics.modeling;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.simantics.databoard.Bindings;
import org.simantics.databoard.util.URIStringUtils;
+import org.simantics.datatypes.literal.GUID;
import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
import org.simantics.db.Statement;
import org.simantics.db.WriteGraph;
import org.simantics.db.common.NamedResource;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
import org.simantics.db.common.utils.NameUtils;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.adapter.Instances;
+import org.simantics.db.layer0.request.ChildrenByIdentifier;
import org.simantics.db.layer0.util.Layer0Utils;
import org.simantics.diagram.stubs.DiagramResource;
import org.simantics.layer0.Layer0;
import org.simantics.structural2.modelingRules.AllowedConnectionTypes;
import org.simantics.utils.ObjectUtils;
import org.simantics.utils.datastructures.Triple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import gnu.trove.set.hash.THashSet;
/**
* @author Antti Villberg
*/
public class MigrateModel {
+ public static final Logger LOGGER = LoggerFactory.getLogger(MigrateModel.class);
+
public static class MigrationOperation {
public NamedResource instanceToMigrate;
private Resource getPossibleReplacement(ReadGraph graph, Resource type, Resource predicate) throws DatabaseException {
Layer0 L0 = Layer0.getInstance(graph);
+
+ // Try to find a relation with the same GUID
+ GUID guid = graph.getPossibleRelatedValue(predicate, L0.identifier, GUID.BINDING);
+ Map<GUID, Resource> children = graph.syncRequest(new ChildrenByIdentifier(type), TransientCacheListener.instance());
+ Resource replacement = children.get(guid);
+ if (replacement != null)
+ return replacement;
+
+ // Fall back to using relation name
String name = graph.getPossibleRelatedValue(predicate, L0.HasName, Bindings.STRING);
if(name == null) return null;
Resource child = Layer0Utils.getPossibleChild(graph, type, name);
problems.append(" " + name + " was a property in the source type\n");
continue;
}
+
String sourceValueType = graph.getPossibleRelatedValue(predicate, L0.RequiresValueType, Bindings.STRING);
String replacementValueType = graph.getPossibleRelatedValue(replacement, L0.RequiresValueType, Bindings.STRING);
if(!ObjectUtils.objectEquals(sourceValueType, replacementValueType)) {
Resource replacement = getPossibleReplacement(graph, type, predicate);
graph.deny(stm);
if(replacement == null) continue;
- graph.claim(stm.getSubject(), replacement, stm.getObject());
+
+ // Filter out incompatible literal types.
+ // TODO: Show warning in UI
+ Resource object = stm.getObject();
+ Resource replacementRange = graph.getPossibleObject(replacement, L0.HasRange);
+ if (replacementRange != null && !graph.isInstanceOf(object, replacementRange)) {
+ String instanceName = graph.getPossibleRelatedValue(instanceToMigrate, L0.HasName);
+ if (instanceName == null) instanceName = "<unknown>";
+
+ String rangeName = graph.getPossibleRelatedValue(replacementRange, L0.HasName);
+ if (rangeName == null) rangeName = "<unknown>";
+
+ Resource literalType= graph.getPossibleType(object, L0.Value);
+ String literalTypeName = literalType != null ? graph.getPossibleRelatedValue(literalType, L0.HasName) : null;
+ if (literalTypeName == null) literalTypeName = "<unknown>";
+
+ String replacementName = graph.getRelatedValue(replacement, L0.HasName);
+ LOGGER.warn("{}: Ignored incompatible value of type {} for predicate {} with range {}", instanceName, literalTypeName, replacementName, rangeName);
+
+ continue;
+ }
+
+ graph.claim(stm.getSubject(), replacement, object);
}
}
destructiveConnectionRule()
),
// If component does not have a corresponding element in the diagram, remove it
- and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))
+ and(
+ deny(b(new Tag(MOD.ComponentToElement), Component)),
+ deny(b(new Tag(STR.IsConnectedTo), Component)),
+ deny(exists(Component)))
)
)
),
if_(b(mappedFromConnector, Component), // handle only mapped components
query(
unless(bf(MOD.ComponentToConnector, Component, Connector),
- and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))
+ and(
+ deny(b(new Tag(MOD.ComponentToElement), Component)),
+ deny(b(new Tag(STR.IsConnectedTo), Component)),
+ deny(exists(Component)))
)
)
)
--- /dev/null
+// This module is meant to be imported with namespace
+import "SCL/ModuleRepository"
+import "SafeDynamic"
+
+importJava "org.simantics.scl.compiler.commands.CommandSession" where
+ data CommandSession
+
+ @JavaName "<init>"
+ create :: ModuleRepository -> <Proc> CommandSession
+
+ execute :: CommandSession -> String -> <Proc> ()
+
+ @JavaName getVariableValueAndType
+ get :: CommandSession -> String -> <Proc> Maybe SafeDynamic
+ @JavaName setVariable
+ set :: CommandSession -> String -> SafeDynamic -> <Proc> ()
+
+ @JavaName removeVariable
+ remove :: CommandSession -> String -> <Proc> ()
\ No newline at end of file
import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.constants.StringConstant;
+import org.simantics.scl.compiler.dynamic.SafeDynamic;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EBlock;
import org.simantics.scl.compiler.elaboration.expressions.EConstant;
import org.simantics.scl.compiler.environment.LocalEnvironment;
import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
import org.simantics.scl.compiler.errors.CompilationError;
+import org.simantics.scl.compiler.errors.ErrorSeverity;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.codegen.utils.NameMangling;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
*/
private boolean validateOnly;
+ public CommandSession(ModuleRepository moduleRepository) {
+ this(moduleRepository, SCLReporting.getCurrentReportingHandler());
+ }
+
public CommandSession(ModuleRepository moduleRepository, SCLReportingHandler handler) {
this.moduleRepository = moduleRepository;
this.defaultHandler = new PrintDecorator(
defaultHandler.printError(failure.toString());
if(failure.reason instanceof CompilationError[])
for(CompilationError error : (CompilationError[])failure.reason) {
- defaultHandler.printError(" " + error.description);
+ if(error.severity != ErrorSeverity.WARNING)
+ defaultHandler.printError(" " + error.description);
}
}
for(CommandSessionImportEntry entry : importEntries)
variableTypes.put(name, type);
}
+ public void setVariable(String name, SafeDynamic typeAndValue) {
+ variableValues.put(name, typeAndValue.value);
+ variableTypes.put(name, typeAndValue.type_);
+ }
+
public Object getVariableValue(String name) {
return variableValues.get(name);
}
return variableTypes.get(name);
}
+ public SafeDynamic getVariableValueAndType(String name) {
+ Type type = variableTypes.get(name);
+ if(type == null)
+ return null;
+ Object value = variableValues.get(name);
+ return new SafeDynamic(type, value);
+ }
+
public void removeVariable(String name) {
variableValues.remove(name);
variableTypes.remove(name);
formatException(handler, e);
}
}
-
+
public static CompilationError[] validate(ModuleRepository moduleRepository,StringReader commandReader) {
CommandSession session = new CommandSession(moduleRepository, null);
return session.validate(commandReader);
if(td.equals(TypeDesc.VOID))
throw new InternalCompilerError();
}
+ if( (returnTypeDesc == null) != (parameterTypeDescs == null) )
+ throw new IllegalArgumentException("Either specify both returnTypeDesc and parameterTypeDescs or neither");
ClassBuilder.checkClassName(className);
this.className = className;
this.methodName = methodName;
}
@Override
- public Type applyExact(MethodBuilder mb, Val[] parameters) {
- if(returnTypeDesc == null) {
+ public Type applyExact(MethodBuilder mb, Val[] parameters) {
+ if(returnTypeDesc == null || parameterTypeDescs == null) {
+ // This method may be called from multiple threads at the same time when returnTypeDesc
+ // and parameterTypeDescs are uninitialized. Double initialization is OK in this case,
+ // but because there are two fields, we have to check that both are initialized.
JavaTypeTranslator tt = mb.getJavaTypeTranslator();
returnTypeDesc = tt.toTypeDesc(returnType);
parameterTypeDescs = JavaTypeTranslator.filterVoid(
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.ExpressionVisitor;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.ForVariablesUsesVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.StandardExpressionVisitor;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.parsing.Symbol;
newLiterals[i] = literals[i].replace(context);
return new CHRQuery(location, newLiterals);
}
+
+ public void accept(ExpressionVisitor visitor) {
+ for(CHRLiteral literal : literals) {
+ if(literal == null || literal.parameters == null)
+ continue; // FIXME why this happens?
+ for(Expression parameter : literal.parameters) {
+ if(parameter == null)
+ continue; // FIXME why this happens?
+ parameter.accept(visitor);
+ }
+ }
+ }
}
package org.simantics.scl.compiler.elaboration.chr;
import java.util.ArrayList;
+import java.util.HashMap;
import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.elaboration.chr.plan.CHRSearchPlan;
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.EAsPattern;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.ExpressionVisitor;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.StandardExpressionVisitor;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.parsing.Symbol;
import org.simantics.scl.compiler.types.Types;
context.disallowNewExistentials();
body.resolve(context);
existentialVariables = context.popExistentialFrame();
+
+ warnForExistentialsUsedOnlyOnce(context);
+ }
+
+ private static final Object NEVER_USED = new Object();
+
+ private void warnForExistentialsUsedOnlyOnce(TranslationContext context) {
+ // Initialize the hash map
+ HashMap<Variable, Object> usageCount = new HashMap<>(existentialVariables.length);
+ for(Variable var : existentialVariables)
+ if(!var.getName().equals("_"))
+ usageCount.put(var, NEVER_USED);
+
+ // Collect variable uses
+ ExpressionVisitor visitor = new StandardExpressionVisitor() {
+ private void handle(Expression expression, Variable variable) {
+ Object object = usageCount.remove(variable);
+ if(object == NEVER_USED)
+ usageCount.put(variable, expression);
+ }
+ @Override
+ public void visit(EVariable expression) {
+ if(expression.variable != null)
+ handle(expression, expression.variable);
+ }
+ @Override
+ public void visit(EAsPattern expression) {
+ expression.pattern.accept(this);
+ handle(expression, expression.var);
+ }
+ };
+ head.accept(visitor);
+ body.accept(visitor);
+
+ // Report as warnings
+ usageCount.forEach((variable, expression_) -> {
+ if(!(expression_ instanceof Expression))
+ return; // Should never happen
+ Expression expression = (Expression)expression_;
+ if(context.isExpandedFromWildcard(expression))
+ return;
+
+ context.getErrorLog().logWarning(expression.location,
+ "Existential variable " + variable.getName() + " is referred only once. Replace by _ if this is a wildcard.");
+ });
+
}
public void checkType(TypingContext context) {
TIntArrayList chrConstraintFrames = new TIntArrayList();
ArrayList<CHRConstraintEntry> chrConstraintEntries = new ArrayList<CHRConstraintEntry>();
+ private THashSet<Expression> expandedFromWildcard;
+
public CHRRuleset currentRuleset;
public ModuleDebugInfo moduleDebugInfo;
variable = new Variable(name);
variables.put(name, variable);
existentialFrame.variables.add(name);
- return new EVariable(variable);
+ return new EVariable(location, variable);
}
case '_': {
if(name.length()==1) {
return Environments.getRuleset(environment, name);
}
+ /**
+ * Tells that new existential variables are no longer allowed in this context.
+ */
public void disallowNewExistentials() {
getCurrentExistentialFrame().disallowNewExistentials = true;
}
+
+ /**
+ * Marks that the expression is a result of expanding .. wildcard pattern in records.
+ */
+ public void addExpandedFromWildcard(Expression expression) {
+ if(expandedFromWildcard == null)
+ expandedFromWildcard = new THashSet<>();
+ expandedFromWildcard.add(expression);
+ }
+
+ /**
+ * Asks if the expression is a result of expanding .. wildcard pattern in records.
+ */
+ public boolean isExpandedFromWildcard(Expression expression) {
+ if(expandedFromWildcard == null)
+ return false;
+ else
+ return expandedFromWildcard.contains(expression);
+ }
}
String variableName = fieldNames[i];
if(chrLiteral)
variableName = "?" + variableName;
- parameters[i] = new EVar(wildcardField.location, variableName);
+ EVar expandedVar = new EVar(wildcardField.location, variableName);
+ parameters[i] = expandedVar;
+ context.addExpandedFromWildcard(expandedVar);
}
}
if(!recordMap.isEmpty()) {
@Override
public Expression resolve(TranslationContext context) {
- return context.resolveVariable(location, name);
+ Expression resolved = context.resolveVariable(location, name);
+ if(context.isExpandedFromWildcard(this))
+ context.addExpandedFromWildcard(resolved);
+ return resolved;
}
@Override
@Override
public Expression resolveAsPattern(TranslationContext context) {
- return context.resolvePattern(this);
+ Expression resolved = context.resolvePattern(this);
+ if(context.isExpandedFromWildcard(this))
+ context.addExpandedFromWildcard(resolved);
+ return resolved;
}
@Override
package org.simantics.scl.compiler.elaboration.expressions;
+@FunctionalInterface
public interface VariableProcedure {
void execute(long location, Variable variable);
}
+import "JavaBuiltin" as Java
+
importJava "java.util.Iterator" where
data T a
loop ()
else ()
+@inline
+iterI :: (Integer -> a -> <e> b) -> T a -> <Proc,e> ()
+iterI f it = loop 0
+ where
+ loop i =
+ if hasNext it
+ then do
+ f i (next it)
+ loop (Java.iadd i 1)
+ else ()
+
@inline
iterB :: (a -> <e> Boolean) -> T a -> <Proc,e> Boolean
iterB f it = loop ()
"""
class (Monad m) => MonadZero m where
mzero :: m a
+ mfilter :: (a -> Boolean) -> m a -> m a
+
+ mfilter p m = m >>= (\x -> if p x then return x else mzero)
"Injects a boolean test to a type beloning to `MonadZero`."
guard :: MonadZero m => Boolean -> m ()
instance MonadE [] where
bindE l f = concatMap f l
+
+/// MZeroE ///
+
+class (MonadE m, MonadZero m) => MonadZeroE m where
+ filter :: (a -> <e> Boolean) -> m a -> <e> m a
+
+ filter p m = m `bindE` (\x -> if p x then return x else mzero)
+instance MonadZeroE [] where
+ filter = filterList
+
+instance MonadZeroE Maybe where
+ filter p (Just x) | not (p x) = Nothing
+ filter _ m = m
+
/// Category ///
"Identity function."
snd (x,y) = y
@inline
-mapFst :: (a -> b) -> (a,c) -> (b,c)
+mapFst :: (a -> <e> b) -> (a,c) -> <e> (b,c)
mapFst f (x,y) = (f x, y)
@inline
-mapSnd :: (a -> b) -> (c,a) -> (c,b)
+mapSnd :: (a -> <e> b) -> (c,a) -> <e> (c,b)
mapSnd f (x,y) = (x, f y)
instance (Ord a, Ord b) => Ord (a, b) where
`filter pred lst` returns those elements of `lst` that the predicate `pred` accepts. For example
filter (> 3) [1, 2, 3, 4, 5, 6] = [4, 5, 6]
-"""
+"""
@inline
-filter :: (a -> <e> Boolean) -> [a] -> <e> [a]
-filter p l = build (\empty cons -> foldl (\cur x -> if p x then cons cur x else cur) empty l)
+filterList :: (a -> <e> Boolean) -> [a] -> <e> [a]
+filterList p l = build (\empty cons -> foldl (\cur x -> if p x then cons cur x else cur) empty l)
"""
Takes those elements of the input list that match `(Just x)` and adds the contents to the resulting list. For example,
iterator :: T a -> Iterator.T a
@inline
-iter :: (a -> <e> ()) -> T a -> <e> ()
+iter :: (a -> <e> b) -> T a -> <e> ()
iter f s = runProc (Iterator.iter f (iterator s))
@inline
iterB :: (a -> <e> Boolean) -> T a -> <e> Boolean
iterB f s = runProc (Iterator.iterB f (iterator s))
+@inline
+iterI :: (Integer -> a -> <e> b) -> T a -> <e> ()
+iterI f s = runProc (Iterator.iterI f (iterator s))
+
@inline
fold :: (a -> b -> <e> a) -> a -> T b -> <e> a
fold f init s = runProc (Iterator.fold f init (iterator s))
+
+importJava "java.util.Collections" where
+ singleton :: a -> T a
+
+ @JavaName emptySet
+ empty :: T a
+
+importJava "gnu.trove.set.hash.THashSet" where
+ @JavaName "<init>"
+ fromList :: [a] -> T a
+
+importJava "java.util.ArrayList" where
+ @JavaName "<init>"
+ toList :: T a -> [a]
--- /dev/null
+import "Prelude"
+import "MSet" as MSet
+import "Set" as Set
+
+instance Functor Set.T where
+ fmap = map
+
+instance FunctorE Set.T where
+ map f set = runProc do
+ result = MSet.create ()
+ Set.iter (\x -> MSet.add result $ f x) set
+ MSet.freeze result
+
+ iter = Set.iter
+ iterI = Set.iterI
+
+instance Monad Set.T where
+ return = Set.singleton
+ (>>=) = bindE
+
+@private
+importJava "java.util.Set" where
+ @JavaName addAll
+ addAll' :: MSet.T a -> Set.T a -> <Proc> Boolean
+
+instance MonadE Set.T where
+ set `bindE` f = runProc do
+ result = MSet.create ()
+ Set.iter (\x -> addAll' result $ f x) set
+ MSet.freeze result
+
+instance MonadZero Set.T where
+ mzero = Set.empty
+
+instance MonadZeroE Set.T where
+ filter p set = runProc do
+ result = MSet.create ()
+ Set.iter (\x ->
+ if p x
+ then ignore $ MSet.add result x
+ else ()
+ ) set
+ MSet.freeze result
+
+instance (Show a) => Show (Set.T a) where
+ sb <+ set = do
+ sb << "{"
+ Set.iterI (\i x -> (if i > 0 then sb << ", " else sb) <+ x) set
+ sb << "}"
+
+instance Additive (Set.T a) where
+ zero = Set.empty
+ a + b = runProc do
+ result = MSet.create ()
+ Set.iter (MSet.add result) a
+ Set.iter (MSet.add result) b
+ MSet.freeze result
+ sum sets = runProc do
+ result = MSet.create ()
+ iter (Set.iter (MSet.add result)) sets
+ MSet.freeze result
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-import "Set" as Set
-import "MSet" as MSet
-import "MList" as MList
-
-fromList :: [a] -> Set.T a
-fromList l = runProc (MSet.freeze $ MSet.fromList l)
-
-toList :: Set.T a -> [a]
-toList s = runProc do
- result = MList.createC (Set.size s)
- Set.iter (MList.add result) s
- MList.freeze result
\ No newline at end of file
include "File" as File
include "Serialization" as Serialization
include "Set" as Set
-include "SetUtils" as Set
+include "SetClasses"
//include "Map" as Map
include "MMap" as MMap
include "MSet" as MSet
private static final Logger LOGGER = LoggerFactory.getLogger(SCLReporting.class);
+ public static SCLReportingHandler getCurrentReportingHandler() {
+ SCLReportingHandler handler = ((SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER));
+ return handler == null ? SCLReportingHandler.DEFAULT : handler;
+ }
+
public static void print(String text) {
SCLReportingHandler handler = ((SCLReportingHandler)SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER));
if(handler != null)
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.handlers.HandlerUtil;
import org.simantics.Simantics;
+import org.simantics.databoard.type.Datatype;
import org.simantics.db.ReadGraph;
import org.simantics.db.RequestProcessor;
import org.simantics.db.Resource;
import org.simantics.db.common.primitiverequest.Types;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.request.PossibleGUID;
-import org.simantics.db.layer0.request.PossibleVariableGUID;
import org.simantics.db.layer0.request.PossibleURI;
+import org.simantics.db.layer0.request.PossibleVariableGUID;
import org.simantics.db.layer0.request.PossibleVariableRepresents;
import org.simantics.db.layer0.request.VariableRead;
import org.simantics.db.layer0.request.VariableURI;
if(var != null) {
String uri = processor.syncRequest(new VariableURI(var));
String guid = processor.syncRequest(new PossibleVariableGUID(var));
+
+ Set<String> classifications = processor.syncRequest(new VariableRead<Set<String>>(var) {
+ @Override
+ public Set<String> perform(ReadGraph graph) throws DatabaseException {
+ return var.getClassifications(graph);
+ }
+ });
+ String classificationsStr = toJSONStringArray(new ArrayList<>(classifications));
+
+ Datatype datatype = processor.syncRequest(new VariableRead<Datatype>(var) {
+ @Override
+ public Datatype perform(ReadGraph graph) throws DatabaseException {
+ return var.getPossibleDatatype(graph);
+ }
+ });
+
return toJSONObjectString(
"type", "\"Variable\"",
"uri", safeQuotedString(uri),
"guid", safeQuotedString(guid),
"resourceId", res == null ? "" : Long.toString(res.getResourceId()),
- "typeResources", typesStr);
+ "typeResources", typesStr,
+ "classifications", classificationsStr,
+ "datatype", safeQuotedString(datatype != null ? datatype.getClass().getName() : null));
}
if(res != null) {
String uri = processor.syncRequest(new PossibleURI(res));
when ?x <- ?y
then True
--
+3:10-3:12: Existential variable ?x is referred only once. Replace by _ if this is a wildcard.
3:10-3:18: Cannot solve the query.
+3:16-3:18: Existential variable ?y is referred only once. Replace by _ if this is a wildcard.
--
import "Prelude"
where
X ?x => Y ?y
--
+6:7-6:9: Existential variable ?x is referred only once. Replace by _ if this is a wildcard.
6:15-6:17: New existential variables can be defined only in queries.
\ No newline at end of file