|
65 | 65 | import org.eclipse.epsilon.eol.dom.NotOperatorExpression;
|
66 | 66 | import org.eclipse.epsilon.eol.dom.Operation;
|
67 | 67 | import org.eclipse.epsilon.eol.dom.OperationCallExpression;
|
68 |
| -import org.eclipse.epsilon.eol.dom.OperationList; |
69 | 68 | import org.eclipse.epsilon.eol.dom.OperatorExpression;
|
70 | 69 | import org.eclipse.epsilon.eol.dom.OrOperatorExpression;
|
71 | 70 | import org.eclipse.epsilon.eol.dom.Parameter;
|
|
88 | 87 | import org.eclipse.epsilon.eol.dom.XorOperatorExpression;
|
89 | 88 | import org.eclipse.epsilon.eol.staticanalyser.execute.context.FrameStack;
|
90 | 89 | import org.eclipse.epsilon.eol.execute.context.FrameType;
|
| 90 | +import org.eclipse.epsilon.eol.execute.operations.AbstractOperation; |
| 91 | +import org.eclipse.epsilon.eol.execute.operations.TypeCalculator; |
91 | 92 | import org.eclipse.epsilon.eol.execute.operations.contributors.OperationContributor;
|
92 | 93 | import org.eclipse.epsilon.eol.staticanalyser.execute.context.Variable;
|
93 | 94 | import org.eclipse.epsilon.eol.m3.MetaClass;
|
@@ -259,124 +260,50 @@ public void visit(ExpressionStatement expressionStatement) {
|
259 | 260 | expressionStatement.getExpression().accept(this);
|
260 | 261 |
|
261 | 262 | }
|
262 |
| - |
| 263 | + |
263 | 264 | @Override
|
264 | 265 | public void visit(FirstOrderOperationCallExpression firstOrderOperationCallExpression) {
|
265 |
| - OperationList builtinOperations = new OperationList(); |
266 |
| - Expression targetExpression = firstOrderOperationCallExpression.getTargetExpression(); |
267 |
| - EolType contextType = null; |
268 |
| - String name = firstOrderOperationCallExpression.getNameExpression().getName(); |
269 |
| - |
270 |
| - for (Operation op : ((EolModule) module).getOperations()) |
271 |
| - if (op.getAnnotation("firstorder") != null) |
272 |
| - builtinOperations.add(op); |
| 266 | + String name = firstOrderOperationCallExpression.getName(); |
| 267 | + AbstractOperation operation = context.operationFactory.getOperationFor(name); |
| 268 | + if (operation == null) { |
| 269 | + errors.add(new ModuleMarker(firstOrderOperationCallExpression.getNameExpression(), |
| 270 | + "Undefined first order operation " + name, Severity.Error)); |
| 271 | + return; |
| 272 | + }; |
| 273 | + TypeCalculator tc = operation.getClass().getAnnotation(TypeCalculator.class); |
| 274 | + if (tc == null) { |
| 275 | + setResolvedType(firstOrderOperationCallExpression, EolAnyType.Instance); |
| 276 | + return; |
| 277 | + } |
| 278 | + |
273 | 279 |
|
| 280 | + Expression targetExpression = firstOrderOperationCallExpression.getTargetExpression(); |
274 | 281 | targetExpression.accept(this);
|
275 |
| - |
276 |
| - if (getResolvedType(targetExpression) instanceof EolCollectionType) { |
277 |
| - contextType = ((EolCollectionType) getResolvedType(targetExpression)).getContentType(); |
278 |
| - } else if (getResolvedType(targetExpression) == EolAnyType.Instance) { |
279 |
| - contextType = getResolvedType(targetExpression); |
| 282 | + EolType contextType = getResolvedType(targetExpression); |
| 283 | + if (!(contextType instanceof EolCollectionType)) { |
| 284 | + contextType = new EolCollectionType("Sequence", contextType); |
280 | 285 | }
|
281 | 286 |
|
282 |
| - if (name.startsWith("sequential")) |
283 |
| - name = name.substring(10); |
284 |
| - else if (name.startsWith("parallel")) |
285 |
| - name = name.substring(8); |
286 |
| - |
287 |
| - if (contextType != null) { |
288 |
| - context.getFrameStack().enterLocal(FrameType.UNPROTECTED, firstOrderOperationCallExpression); |
289 |
| - Parameter parameter = firstOrderOperationCallExpression.getParameters().get(0); |
290 |
| - |
291 |
| - visit(parameter, false); |
292 |
| - |
293 |
| - if (parameter.isExplicitlyTyped()) { |
294 |
| - // TODO: Check that the type of the parameter is a subtype of the type of the |
295 |
| - // collection |
296 |
| - contextType = getType(parameter); |
297 |
| - EolType target = ((EolCollectionType) getResolvedType(targetExpression)).getContentType(); |
298 |
| - EolType param = contextType; |
299 |
| - while (!(param.equals(target))) { |
300 |
| - param = getParentType(param); |
301 |
| - if (param instanceof EolAnyType) { |
302 |
| - // context.addErrorMarker(parameter, ); |
303 |
| - errors.add(new ModuleMarker(parameter, "The parameter must be instance of " + target.getName(), |
304 |
| - Severity.Error)); |
305 |
| - |
306 |
| - break; |
307 |
| - } |
308 |
| - } |
309 |
| - } else { |
310 |
| - // context.getFrameStack().put(parameter.getName(), contextType); |
311 |
| - if (getResolvedType(targetExpression) instanceof EolCollectionType) { |
312 |
| - |
313 |
| - parameter.setTypeExpression(new TypeExpression( |
314 |
| - ((EolCollectionType) getResolvedType(targetExpression)).getContentType().getName())); |
315 |
| - |
316 |
| - setResolvedType(parameter.getTypeExpression(), |
317 |
| - ((EolCollectionType) getResolvedType(targetExpression)).getContentType()); |
318 |
| - } else { |
319 |
| - parameter.setTypeExpression(new TypeExpression("Any")); |
320 |
| - setResolvedType(parameter.getTypeExpression(), EolAnyType.Instance); |
321 |
| - } |
322 |
| - setType(parameter, getResolvedType(parameter.getTypeExpression())); |
323 |
| - parameter.getTypeExpression().setName(getResolvedType(parameter.getTypeExpression()).toString()); |
324 |
| - contextType = getType(parameter); |
325 |
| - } |
326 |
| - |
327 |
| - context.getFrameStack().put(new Variable(parameter.getName(), getType(parameter))); |
328 |
| - |
329 |
| - Expression expression = firstOrderOperationCallExpression.getExpressions().get(0); |
330 |
| - expression.accept(this); |
331 |
| - |
332 |
| - context.getFrameStack().leaveLocal(firstOrderOperationCallExpression); |
333 |
| - |
334 |
| - if (StringUtil.isOneOf(name, "select", "reject", "rejectOne", "closure", "sortBy")) { |
335 |
| - setResolvedType(firstOrderOperationCallExpression, new EolCollectionType("Collection", contextType)); |
336 |
| - } else if (name.equals("selectOne")) { |
337 |
| - setResolvedType(firstOrderOperationCallExpression, contextType); |
338 |
| - } else if (name.equals("collect")) { |
339 |
| - Operation firstOrder = builtinOperations.getOperation(name); |
340 |
| - firstOrder.getReturnTypeExpression().accept(this); |
341 |
| - setResolvedType(firstOrder.getReturnTypeExpression(), getResolvedType(targetExpression)); |
342 |
| - |
343 |
| - if (!(getResolvedType(firstOrder.getReturnTypeExpression()) instanceof EolAnyType)) |
344 |
| - ((EolCollectionType) getResolvedType(firstOrder.getReturnTypeExpression())) |
345 |
| - .setContentType(getResolvedType(firstOrderOperationCallExpression.getExpressions().get(0))); |
346 |
| - |
347 |
| - setResolvedType(firstOrderOperationCallExpression, |
348 |
| - new EolCollectionType(getResolvedType(targetExpression).getName(), |
349 |
| - getResolvedType(firstOrderOperationCallExpression.getExpressions().get(0)))); |
350 |
| - |
351 |
| - } else if (StringUtil.isOneOf(name, "exists", "forAll", "one", "none", "nMatch")) { |
352 |
| - setResolvedType(firstOrderOperationCallExpression, EolPrimitiveType.Boolean); |
353 |
| - } else if (name.equals("aggregate")) { |
354 |
| - if (firstOrderOperationCallExpression.getExpressions().size() == 2) { |
355 |
| - Expression valueExpression = firstOrderOperationCallExpression.getExpressions().get(1); |
356 |
| - valueExpression.accept(this); |
357 |
| - |
358 |
| - setResolvedType(firstOrderOperationCallExpression, |
359 |
| - new EolMapType(getResolvedType(expression), getResolvedType(valueExpression))); |
360 |
| - } else { |
361 |
| - errors.add(new ModuleMarker(firstOrderOperationCallExpression.getNameExpression(), |
362 |
| - "Aggregate requires a key and a value expression", Severity.Error)); |
363 |
| - |
364 |
| - } |
365 |
| - } else if (name.equals("mapBy")) { |
366 |
| - setResolvedType(firstOrderOperationCallExpression, |
367 |
| - new EolMapType(getResolvedType(expression), new EolCollectionType("Sequence", contextType))); |
368 |
| - } else if (name.equals("sortBy")) { |
369 |
| - setResolvedType(firstOrderOperationCallExpression, new EolCollectionType("Sequence", contextType)); |
370 |
| - } |
371 |
| - if (StringUtil.isOneOf(name, "select", "selectOne", "reject", "rejectOne", "exists", "one", "none", |
372 |
| - "forAll", "closure") && getResolvedType(expression).isNot(EolPrimitiveType.Boolean)) { |
| 287 | + Parameter parameter = firstOrderOperationCallExpression.getParameters().get(0); |
| 288 | + parameter.accept(this); |
| 289 | + EolType parameterType = (EolType) parameter.getData().get("type"); |
| 290 | + if (parameterType.equals(EolAnyType.Instance)) { |
| 291 | + parameterType = ((EolCollectionType) contextType).getContentType(); |
| 292 | + } |
373 | 293 |
|
374 |
| - errors.add(new ModuleMarker(expression, "Expression should return a Boolean but returns a " |
375 |
| - + getResolvedType(expression).getName() + " instead", Severity.Error)); |
376 |
| - } |
377 |
| - } else { |
378 |
| - errors.add(new ModuleMarker(firstOrderOperationCallExpression.getNameExpression(), |
379 |
| - "Operation " + name + " only applies to collections", Severity.Error)); |
| 294 | + context.getFrameStack().enterLocal(FrameType.UNPROTECTED, firstOrderOperationCallExpression, |
| 295 | + new Variable(parameter.getName(), parameterType)); |
| 296 | + Expression expression = firstOrderOperationCallExpression.getExpressions().get(0); |
| 297 | + expression.accept(this); |
| 298 | + EolType expressionType = getResolvedType(expression); |
| 299 | + context.getFrameStack().leaveLocal(firstOrderOperationCallExpression); |
| 300 | + |
| 301 | + try { |
| 302 | + EolType returnType = tc.klass().newInstance().calculateType(contextType, expressionType); |
| 303 | + setResolvedType(firstOrderOperationCallExpression, returnType); |
| 304 | + } catch (Exception e) { |
| 305 | + setResolvedType(firstOrderOperationCallExpression, EolAnyType.Instance); |
| 306 | + e.printStackTrace(); |
380 | 307 | }
|
381 | 308 | }
|
382 | 309 |
|
|
0 commit comments