/* Copyright (c) 2008 Arno Haase, Andr� Arnold. 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: Arno Haase - initial API and implementation Andr� Arnold */ package org.eclipse.xtend.middleend.xtend.internal.xtend; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.emf.mwe.core.issues.Issues; import org.eclipse.internal.xtend.xtend.ast.Check; import org.eclipse.internal.xtend.xtend.ast.ExtensionFile; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.BackendTypesystem; import org.eclipse.xtend.backend.common.ExpressionBase; import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.common.QualifiedName; import org.eclipse.xtend.backend.common.SourcePos; import org.eclipse.xtend.backend.common.SyntaxConstants; import org.eclipse.xtend.backend.expr.AndExpression; import org.eclipse.xtend.backend.expr.IfExpression; import org.eclipse.xtend.backend.expr.InitClosureExpression; import org.eclipse.xtend.backend.expr.InvocationOnObjectExpression; import org.eclipse.xtend.backend.expr.LiteralExpression; import org.eclipse.xtend.backend.expr.LocalVarEvalExpression; import org.eclipse.xtend.backend.expr.OrExpression; import org.eclipse.xtend.backend.expr.SequenceExpression; import org.eclipse.xtend.backend.functions.SourceDefinedFunction; import org.eclipse.xtend.backend.syslib.SysLibNames; import org.eclipse.xtend.backend.types.builtin.BooleanType; import org.eclipse.xtend.backend.types.builtin.CollectionType; import org.eclipse.xtend.backend.types.builtin.ObjectType; import org.eclipse.xtend.expression.ExecutionContext; import org.eclipse.xtend.expression.Variable; import org.eclipse.xtend.middleend.xtend.OldHelper; import org.eclipse.xtend.middleend.xtend.internal.OldExpressionConverter; import org.eclipse.xtend.middleend.xtend.internal.TypeToBackendType; /** * * @author Arno Haase (http://www.haase-consulting.com) * @author Andr� Arnold */ public final class CheckConverter { public static final QualifiedName ALL_CHECKS_FUNCTION_NAME = new QualifiedName ("CheckAllChecks"); /** * name of the parameter in which the Issues are passed to the check function. This is not intended to * be edited in a source file, so it is chosen not to be a valid identifier to avoid name clashes. */ public static final String ISSUES_PARAM_NAME = "$issues"; public static final String ALL_OBJECTS_PARAM_NAME = "$allObjects"; private final TypeToBackendType _typeConverter; private final ExecutionContext _emptyExecutionContext; public CheckConverter (ExecutionContext ctx, TypeToBackendType typeConverter) { _emptyExecutionContext = ctx; _typeConverter = typeConverter; } public NamedFunction createCheckFunction (BackendTypesystem ts, ExtensionFile extensionFile) { final OldExpressionConverter exprConv = new OldExpressionConverter (_emptyExecutionContext.cloneWithResource (extensionFile), _typeConverter, OldHelper.normalizeXtendResourceName (extensionFile.getFullyQualifiedName())); final List<String> paramNames = Arrays.asList (ISSUES_PARAM_NAME, ALL_OBJECTS_PARAM_NAME); final List<BackendType> paramTypes = Arrays.asList (ts.findType (Issues.class), CollectionType.INSTANCE); final List<ExpressionBase> allChecks = new ArrayList<ExpressionBase> (); for (Check chk: extensionFile.getChecks()) { if (!exprConv.hasThis() ) { ExecutionContext oldCtx = exprConv.getExecutionContext(); exprConv.setExecutionContext(oldCtx.cloneWithVariable(new Variable(ExecutionContext.IMPLICIT_VARIABLE, oldCtx.getTypeForName(chk.getType().getValue())))); allChecks.add (convertCheck (chk, exprConv)); exprConv.setExecutionContext(oldCtx); } } final ExpressionBase body = new SequenceExpression (allChecks, exprConv.getSourcePos (extensionFile)); return new NamedFunction (ALL_CHECKS_FUNCTION_NAME, new SourceDefinedFunction (ALL_CHECKS_FUNCTION_NAME, paramNames, paramTypes, BooleanType.INSTANCE, body, false, null)); } private ExpressionBase convertCheck (Check chk, OldExpressionConverter exprConv) { final SourcePos sourcePos = exprConv.getSourcePos (chk); final ExpressionBase preCondExpression = (chk.getGuard() == null) ? exprConv.convert (chk.getConstraint()) : new OrExpression( new InvocationOnObjectExpression (new QualifiedName (SysLibNames.OPERATOR_NOT), Arrays.asList (exprConv.convert (chk.getGuard())), true, sourcePos), new AndExpression (exprConv.convert (chk.getGuard()), exprConv.convert (chk.getConstraint()), sourcePos), sourcePos); final String addIssueMethodName = chk.isErrorCheck() ? "addError" : "addWarning"; final List<ExpressionBase> failureParams = new ArrayList<ExpressionBase> (); failureParams.add (new LocalVarEvalExpression (ISSUES_PARAM_NAME, sourcePos)); failureParams.add (exprConv.convert(chk.getMsg())); failureParams.add (new LocalVarEvalExpression (SyntaxConstants.THIS, sourcePos)); final ExpressionBase failureExpression = new InvocationOnObjectExpression (new QualifiedName (addIssueMethodName), failureParams, true, sourcePos); final ExpressionBase onEachExpression = new IfExpression (preCondExpression, new LiteralExpression (null, sourcePos), failureExpression, sourcePos); final List<ExpressionBase> typeSelectParams = new ArrayList<ExpressionBase> (); typeSelectParams.add (new LocalVarEvalExpression (ALL_OBJECTS_PARAM_NAME, sourcePos)); typeSelectParams.add (new LiteralExpression (_typeConverter.convertToBackendType (chk.getType()), sourcePos)); final ExpressionBase typeSelectExpression = new InvocationOnObjectExpression (new QualifiedName (SysLibNames.TYPE_SELECT), typeSelectParams, true, sourcePos); final List<ExpressionBase> collectParams = new ArrayList<ExpressionBase> (); collectParams.add (typeSelectExpression); collectParams.add (new InitClosureExpression (Arrays.asList(SyntaxConstants.THIS), Arrays.asList(ObjectType.INSTANCE), onEachExpression, sourcePos)); return new InvocationOnObjectExpression (new QualifiedName (SysLibNames.COLLECT), collectParams, true, sourcePos); } }