simple_ir_transformer 0.0.1

SITER - SImple Ir TransformER
Documentation
mod backends;

use std::collections::HashMap;
use tinyjson::JsonValue;

pub static VERSION: &str = "1.0.0";

#[derive(Debug, Clone)]
pub enum Value {
    Str(String),
    Int(i64),
    Bool(bool),
    List(Vec<Value>),
    Map(HashMap<String, Value>),
    Null,
}

#[derive(Debug)]
pub enum IRError {
    ParseError(String),
    InvalidRoot,
    UnknownLanguage(String),
}

impl std::fmt::Display for IRError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            IRError::ParseError(e)      => write!(f, "Ошибка парсинга JSON: {}", e),
            IRError::InvalidRoot        => write!(f, "IR должен быть JSON объектом"),
            IRError::UnknownLanguage(l) => write!(f, "Неизвестный язык: {}", l),
        }
    }
}

pub struct IR {
    pub ir: String,
}

impl IR {
    pub fn new(ir: String) -> Self {
        Self { ir }
    }

    fn convert(v: JsonValue) -> Value {
        match v {
            JsonValue::String(s)  => Value::Str(s),
            JsonValue::Number(n)  => Value::Int(n as i64),
            JsonValue::Boolean(b) => Value::Bool(b),
            JsonValue::Array(arr) => {
                Value::List(arr.into_iter().map(Self::convert).collect())
            }
            JsonValue::Object(map) => {
                Value::Map(
                    map.into_iter()
                        .map(|(k, v)| (k, Self::convert(v)))
                        .collect()
                )
            }
            JsonValue::Null => Value::Null,
        }
    }

    pub fn transpile(&self, lang: &str) -> Result<String, IRError> {
        let jj: JsonValue = self.ir
            .parse()
            .map_err(|e: tinyjson::JsonParseError| IRError::ParseError(e.to_string()))?;

        let obj_map = match jj {
            JsonValue::Object(map) => map,
            _ => return Err(IRError::InvalidRoot),
        };

        let converted: HashMap<String, Value> = obj_map
            .into_iter()
            .map(|(k, v)| (k, Self::convert(v)))
            .collect();

        match lang {
            "Python" => {
                Ok(backends::python_backend::Python::new(&converted).transpile())
            }
            "JavaScript" => {
                Ok(backends::js_backend::JS::new(&converted).transpile())
            }
            "Lua" => {
                Ok(backends::lua_backend::Lua::new(&converted).transpile())
            }
            _ => Err(IRError::UnknownLanguage(lang.to_string())),
        }
    }
}