-package org.simantics.scl.compiler.elaboration.expressions;
-
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc;
-
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
-import org.simantics.scl.compiler.elaboration.java.EqRelation;
-import org.simantics.scl.compiler.elaboration.query.QAtom;
-import org.simantics.scl.compiler.elaboration.query.Query;
-import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
-import org.simantics.scl.compiler.elaboration.relations.SCLEntityType.Attribute;
-import org.simantics.scl.compiler.elaboration.relations.SCLEntityType.AttributeBinding;
-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.Token;
-
-import gnu.trove.map.hash.THashMap;
-
-public class EEntityTypeAnnotation extends ASTExpression {
-
- Expression expression;
- Token entityTypeName;
- SCLEntityType entityType;
- Query query; // optional
- THashMap<String, AttributeBinding> attributeBindingMap;
-
- public EEntityTypeAnnotation(Expression expression, Token entityTypeName,
- Query query) {
- this.expression = expression;
- this.entityTypeName = entityTypeName;
- this.query = query;
- }
-
- @Override
- public Expression resolve(TranslationContext context) {
- // Resolve a subexpression
- expression = expression.resolve(context);
-
- // Check that we are inside a query
- if(context.currentPreQuery == null) {
- context.getErrorLog().log(location, "Entity type annotations can be used only in queries.");
- return new EError(location);
- }
-
- // Resolve entity type
- try {
- entityType = Environments.getEntityType(context.getEnvironment(), entityTypeName.text);
- } catch (AmbiguousNameException e) {
- context.getErrorLog().log(location, e.getMessage());
- return new EError(location);
- }
- if(entityType == null) {
- context.getErrorLog().log(location, "Couldn't resolve entity type " + entityTypeName.text + ".");
- return new EError(location);
- }
-
- // Rewrite the subexpression as a separate query if it is not a variable
- Variable base;
- if(expression instanceof EVariable)
- base = ((EVariable)expression).variable;
- else {
- base = new Variable("?" + entityTypeName.text);
- context.currentPreQuery.extraVariables.add(base);
- context.currentPreQuery.sideQueries.add(loc(expression.location,
- new QAtom(EqRelation.INSTANCE, new EVariable(base), expression)));
- expression = loc(expression.location, new EVariable(base));
- }
-
- // Resolve a related query if it exists
- if(query != null) {
- EEntityTypeAnnotation oldEntityTypeAnnotation = context.currentEntityTypeAnnotation;
- attributeBindingMap = new THashMap<String, AttributeBinding>();
- context.currentEntityTypeAnnotation = this;
- query = query.resolve(context);
- context.currentPreQuery.sideQueries.add(query);
- context.currentEntityTypeAnnotation = oldEntityTypeAnnotation;
- AttributeBinding[] attributeBindings;
- if(attributeBindingMap.isEmpty())
- attributeBindings = AttributeBinding.EMPTY_ARRAY;
- else {
- attributeBindings = attributeBindingMap.values().toArray(new AttributeBinding[attributeBindingMap.size()]);
- for(AttributeBinding binding : attributeBindings)
- context.currentPreQuery.extraVariables.add(binding.variable);
- }
- context.currentPreQuery.sideQueries.add(entityType.generateQuery(context, base, attributeBindings));
- }
- else
- context.currentPreQuery.sideQueries.add(entityType.generateQuery(context, base, AttributeBinding.EMPTY_ARRAY));
- return expression;
- }
-
- @Override
- public void setLocationDeep(long loc) {
- if(location == Locations.NO_LOCATION) {
- location = loc;
- expression.setLocationDeep(loc);
- query.setLocationDeep(loc);
- }
- }
-
- public Expression resolveAttribute(TranslationContext context, long location, String name) {
- AttributeBinding binding = attributeBindingMap.get(name);
- if(binding == null) {
- Attribute attribute = entityType.getAttribute(name);
- if(attribute == null) {
- context.getErrorLog().log(location, "Attribute " + name + " is not defined in entity type " + entityTypeName.text + ".");
- return new EError(location);
- }
- binding = new AttributeBinding(attribute, new Variable("#"+name));
- attributeBindingMap.put(name, binding);
- }
- return new EVariable(binding.variable);
- }
-
- @Override
- public Expression accept(ExpressionTransformer transformer) {
- return transformer.transform(this);
- }
-
-}