simple_ir_transformer 0.0.3

SITER - SImple Ir TransformER
Documentation
mod transformers;

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 parsing error: {}", e),
            IRError::InvalidRoot        => write!(f, "IR must be a JSON object"),
            IRError::UnknownLanguage(l) => write!(f, "Unknown language: {}, available: Python, JavaScript, Lua", l),
        }
    }
}

pub struct IR {
    pub ir: String,
}

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

    fn json_to_value(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::json_to_value).collect())
            }
            JsonValue::Object(map) => {
                Value::Map(
                    map.into_iter()
                        .map(|(k, v)| (k, Self::json_to_value(v)))
                        .collect()
                )
            }
            JsonValue::Null => Value::Null,
        }
    }

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

        // Validate root is object
        let obj_map = match json {
            JsonValue::Object(map) => map,
            _ => return Err(IRError::InvalidRoot),
        };

        // Convert to our Value type
        let ir_data: HashMap<String, Value> = obj_map
            .into_iter()
            .map(|(k, v)| (k, Self::json_to_value(v)))
            .collect();

        // Transpile to target language
        match lang {
            "Python" => Ok(transformers::python_backend::Python::new(&ir_data).generate()),
            "JavaScript" => Ok(transformers::js_backend::JavaScript::new(&ir_data).generate()),
            "Lua" => Ok(transformers::lua_backend::Lua::new(&ir_data).generate()),
            _ => Err(IRError::UnknownLanguage(lang.to_string())),
        }
    }
}