Skip to content

Commit

Permalink
[lang] Add @pure annotation on no-side-effect actions.
Browse files Browse the repository at this point in the history
see #191

Signed-off-by: Stéphane Galland <galland@arakhne.org>
  • Loading branch information
gallandarakhneorg committed Oct 15, 2015
1 parent 0224df4 commit 269d35a
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 104 deletions.
12 changes: 10 additions & 2 deletions plugins/io.sarl.lang/src/io/sarl/lang/SARLRuntimeModule.java
Expand Up @@ -124,7 +124,8 @@
import io.sarl.lang.jvmmodel.SarlJvmModelAssociations;
import io.sarl.lang.sarl.SarlFactory;
import io.sarl.lang.scoping.batch.SARLImplicitlyImportedFeatures;
import io.sarl.lang.typing.SARLExpressionHelper;
import io.sarl.lang.typing.ExtendedXExpressionHelper;
import io.sarl.lang.typing.SARLXExpressionHelper;
import io.sarl.lang.validation.DefaultFeatureCallValidator;
import io.sarl.lang.validation.FeatureCallValidator;
import io.sarl.lang.validation.SARLConfigurableIssueCodesProvider;
Expand Down Expand Up @@ -323,7 +324,14 @@ public Class<? extends IResourceChangeRegistry> bindResourceChangeRegistry() {
* @return the type of the XExpression helper.
*/
public Class<? extends XExpressionHelper> bindXExpressionHelper() {
return SARLExpressionHelper.class;
return SARLXExpressionHelper.class;
}

/** Replies the type of the extended elper for using XExpressions.
* @return the type of the XExpression helper.
*/
public Class<? extends ExtendedXExpressionHelper> bindExtendedXExpressionHelper() {
return ExtendedXExpressionHelper.class;
}

@Override
Expand Down
Expand Up @@ -116,7 +116,7 @@
import io.sarl.lang.sarl.SarlFormalParameter;
import io.sarl.lang.sarl.SarlRequiredCapacity;
import io.sarl.lang.sarl.SarlSkill;
import io.sarl.lang.typing.SARLExpressionHelper;
import io.sarl.lang.typing.ExtendedXExpressionHelper;
import io.sarl.lang.util.JvmVisibilityComparator;
import io.sarl.lang.util.Utils;

Expand Down Expand Up @@ -160,6 +160,11 @@ public class SARLJvmModelInferrer extends XtendJvmModelInferrer {
*/
@Inject
private CommonTypeComputationServices services;

/** Extended helper for using XExpressions.
*/
@Inject
private ExtendedXExpressionHelper extendedExpressionHelper;

/** JVM type services.
*/
Expand Down Expand Up @@ -934,21 +939,23 @@ protected void transform(final XtendFunction source, final JvmGenericType contai
operation.getExceptions().add(this.typeBuilder.cloneWithProxies(exception));
}

// Create extension / Body
if (!operation.isAbstract() && !container.isInterface()) {
setBody(operation, expression);
}

// Annotations
translateAnnotationsTo(source.getAnnotations(), operation);
if (source.isOverride()
&& !Utils.hasAnnotation(operation, Override.class)
&& this.typeReferences.findDeclaredType(Override.class, source) != null) {
operation.getAnnotations().add(this._annotationTypesBuilder.annotationRef(Override.class));
}
if (!source.isAbstract() &&
(expression == null
|| !((SARLExpressionHelper) this.services.getExpressionHelper()).hasDeepSideEffects(expression))) {
if ((this.extendedExpressionHelper.isPureOperation(operation, expression))
&& (!Utils.hasAnnotation(operation, Pure.class))
&& (this.typeReferences.findDeclaredType(Pure.class, source) != null)) {
// The function is pure
if (!Utils.hasAnnotation(operation, Pure.class)
&& this.typeReferences.findDeclaredType(Pure.class, source) != null) {
operation.getAnnotations().add(this._annotationTypesBuilder.annotationRef(Pure.class));
}
operation.getAnnotations().add(this._annotationTypesBuilder.annotationRef(Pure.class));
}

// Detecting if the action is an early-exit action.
Expand All @@ -969,11 +976,6 @@ protected void transform(final XtendFunction source, final JvmGenericType contai
operation.getAnnotations().add(annotationClassRef(FiredEvent.class, firedEvents));
}

// Create extension / Body
if (!operation.isAbstract() && !container.isInterface()) {
setBody(operation, expression);
}

// 1. Ensure that the Java annotations related to the default value are really present.
// They may be not present if the generated action is a specific version of an inherited
// action with default values for parameters.
Expand Down
@@ -0,0 +1,72 @@
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2015 the original authors or authors.
*
* 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 io.sarl.lang.typing;

import java.util.regex.Pattern;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.util.XExpressionHelper;

/**
* Extended helper on expressions.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @see SARLXExpressionHelper
*/
@Singleton
public class ExtendedXExpressionHelper {

@Inject
private XExpressionHelper expressionHelper;

private final Pattern pattern;

/** Construct the helper.
*/
public ExtendedXExpressionHelper() {
this.pattern = Pattern.compile(XExpressionConstants.SPECIAL_PURE_FUNCTION_NAME_PATTERN);
}

/** Check if the given operation could be annoted with "@Pure".
*
* @param operation - the operation to test.
* @param body - the body of the operation.
* @return <code>true</code> if one of the components of the given expression has a side effect;
* otherwise <code>false</code>.
* @see Pure
*/
public boolean isPureOperation(JvmOperation operation, XExpression body) {
if (operation == null || operation.isAbstract() || body == null) {
return false;
}
String name = operation.getSimpleName();
return (name != null && this.pattern.matcher(name).find()) || !this.expressionHelper.hasSideEffects(body);
}

}
Expand Up @@ -23,9 +23,6 @@

import java.util.regex.Pattern;

import org.eclipse.xtext.xbase.XExpression;

import org.eclipse.xtext.xbase.XBlockExpression;
import com.google.inject.Singleton;
import org.eclipse.xtend.core.typing.XtendExpressionHelper;
import org.eclipse.xtext.common.types.JvmIdentifiableElement;
Expand All @@ -35,21 +32,25 @@
/**
* Helper on expressions.
*
* <p>This implementation extends the Xtend expression helper by assuming that any function
* with a name starting with "get", "is", "has" is a pure function.
* It also assumes that "equals", "hashCode", "clone" and "toString" are also pure functions.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @see "http://www.eclipse.org/Xtext/documentation.html#validation"
*/
@Singleton
public class SARLExpressionHelper extends XtendExpressionHelper {
public class SARLXExpressionHelper extends XtendExpressionHelper {

private final Pattern pattern;

/** Construct the helper.
*/
public SARLExpressionHelper() {
this.pattern = Pattern.compile("^(((is)|(get)|(has))[A-Z].*)|(equals)|(hashCode)|(clone)|(toString)$"); //$NON-NLS-1$
public SARLXExpressionHelper() {
this.pattern = Pattern.compile(XExpressionConstants.SPECIAL_PURE_FUNCTION_NAME_PATTERN);
}

@Override
Expand All @@ -67,31 +68,4 @@ public boolean hasSideEffects(XAbstractFeatureCall featureCall, boolean inspectC
return false;
}

/** Replies if the given expression may the root expression for a pure function.
*
* <p>A pure function causes no externally visible side-effects and does not mutate non-local state.
* In other words: if the result of a pure function is not used, it is dead code and is supposed to
* be removeable without changing the behavior of the program.
*
* <p>This function extends the function {@link #hasSideEffects(org.eclipse.xtext.xbase.XExpression)}
* by assuming that {@link XBlockExpression} expressions do not cause side effects if its member
* expressions do not cause side effects.
*
* <p><strong>This function is a recursive version of {@link #hasSideEffects(org.eclipse.xtext.xbase.XExpression)}.
*
* @param expression - the expression to test.
* @return whether the expression itself (not its children) possibly causes a side-effect
*/
public boolean hasDeepSideEffects(XExpression expression) {
// if (expression instanceof XBlockExpression) {
// for (XExpression subexpression : ((XBlockExpression) expression).getExpressions()) {
// if (hasDeepSideEffects(subexpression)) {
// return true;
// }
// }
// return false;
// }
return hasSideEffects(expression);
}

}
@@ -0,0 +1,47 @@
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2015 the original authors or authors.
*
* 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 io.sarl.lang.typing;

import com.google.inject.Singleton;

/**
* Constants used by the XExpression helpers.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @see SARLXExpressionHelper
*/
@Singleton
public final class XExpressionConstants {

/** Regular expression pattern that matches the names of functions usually
* considered as pure.
*/
public static final String SPECIAL_PURE_FUNCTION_NAME_PATTERN = "^(((is)|(get)|(has))[A-Z].*)|(equals)|(hashCode)|(clone)|(toString)$"; //$NON-NLS-1$;

private XExpressionConstants() {
//
}

}

0 comments on commit 269d35a

Please sign in to comment.