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.Symbol.VariableSymbol;

import java.util.Map;
import java.util.Optional;

/**
 * This class implements constant propagation:
 * remember variables that have constant values
 * no need evaluate them at runtime, save movl instruction
 */
public class ConstantAnalysis extends MaybeFlowAnalysis<Integer> {
	public ConstantAnalysis(ControlFlowGraph cfg) {
		super(cfg, true, false);
	}

	@Override
	protected MaybeC<Integer> defaultInit(VariableSymbol varSym) {
		if (varSym.kind == VariableSymbol.Kind.LOCAL)
			return MaybeC.value(0);
		else
			return MaybeC.notConstant();
	}

	@Override
	public void transferStmt(Ast.Stmt stmt, Map<VariableSymbol, MaybeC<Integer>> state) {
		if (stmt instanceof Assign) {
			Assign ast = (Assign) stmt;
			if (ast.left() instanceof Var) {
				VariableSymbol symbol = ((Var) ast.left()).sym;
				if (!state.containsKey(symbol)) return;

				// Obtain value and previous MaybeConstant
				Optional<Integer> valueOpt = cte.calc(ast.right());
				MaybeC<Integer> mc = state.get(symbol);
				if (valueOpt.isPresent()) {
					state.put(symbol, MaybeC.value(valueOpt.get()));
				} else {
					mc.setNotConstant();
				}
			}
		}
	}
}
