package cd.transform.analysis;

import cd.ir.Ast;
import cd.ir.Ast.Assign;
import cd.ir.Ast.Var;
import cd.ir.ControlFlowGraph;
import cd.ir.ExprVisitor;
import cd.ir.Symbol;
import cd.ir.Symbol.TypeSymbol;

import java.util.Map;

public class DynamicTypeAnalysis extends MaybeFlowAnalysis<TypeSymbol> {
	public DynamicTypeAnalysis(ControlFlowGraph cfg) {
		super(cfg, false, true);
	}

	@Override
	public void transferStmt(Ast.Stmt stmt, Map<Symbol.VariableSymbol, MaybeC<TypeSymbol>> state) {
		if (stmt instanceof Assign) {
			Assign assign = (Assign) stmt;
			if (!(assign.left() instanceof Var)) return;
			Symbol.VariableSymbol sym = ((Var) assign.left()).sym;
			if (!state.containsKey(sym)) return;
			TypeSymbol type = new TypeVisitor().visit(assign.right(), null);
			if (type != null) {
				state.put(sym, MaybeC.value(type));
			} else {
				state.get(sym).setNotConstant();
			}
		}
	}

	@Override
	protected MaybeC<TypeSymbol> defaultInit(Symbol.VariableSymbol varSym) {
		return MaybeC.notConstant();
	}

	static class TypeVisitor extends ExprVisitor<TypeSymbol, Void> {
		@Override
		public TypeSymbol newObject(Ast.NewObject ast, Void arg) {
			return ast.type;
		}

		@Override
		public TypeSymbol newArray(Ast.NewArray ast, Void arg) {
			return ast.type;
		}
	}
}
