use of nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostAssignmentParameter.
@Override
protected void walkPostAssignmentParameter(final AstNode node) {
final ExpressionResult result = ExpressionResult.UNDEFINED;
this.setNodeType(node, result);
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostAugmentedAssignmentExpression.
@Override
protected void walkPostAugmentedAssignmentExpression(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
final AbstractType falseType = this.typeKeeper.getType(SW_FALSE);
// Take result from right hand.
final AstNode rightNode = node.getLastChild();
final ExpressionResult rightResult = this.getNodeType(rightNode);
// Get left hand result.
final AstNode assignedNode = node.getFirstChild();
final ExpressionResult leftResult = this.getNodeType(assignedNode);
// Get operator.
final AstNode operatorNode = node.getChildren().get(1);
final String operatorStr = operatorNode.getTokenValue();
// Evaluate binary operator.
final AbstractType leftType = leftResult.get(0, unsetType);
final AbstractType rightType = rightResult.get(0, unsetType);
final ExpressionResult result;
switch(operatorStr.toLowerCase()) {
case "_is":
case "_isnt":
result = new ExpressionResult(falseType);
break;
// TODO: Not entirely true.
case "_andif":
case // TODO: Not entirely true.
"_orif":
result = new ExpressionResult(falseType);
break;
default:
final BinaryOperator.Operator operator = BinaryOperator.Operator.valueFor(operatorStr);
final BinaryOperator binaryOperator = this.typeKeeper.getBinaryOperator(operator, leftType, rightType);
final AbstractType resultingType = binaryOperator != null ? binaryOperator.getResultType() : UndefinedType.INSTANCE;
result = new ExpressionResult(resultingType);
break;
}
// Store result of expression.
this.setNodeType(node, result);
if (assignedNode.is(MagikGrammar.ATOM)) {
// Store 'active' type for future reference.
final Scope scope = this.globalScope.getScopeForNode(assignedNode);
Objects.requireNonNull(scope);
final String identifier = assignedNode.getTokenValue();
final ScopeEntry scopeEntry = scope.getScopeEntry(identifier);
this.currentScopeEntryNodes.put(scopeEntry, assignedNode);
this.setNodeType(assignedNode, result);
}
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostProcedureInvocation.
@Override
protected void walkPostProcedureInvocation(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
// Get called type for invocation.
final AstNode calledNode = node.getPreviousSibling();
final ExpressionResult calledResult = this.getNodeType(calledNode);
AbstractType calledType = calledResult.get(0, unsetType);
final AbstractType originalCalledType = calledType;
if (calledType == SelfType.INSTANCE) {
// Replace self type with concrete type, need to know the method we call.
calledType = this.typeKeeper.getType(SW_PROCEDURE);
}
// Clear iterator results.
this.setIteratorType(null);
// Perform procedure call.
ExpressionResult callResult = null;
if (calledType instanceof ProcedureInstance) {
final ProcedureInstance procedureType = (ProcedureInstance) calledType;
final Collection<Method> methods = procedureType.getMethods("invoke()");
final Method method = methods.stream().findAny().orElse(null);
Objects.requireNonNull(method);
callResult = method.getCallResult();
final ExpressionResult loopbodyResult = method.getLoopbodyResult();
this.setIteratorType(loopbodyResult);
if (originalCalledType == SelfType.INSTANCE) {
callResult = callResult.substituteType(SelfType.INSTANCE, calledType);
final ExpressionResult subbedResult = this.getIteratorType().substituteType(SelfType.INSTANCE, calledType);
this.setIteratorType(subbedResult);
}
}
if (callResult == null) {
callResult = ExpressionResult.UNDEFINED;
this.setIteratorType(ExpressionResult.UNDEFINED);
}
// Store it!
this.setNodeType(node, callResult);
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult in project magik-tools by StevenLooman.
the class LocalTypeReasonerTest method testReasonMethodReturnProc.
@Test
void testReasonMethodReturnProc() {
final String code = "" + "_method object.test\n" + " _return _proc@test()\n" + " >> 10\n" + " _endproc\n" + "_endmethod\n";
// Set up TypeKeeper/TypeReasoner.
final TypeKeeper typeKeeper = new TypeKeeper();
// Do analysis.
final MagikTypedFile magikFile = this.createMagikFile(code, typeKeeper);
final LocalTypeReasoner reasoner = magikFile.getTypeReasoner();
// Assert user:object.test type determined.
final AstNode topNode = magikFile.getTopNode();
final AstNode methodNode = topNode.getFirstChild(MagikGrammar.METHOD_DEFINITION);
final ExpressionResult result = reasoner.getNodeType(methodNode);
assertThat(result.size()).isEqualTo(1);
final ProcedureInstance resultType = (ProcedureInstance) result.get(0, null);
assertThat(resultType).isNotNull();
assertThat(resultType.getProcedureName()).isEqualTo("test");
final Collection<Method> procMethods = resultType.getMethods("invoke()");
assertThat(procMethods).isNotEmpty();
for (final Method procMethod : procMethods) {
final ExpressionResult procResult = procMethod.getCallResult();
assertThat(procResult.size()).isEqualTo(1);
final MagikType procResultType = (MagikType) procResult.get(0, null);
assertThat(procResultType).isNotNull();
assertThat(procResultType.getFullName()).isEqualTo("sw:integer");
}
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult in project magik-tools by StevenLooman.
the class LocalTypeReasonerTest method testEmptyLocalDefinition.
@Test
void testEmptyLocalDefinition() {
final String code = "" + "_method object.test\n" + " _local a\n" + " _return a\n" + "_endmethod\n";
// Set up TypeKeeper/TypeReasoner.
final TypeKeeper typeKeeper = new TypeKeeper();
// Do analysis.
final MagikTypedFile magikFile = this.createMagikFile(code, typeKeeper);
final LocalTypeReasoner reasoner = magikFile.getTypeReasoner();
// Assert user:object.test type determined.
final AstNode topNode = magikFile.getTopNode();
final AstNode methodNode = topNode.getFirstChild(MagikGrammar.METHOD_DEFINITION);
final ExpressionResult result = reasoner.getNodeType(methodNode);
assertThat(result.size()).isEqualTo(1);
final MagikType resultType = (MagikType) result.get(0, null);
assertThat(resultType).isNotNull();
assertThat(resultType.getFullName()).isEqualTo("sw:unset");
}
Aggregations