blob: 7ed5aba153dd71fc5093cc91311c8c7da6b0fe82 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.ruby.typeinference.evaluators;
import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ruby.ast.RubyIfStatement;
import org.eclipse.dltk.ruby.typeinference.RubyTypeInferencingUtils;
import org.eclipse.dltk.ti.GoalState;
import org.eclipse.dltk.ti.goals.ExpressionTypeGoal;
import org.eclipse.dltk.ti.goals.GoalEvaluator;
import org.eclipse.dltk.ti.goals.IGoal;
import org.eclipse.dltk.ti.types.IEvaluatedType;
public class IfStatementTypeEvaluator extends GoalEvaluator {
private final static int STATE_TRY_THEN = 0;
private final static int STATE_WAITING_THEN = 1;
private final static int STATE_TRY_ELSE = 2;
private final static int STATE_WAITING_ELSE = 3;
private final static int STATE_DONE = -2;
private int state = STATE_TRY_THEN;
private IEvaluatedType[] evaluatedTypes = new IEvaluatedType[2];
private int index = STATE_TRY_THEN;
public IfStatementTypeEvaluator(ExpressionTypeGoal goal) {
super(goal);
}
private IGoal produceNextSubgoal(IGoal previousGoal, Object previousResult) {
if (state == STATE_TRY_THEN) {
ExpressionTypeGoal typedGoal = (ExpressionTypeGoal) goal;
RubyIfStatement expression = (RubyIfStatement) typedGoal
.getExpression();
ASTNode clause = expression.getThen();
if (clause == null)
state = STATE_TRY_ELSE;
else {
state = STATE_WAITING_THEN;
return new ExpressionTypeGoal(goal.getContext(), clause);
}
}
if (state == STATE_WAITING_THEN || state == STATE_WAITING_ELSE) {
if (previousResult != null)
evaluatedTypes[index++] = (IEvaluatedType) previousResult;
state = (state == STATE_WAITING_THEN ? STATE_TRY_ELSE : STATE_DONE);
} else {
Assert.isTrue(previousGoal == null);
}
if (state == STATE_TRY_ELSE) {
ExpressionTypeGoal typedGoal = (ExpressionTypeGoal) goal;
RubyIfStatement expression = (RubyIfStatement) typedGoal
.getExpression();
ASTNode clause = expression.getElse();
if (clause == null)
state = STATE_DONE;
else {
state = STATE_WAITING_ELSE;
return new ExpressionTypeGoal(goal.getContext(), clause);
}
}
return null;
}
@Override
public Object produceResult() {
return RubyTypeInferencingUtils.combineTypes(evaluatedTypes);
}
@Override
public IGoal[] init() {
IGoal goal = produceNextSubgoal(null, null);
if (goal != null)
return new IGoal[] { goal };
return IGoal.NO_GOALS;
}
@Override
public IGoal[] subGoalDone(IGoal subgoal, Object result, GoalState state) {
IGoal goal = produceNextSubgoal(subgoal, result);
if (goal != null)
return new IGoal[] { goal };
return IGoal.NO_GOALS;
}
}