| /******************************************************************************* |
| * 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; |
| } |
| |
| } |