Skip to content

Commit 75d8edc

Browse files
committed
Issue #5 - Implemented overloading resolution for operation calls.
(But not for super calls or instance creation yet.)
1 parent 098bc2b commit 75d8edc

File tree

15 files changed

+434
-201
lines changed

15 files changed

+434
-201
lines changed
1.36 KB
Binary file not shown.
1.36 KB
Binary file not shown.

org.modeldriven.alf/src/org/modeldriven/alf/execution/AlfBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
public abstract class AlfBase {
2626

27-
public static final String ALF_VERSION = "0.6.0b";
27+
public static final String ALF_VERSION = "0.6.0c";
2828

2929
protected boolean isVerbose = false;
3030

org.modeldriven.alf/src/org/modeldriven/alf/syntax/expressions/impl/BehaviorInvocationExpressionImpl.java

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/*******************************************************************************
3-
* Copyright 2011-2015 Data Access Technologies, Inc. (Model Driven Solutions)
3+
* Copyright 2011-2016 Data Access Technologies, Inc. (Model Driven Solutions)
44
* All rights reserved worldwide. This program and the accompanying materials
55
* are made available for use under the terms of the GNU General Public License
66
* (GPL) version 3 that accompanies this distribution and is available at
@@ -135,28 +135,7 @@ public boolean behaviorInvocationExpressionReferentConstraint() {
135135
**/
136136
public boolean behaviorInvocationExpressionArgumentCompatibility() {
137137
BehaviorInvocationExpression self = this.getSelf();
138-
// TODO: Once overloading resolution is implemented, change this to only
139-
// be for non-feature invocations.
140-
// if (self.getFeature() == null) {
141-
Tuple tuple = self.getTuple();
142-
if (tuple == null ||
143-
tuple.getImpl().size() > this.parameterCount()) {
144-
return false;
145-
} else {
146-
this.getAssignmentAfterMap(); // Force computation of assignments.
147-
for (NamedExpression input: tuple.getInput()) {
148-
if (!this.parameterIsAssignableFrom(input)) {
149-
return false;
150-
}
151-
}
152-
for (NamedExpression output: tuple.getOutput()) {
153-
if (!this.parameterIsAssignableTo(output)) {
154-
return false;
155-
}
156-
}
157-
}
158-
// }
159-
return true;
138+
return self.getFeature() != null || this.isCompatibleWith(null);
160139
}
161140

162141
/**

org.modeldriven.alf/src/org/modeldriven/alf/syntax/expressions/impl/FeatureInvocationExpressionImpl.java

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/*******************************************************************************
3-
* Copyright 2011, 2012 Data Access Technologies, Inc. (Model Driven Solutions)
3+
* Copyright 2011-2016 Data Access Technologies, Inc. (Model Driven Solutions)
44
* All rights reserved worldwide. This program and the accompanying materials
55
* are made available for use under the terms of the GNU General Public License
66
* (GPL) version 3 that accompanies this distribution and is available at
@@ -112,30 +112,7 @@ public boolean featureInvocationExpressionFeatureDerivation() {
112112
**/
113113
public boolean featureInvocationExpressionReferentExists() {
114114
FeatureInvocationExpression self = this.getSelf();
115-
// return self.getIsImplicit() || self.getReferent() != null;
116-
if (self.getReferent() == null) {
117-
return self.getIsImplicit();
118-
} else {
119-
// TODO: Remove this check once overloading resolution is implemented.
120-
Tuple tuple = self.getTuple();
121-
if (tuple == null ||
122-
tuple.getImpl().size() > this.parameterCount()) {
123-
return false;
124-
} else {
125-
this.getAssignmentAfterMap(); // Force computation of assignments.
126-
for (NamedExpression input: tuple.getInput()) {
127-
if (!this.parameterIsAssignableFrom(input)) {
128-
return false;
129-
}
130-
}
131-
for (NamedExpression output: tuple.getOutput()) {
132-
if (!this.parameterIsAssignableTo(output)) {
133-
return false;
134-
}
135-
}
136-
}
137-
return true;
138-
}
115+
return self.getIsImplicit() || self.getReferent() != null;
139116
}
140117

141118
/**

org.modeldriven.alf/src/org/modeldriven/alf/syntax/expressions/impl/FeatureReferenceImpl.java

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/*******************************************************************************
3-
* Copyright 2011-2015 Data Access Technologies, Inc. (Model Driven Solutions)
3+
* Copyright 2011-2016 Data Access Technologies, Inc. (Model Driven Solutions)
44
*
55
* All rights reserved worldwide. This program and the accompanying materials
66
* are made available for use under the terms of the GNU General Public License
@@ -15,6 +15,8 @@
1515
import org.modeldriven.alf.syntax.common.impl.SyntaxElementImpl;
1616
import org.modeldriven.alf.syntax.expressions.*;
1717
import org.modeldriven.alf.syntax.units.*;
18+
import org.modeldriven.alf.syntax.units.impl.AssignableTypedElementImpl;
19+
import org.modeldriven.alf.syntax.units.impl.OperationDefinitionImpl;
1820

1921
import java.util.ArrayList;
2022
import java.util.Collection;
@@ -166,23 +168,85 @@ public ElementReference getStructuralFeatureReferent() {
166168
}
167169

168170
public ElementReference getBehavioralFeatureReferent(InvocationExpression invocation) {
169-
// TODO Handle overloading resolution.
170171
FeatureReference self = this.getSelf();
171-
ElementReference feature = null;
172+
ElementReference signal = null;
173+
List<ElementReference> operations = new ArrayList<ElementReference>();
172174
for (ElementReference referent: self.getReferent()) {
173-
if (referent.getImpl().isOperation() ||
174-
referent.getImpl().isReception()) {
175-
if (feature != null) {
176-
return null;
177-
}
175+
if (referent.getImpl().isReception()) {
178176
// NOTE: If the feature is a reception, then the referent should be the
179177
// signal being received, not the reception itself.
180-
feature = referent.getImpl().isReception()?
181-
referent.getImpl().getSignal():
182-
referent;
178+
referent = referent.getImpl().getSignal();
179+
}
180+
if (invocation.getImpl().isCompatibleWith(referent)) {
181+
if (referent.getImpl().isOperation()) {
182+
if (signal != null) {
183+
return null;
184+
}
185+
operations.add(referent);
186+
} else if (referent.getImpl().isSignal()) {
187+
if (signal != null || operations.size() > 0) {
188+
return null;
189+
}
190+
signal = referent;
191+
}
192+
}
193+
}
194+
return signal != null? signal: selectMostSpecificOperation(operations);
195+
}
196+
197+
public static ElementReference selectMostSpecificOperation(List<ElementReference> operations) {
198+
ElementReference selectedOperation = null;
199+
if (operations.size() > 0) {
200+
for (ElementReference operation1: operations) {
201+
boolean isMostSpecific = true;
202+
for (ElementReference operation2: operations) {
203+
if (!operation1.equals(operation2) && !isMoreSpecificThan(operation1, operation2)) {
204+
isMostSpecific = false;
205+
break;
206+
}
207+
}
208+
if (isMostSpecific) {
209+
if (selectedOperation != null) {
210+
return null;
211+
}
212+
selectedOperation = operation1;
213+
}
214+
}
215+
}
216+
return selectedOperation;
217+
}
218+
219+
public static boolean isMoreSpecificThan(ElementReference operation1, ElementReference operation2) {
220+
List<FormalParameter> parameters1 =
221+
OperationDefinitionImpl.removeReturnParameter(operation1.getImpl().getParameters());
222+
List<FormalParameter> parameters2 =
223+
OperationDefinitionImpl.removeReturnParameter(operation2.getImpl().getParameters());
224+
if (parameters1.size() > parameters2.size()) {
225+
return false;
226+
} else {
227+
for (int i = 0; i < parameters1.size(); i++) {
228+
FormalParameter parameter1 = parameters1.get(i);
229+
String direction = parameter1.getDirection();
230+
FormalParameter parameter2 = parameters2.get(i);
231+
if ("in".equals(direction)) {
232+
if (!new AssignableTypedElementImpl(parameter2.getImpl()).isAssignableFrom(
233+
new AssignableTypedElementImpl(parameter1.getImpl()))) {
234+
return false;
235+
}
236+
} else if ("out".equals(direction)) {
237+
if (!new AssignableTypedElementImpl(parameter1.getImpl()).isAssignableFrom(
238+
new AssignableTypedElementImpl(parameter2.getImpl()))) {
239+
return false;
240+
}
241+
}
183242
}
243+
FormalParameter returnParameter1 = operation1.getImpl().getReturnParameter();
244+
FormalParameter returnParameter2 = operation2.getImpl().getReturnParameter();
245+
return returnParameter1 == null ||
246+
returnParameter2 != null &&
247+
new AssignableTypedElementImpl(returnParameter1.getImpl()).isAssignableFrom(
248+
new AssignableTypedElementImpl(returnParameter2.getImpl()));
184249
}
185-
return feature;
186250
}
187251

188252
public void setCurrentScope(NamespaceDefinition currentScope) {

org.modeldriven.alf/src/org/modeldriven/alf/syntax/expressions/impl/InvocationExpressionImpl.java

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/*******************************************************************************
3-
* Copyright 2011, 2016 Data Access Technologies, Inc. (Model Driven Solutions)
3+
* Copyright 2011-2016 Data Access Technologies, Inc. (Model Driven Solutions)
44
* All rights reserved worldwide. This program and the accompanying materials
55
* are made available for use under the terms of the GNU General Public License
66
* (GPL) version 3 that accompanies this distribution and is available at
@@ -371,36 +371,48 @@ public List<ElementReference> parameterElements() {
371371
}
372372
return parameters;
373373
}
374+
375+
public List<FormalParameter> parameters() {
376+
return this.parametersFor(null);
377+
}
374378

375-
public List<FormalParameter> parameters() {
376-
InvocationExpression self = this.getSelf();
377-
ElementReference referent = self.getReferent();
379+
public List<FormalParameter> parametersFor(ElementReference referent) {
380+
if (referent == null) {
381+
referent = this.getSelf().getReferent();
382+
}
378383
List<FormalParameter> parameters = new ArrayList<FormalParameter>();
379-
if (self.getIsBehavior() || self.getIsOperation()) {
380-
parameters = referent.getImpl().getParameters();
381-
} else if (self.getIsAssociationEnd()) {
382-
ElementReference association = referent.getImpl().getAssociation();
383-
String referentName = referent.getImpl().getName();
384-
for (ElementReference property: association.getImpl().getAssociationEnds()) {
385-
if (!property.getImpl().getName().equals(referentName)) {
386-
FormalParameter parameter = parameterFromProperty(property);
387-
parameter.setLower(1);
388-
parameter.setUpper(1);
389-
parameters.add(parameter);
384+
if (referent != null) {
385+
if (referent.getImpl().isBehavior() || referent.getImpl().isOperation()) {
386+
parameters = referent.getImpl().getParameters();
387+
} else if (referent.getImpl().isAssociationEnd()) {
388+
ElementReference association = referent.getImpl().getAssociation();
389+
String referentName = referent.getImpl().getName();
390+
for (ElementReference property: association.getImpl().getAssociationEnds()) {
391+
if (!property.getImpl().getName().equals(referentName)) {
392+
FormalParameter parameter = parameterFromProperty(property);
393+
parameter.setLower(1);
394+
parameter.setUpper(1);
395+
parameters.add(parameter);
396+
}
397+
}
398+
} else {
399+
for (ElementReference property: referent.getImpl().getAttributes()) {
400+
parameters.add(parameterFromProperty(property));
390401
}
391-
}
392-
} else if (referent != null) {
393-
for (ElementReference property: referent.getImpl().getAttributes()) {
394-
parameters.add(parameterFromProperty(property));
395402
}
396403
}
397404
return parameters;
398405
}
399-
406+
400407
// Returns the number of parameters, excluding return parameters.
401408
public int parameterCount() {
402-
int n = this.parameters().size();
403-
for (FormalParameter parameter: this.parameters()) {
409+
return this.countParametersOf(null);
410+
}
411+
412+
public int countParametersOf(ElementReference referent) {
413+
List<FormalParameter> parameters = parametersFor(referent);
414+
int n = parameters.size();
415+
for (FormalParameter parameter: parameters) {
404416
if ("return".equals(parameter.getDirection())) {
405417
n--;
406418
}
@@ -424,6 +436,12 @@ protected static FormalParameter parameterFromProperty(ElementReference property
424436
* after the tuple of the expression.
425437
**/
426438
public Map<String, AssignedSource> updateAssignmentMap() {
439+
// NOTE: Defer computation of referent until the assignments before
440+
// the feature and tuple are set.
441+
return this.updateAssignmentsFor(null);
442+
}
443+
444+
public Map<String, AssignedSource> updateAssignmentsFor(ElementReference referent) {
427445
InvocationExpression self = this.getSelf();
428446
FeatureReference feature = self.getFeature();
429447
Tuple tuple = self.getTuple();
@@ -434,13 +452,17 @@ public Map<String, AssignedSource> updateAssignmentMap() {
434452
}
435453
if (tuple != null) {
436454
tuple.getImpl().setAssignmentsBefore(assignments);
437-
assignments = tuple.getImpl().getAssignmentsAfterMap();
455+
assignments = tuple.getImpl().getAssignmentsAfterMap(referent);
438456
}
439457
return assignments;
440-
} // updateAssignments
458+
}
441459

442460
protected boolean parameterIsAssignableFrom(NamedExpression input) {
443-
FormalParameter namedParameter = this.parameterNamed(input.getName());
461+
return this.parameterIsAssignableFrom(input, null);
462+
}
463+
464+
protected boolean parameterIsAssignableFrom(NamedExpression input, ElementReference referent) {
465+
FormalParameter namedParameter = this.parameterNamed(input.getName(), referent);
444466
if (namedParameter == null) {
445467
return false;
446468
} else {
@@ -450,9 +472,13 @@ protected boolean parameterIsAssignableFrom(NamedExpression input) {
450472
namedParameter.getImpl().isAssignableFrom(input.getExpression());
451473
}
452474
}
453-
475+
454476
protected boolean parameterIsAssignableTo(NamedExpression output) {
455-
FormalParameter namedParameter = this.parameterNamed(output.getName());
477+
return parameterIsAssignableTo(output, null);
478+
}
479+
480+
protected boolean parameterIsAssignableTo(NamedExpression output, ElementReference referent) {
481+
FormalParameter namedParameter = this.parameterNamed(output.getName(), referent);
456482
if (namedParameter == null ||
457483
!(output instanceof OutputNamedExpression)) {
458484
return false;
@@ -467,14 +493,45 @@ protected boolean parameterIsAssignableTo(NamedExpression output) {
467493
}
468494

469495
public FormalParameter parameterNamed(String name) {
470-
for (FormalParameter parameter: this.parameters()) {
496+
return parameterNamed(name, null);
497+
}
498+
499+
public FormalParameter parameterNamed(String name, ElementReference referent) {
500+
if (referent == null) {
501+
referent = this.getSelf().getReferent();
502+
}
503+
for (FormalParameter parameter: this.parametersFor(referent)) {
471504
if (parameter.getName().equals(name)) {
472505
return parameter;
473506
}
474507
}
475508
return null;
476509
}
477510

511+
public boolean isCompatibleWith(ElementReference referent) {
512+
// NOTE: If referent is null, then the invocation referent is used,
513+
// which is cached, along with tuple inputs and outputs.
514+
InvocationExpression self = this.getSelf();
515+
Tuple tuple = self.getTuple();
516+
if (tuple == null ||
517+
tuple.getImpl().size() > countParametersOf(referent)) {
518+
return false;
519+
} else {
520+
this.updateAssignmentsFor(referent);
521+
for (NamedExpression input: tuple.getImpl().deriveInput(referent)) {
522+
if (!parameterIsAssignableFrom(input, referent)) {
523+
return false;
524+
}
525+
}
526+
for (NamedExpression output: tuple.getImpl().deriveOutput(referent)) {
527+
if (!parameterIsAssignableTo(output, referent)) {
528+
return false;
529+
}
530+
}
531+
}
532+
return true;
533+
}
534+
478535
@Override
479536
public void setCurrentScope(NamespaceDefinition currentScope) {
480537
Tuple tuple = this.getSelf().getTuple();

org.modeldriven.alf/src/org/modeldriven/alf/syntax/expressions/impl/LinkOperationExpressionImpl.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/*******************************************************************************
3-
* Copyright 2011, 2012 Data Access Technologies, Inc. (Model Driven Solutions)
3+
* Copyright 2011-2016 Data Access Technologies, Inc. (Model Driven Solutions)
44
* All rights reserved worldwide. This program and the accompanying materials
55
* are made available for use under the terms of the GNU General Public License
66
* (GPL) version 3 that accompanies this distribution and is available at
@@ -176,9 +176,11 @@ public boolean linkOperationExpressionArgumentCompatibility() {
176176
* Otherwise, returns the ends of the named association.
177177
**/
178178
@Override
179-
public List<FormalParameter> parameters() {
179+
public List<FormalParameter> parametersFor(ElementReference referent) {
180+
if (referent == null) {
181+
referent = this.getSelf().getReferent();
182+
}
180183
LinkOperationExpression self = this.getSelf();
181-
ElementReference referent = self.getReferent();
182184
List<FormalParameter> parameters = new ArrayList<FormalParameter>();
183185
if (self.getIsClear()) {
184186
FormalParameter parameter = new FormalParameter();

0 commit comments

Comments
 (0)