Skip to content

Commit 30a35e0

Browse files
authored
Merge pull request #101 from stefanschoon/datatypes
Introduction of ExpInstanceOp and better error handling for constructors
2 parents 20f1ab4 + 4c69d4f commit 30a35e0

17 files changed

+122
-154
lines changed

.idea/misc.xml

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

use-core/src/main/java/org/tzi/use/analysis/coverage/AbstractCoverageVisitor.java

+1-18
Original file line numberDiff line numberDiff line change
@@ -191,24 +191,7 @@ public void visitObjAsSet(ExpObjAsSet exp) {
191191
private Stack<MOperation> operationStack = new Stack<MOperation>();
192192

193193
@Override
194-
public void visitObjOp(ExpObjOp exp) {
195-
for (Expression ex : exp.getArguments()) {
196-
ex.processWithVisitor(this);
197-
}
198-
199-
addOperationCoverage((MClassifier) exp.getArguments()[0].type(),
200-
exp.getOperation());
201-
202-
if (expandOperations && exp.getOperation().hasExpression()
203-
&& !operationStack.contains(exp.getOperation())) {
204-
operationStack.push(exp.getOperation());
205-
exp.getOperation().expression().processWithVisitor(this);
206-
operationStack.pop();
207-
}
208-
}
209-
210-
@Override
211-
public void visitInstanceConstructor(ExpInstanceConstructor exp) {
194+
public void visitInstanceOp(ExpInstanceOp exp) {
212195
for (Expression ex : exp.getArguments()) {
213196
ex.processWithVisitor(this);
214197
}

use-core/src/main/java/org/tzi/use/parser/ocl/ASTOperationExpression.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -629,10 +629,10 @@ private Expression genObjOperation(Context ctx, MClassifier srcClassifier, Expre
629629
}
630630

631631
try {
632+
// constructor performs additional checks
632633
if (op.isConstructor()) {
633-
res = new ExpInstanceConstructor(srcClassifier, fArgExprs);
634+
res = new ExpInstanceConstructor(op, fArgExprs);
634635
} else {
635-
// constructor performs additional checks
636636
res = new ExpObjOp(op, fArgExprs);
637637
}
638638
res.setSourcePosition(new SrcPos(fOp));

use-core/src/main/java/org/tzi/use/parser/use/ASTOperation.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,6 @@ public MOperation genSignature(Context ctx)
109109
}
110110
} else {
111111
resultType = fType.gen(ctx);
112-
if (fIsConstructor && resultType != null) {
113-
throw new SemanticException(fName, "Constructor " + StringUtil.inQuotes(fName.getText()) +
114-
" must not have result type.");
115-
}
116112
}
117113

118114
fOperation = ctx.modelFactory().createOperation(fName.getText(), varDeclList, resultType, fIsConstructor);
@@ -141,6 +137,11 @@ public void genFinal(Context ctx) throws SemanticException
141137
if (fOperation == null)
142138
return;
143139

140+
if (fIsConstructor && fOperation.resultType() != fOperation.cls()) {
141+
throw new SemanticException(fName, "Instance constructor " + StringUtil.inQuotes(fName.getText()) +
142+
" must not have result type.");
143+
}
144+
144145
// enter parameters into scope of expression
145146
Symtable vars = ctx.varTable();
146147
vars.enterScope();
@@ -161,7 +162,7 @@ public void genFinal(Context ctx) throws SemanticException
161162
try {
162163
if (fExpr != null ) {
163164
if (fIsConstructor) {
164-
throw new MInvalidModelException("Constructor " + StringUtil.inQuotes(fName.getText())
165+
throw new MInvalidModelException("Instance constructor " + StringUtil.inQuotes(fName.getText())
165166
+ " must not have body.");
166167
}
167168
Expression expr = fExpr.gen(ctx);
@@ -195,7 +196,7 @@ private MStatement genStatement(Context context) throws SemanticException {
195196
/**
196197
* During compilation, this operation marks this AST-node
197198
* as invalid, because the signature had errors.
198-
* Any call to {@link #genFinal(Context)} afterwards
199+
* Any call to {@link #genFinal(Context)} afterward
199200
* is ignored.
200201
*/
201202
public void setSignatureGenFailed() {

use-core/src/main/java/org/tzi/use/uml/mm/MDataTypeImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public void addOperation(MOperation op) throws MInvalidModelException {
179179
.map(MModelElementImpl::name).collect(Collectors.toList());
180180
List<String> paramNames = op.paramNames();
181181
if (!CollectionUtil.equalLists(allAttributes, paramNames, Comparator.comparing(String::toString))) {
182-
throw new MInvalidModelException("Constructor `" + opname + "' is missing parent attribute(s).");
182+
throw new MInvalidModelException("Instance constructor `" + opname + "' is missing parent attribute(s).");
183183
}
184184
}
185185

use-core/src/main/java/org/tzi/use/uml/mm/MOperation.java

-2
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,6 @@ public void setExpression(Expression expr) throws MInvalidModelException {
202202
// If no result type is set, use type of the expression
203203
if (fResultType == null) {
204204
fResultType = expr.type();
205-
//} else if (expr.isConstructorCall() == null) {
206-
// TODO
207205
} else if (expr.type() == null) {
208206
throw new MInvalidModelException("The operation " + StringUtil.inQuotes(this.cls().name() + "." + this.name()) +
209207
" does not have a declared result type and the result type of the defined expression could not be calculated. This" +

use-core/src/main/java/org/tzi/use/uml/ocl/expr/EvalNode.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class EvalNode {
4848

4949
/**
5050
* If <code>true</code>, the occurrence
51-
* of variables in the text is replaces by the current value
51+
* of variables in the text is replaced by the current value
5252
* of the variable.
5353
*/
5454
private boolean fSubstituteVariables = false;
@@ -525,9 +525,9 @@ public void visitObjAsSet(ExpObjAsSet exp) {
525525
}
526526

527527
@Override
528-
public void visitObjOp(ExpObjOp exp) {
528+
public void visitInstanceOp(ExpInstanceOp exp) {
529529
if (replace(exp)) return;
530-
super.visitObjOp(exp);
530+
super.visitInstanceOp(exp);
531531
}
532532

533533
@Override

use-core/src/main/java/org/tzi/use/uml/ocl/expr/ExpInstanceConstructor.java

+29-53
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.tzi.use.uml.ocl.expr;
2121

22-
import org.tzi.use.uml.mm.MClassifier;
2322
import org.tzi.use.uml.mm.MOperation;
2423
import org.tzi.use.uml.ocl.value.DataTypeValueValue;
2524
import org.tzi.use.uml.ocl.value.VarBindings;
@@ -38,22 +37,30 @@
3837
*
3938
* @author Stefan Schoon
4039
*/
41-
public final class ExpInstanceConstructor extends Expression {
42-
43-
private final MClassifier classifier;
44-
45-
private final MOperation constructor;
46-
47-
/**
48-
* The arguments.
49-
*/
50-
private final Expression[] fArgs;
51-
52-
public ExpInstanceConstructor(MClassifier classifier, Expression[] args) throws ExpInvalidException {
53-
super(classifier);
54-
this.classifier = classifier;
55-
this.constructor = classifier.operation(classifier.name(), false);
56-
fArgs = args;
40+
public final class ExpInstanceConstructor extends ExpInstanceOp {
41+
42+
public ExpInstanceConstructor(MOperation constructor, Expression[] args) throws ExpInvalidException {
43+
super(constructor, args);
44+
45+
if (!(args[0].type().isTypeOfClass() || args[0].type().isTypeOfDataType()))
46+
throw new ExpInvalidException(
47+
"Target expression of instance constructor must have " +
48+
"object type, found `" + args[0].type() + "'.");
49+
50+
// check for matching arguments
51+
VarDeclList params = fOp.paramList();
52+
if (params.size() != (args.length - 1) )
53+
throw new ExpInvalidException(
54+
"Number of arguments does not match declaration of instance constructor `" +
55+
fOp.name() + "'. Expected " + params.size() + " argument(s), found " +
56+
(args.length - 1) + ".");
57+
58+
for (int i = 1; i < args.length; i++)
59+
if (! args[i].type().conformsTo(params.varDecl(i - 1).type()) )
60+
throw new ExpInvalidException(
61+
"Type mismatch in argument `" + params.varDecl(i - 1).name() +
62+
"'. Expected type `" + params.varDecl(i - 1).type() +
63+
"', found `" + args[i].type() + "'.");
5764
}
5865

5966
@Override
@@ -64,7 +71,7 @@ public Value eval(EvalContext ctx) {
6471

6572
ctx.enter(this);
6673

67-
List<String> parameterNames = constructor.paramNames();
74+
List<String> parameterNames = fOp.paramNames();
6875
int argsSize = parameterNames.size();
6976
Value[] arguments = new Value[argsSize];
7077
Map<String, Value> argValues = new TreeMap<>();
@@ -78,10 +85,10 @@ public Value eval(EvalContext ctx) {
7885
for (VarBindings.Entry e : ctx.varBindings()) {
7986
varBindings.put(e.getVarName(), e.getValue());
8087
}
81-
MInstance self = new MDataTypeValue(classifier, classifier.name(), varBindings);
82-
Value result = new DataTypeValueValue(classifier, self, argValues);
88+
MInstance self = new MDataTypeValue(fClassifier, fClassifier.name(), varBindings);
89+
Value result = new DataTypeValueValue(fClassifier, self, argValues);
8390

84-
MOperationCall operationCall = new MOperationCall(this, self, constructor, arguments);
91+
MOperationCall operationCall = new MOperationCall(this, self, fOp, arguments);
8592
operationCall.setPreferredPPCHandler(ExpressionPPCHandler.getDefaultOutputHandler());
8693
operationCall.setResultValue(result);
8794

@@ -105,41 +112,10 @@ public Value eval(EvalContext ctx) {
105112
return result;
106113
}
107114

108-
@Override
109-
protected boolean childExpressionRequiresPreState() {
110-
for (Expression e : fArgs) {
111-
if (e.requiresPreState()) {
112-
return true;
113-
}
114-
}
115-
return false;
116-
}
117-
118115
@Override
119116
public StringBuilder toString(StringBuilder sb) {
120-
sb.append(classifier.name()).append("(");
117+
sb.append(fClassifier.name()).append("(");
121118
StringUtil.fmtSeqBuffered(sb, fArgs, 1, ", ");
122119
return sb.append(")");
123120
}
124-
125-
@Override
126-
public String name() {
127-
return constructor.name();
128-
}
129-
130-
/**
131-
* All arguments of the expression.
132-
*/
133-
public Expression[] getArguments() {
134-
return fArgs;
135-
}
136-
137-
public MOperation getOperation() {
138-
return constructor;
139-
}
140-
141-
@Override
142-
public void processWithVisitor(ExpressionVisitor visitor) {
143-
visitor.visitInstanceConstructor(this);
144-
}
145121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package org.tzi.use.uml.ocl.expr;
2+
3+
import org.tzi.use.uml.mm.MClassifier;
4+
import org.tzi.use.uml.mm.MOperation;
5+
import org.tzi.use.uml.ocl.value.Value;
6+
7+
/**
8+
* Abstract class for operations and constructors defined by a classifier.
9+
*
10+
* @author Stefan Schoon
11+
*/
12+
public abstract class ExpInstanceOp extends Expression {
13+
protected final MOperation fOp;
14+
15+
/**
16+
* The arguments, first one is "receiver" object
17+
*/
18+
protected final Expression[] fArgs;
19+
20+
protected final MClassifier fClassifier;
21+
22+
public ExpInstanceOp(MOperation op, Expression[] args) {
23+
super(op.resultType());
24+
fOp = op;
25+
fArgs = args;
26+
fClassifier = op.cls();
27+
}
28+
29+
public abstract Value eval(EvalContext ctx);
30+
31+
public MOperation getOperation() {
32+
return fOp;
33+
}
34+
35+
/**
36+
* All arguments of the expression.
37+
* Index 0 is the receiver object (self)
38+
*/
39+
public Expression[] getArguments() {
40+
return fArgs;
41+
}
42+
43+
@Override
44+
public void processWithVisitor(ExpressionVisitor visitor) {
45+
visitor.visitInstanceOp(this);
46+
}
47+
48+
@Override
49+
protected boolean childExpressionRequiresPreState() {
50+
for (Expression e : fArgs) {
51+
if (e.requiresPreState()) {
52+
return true;
53+
}
54+
}
55+
return false;
56+
}
57+
58+
@Override
59+
public String name() {
60+
return fOp.name();
61+
}
62+
}

use-core/src/main/java/org/tzi/use/uml/ocl/expr/ExpObjOp.java

+4-40
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,13 @@
3232
*
3333
* @author Mark Richters
3434
*/
35-
public final class ExpObjOp extends Expression {
36-
private MOperation fOp;
37-
38-
/**
39-
* The arguments, first one is "receiver" object
40-
*/
41-
private Expression[] fArgs;
42-
35+
public final class ExpObjOp extends ExpInstanceOp {
36+
4337
public ExpObjOp(MOperation op, Expression[] args)
4438
throws ExpInvalidException
4539
{
46-
super(op.resultType());
47-
fOp = op;
48-
fArgs = args;
40+
super(op, args);
41+
4942
if (!(args[0].type().isTypeOfClass() || args[0].type().isTypeOfDataType()))
5043
throw new ExpInvalidException(
5144
"Target expression of object operation must have " +
@@ -158,33 +151,4 @@ public StringBuilder toString(StringBuilder sb) {
158151

159152
return sb.append(")");
160153
}
161-
162-
public MOperation getOperation() {
163-
return fOp;
164-
}
165-
166-
/**
167-
* All arguments of the expression.
168-
* Index 0 is the receiver object (self)
169-
* @return
170-
*/
171-
public Expression[] getArguments() {
172-
return fArgs;
173-
}
174-
175-
@Override
176-
public void processWithVisitor(ExpressionVisitor visitor) {
177-
visitor.visitObjOp(this);
178-
}
179-
180-
@Override
181-
protected boolean childExpressionRequiresPreState() {
182-
for (Expression e : fArgs) {
183-
if (e.requiresPreState()) {
184-
return true;
185-
}
186-
}
187-
188-
return false;
189-
}
190154
}

0 commit comments

Comments
 (0)