// use std::collections::*;

use super::ast;
use super::ast_analysis::*;
use super::common;
use super::error::*;
use super::visitor::*;

pub struct ConstIntegerToConstSymbol<'a> {
  analysis: &'a AnalysisResult,
}

impl<'a> ConstIntegerToConstSymbol<'a> {
  fn new(analysis: &'a AnalysisResult) -> Self {
    Self { analysis }
  }
}

impl<'a> NodeVisitorMut for ConstIntegerToConstSymbol<'a> {
  fn visit_constant(&mut self, c: &mut ast::Constant) -> Result<(), CompileError> {
    match (&c.node, &self.analysis.node_types[&c.location.id]) {
      (ast::ConstantNode::Integer(i), common::Type::Symbol) => {
        *c = ast::Constant {
          location: c.location.clone(),
          node: ast::ConstantNode::SymbolId((*i) as usize),
        };
        Ok(())
      }
      _ => Ok(()),
    }
  }
}

pub fn transform(prog: &mut ast::Program, anal: &AnalysisResult) -> Result<(), CompileError> {
  let mut transfs = (ConstIntegerToConstSymbol::new(anal),);
  visit_program_mut(&mut transfs, prog)
}
