langkit 1.0.0

A builder library for creating programming languages in Rust
Documentation
use std::collections::HashMap;

/// Typing mode for the language
#[derive(Debug, Clone, PartialEq)]
pub enum Typing {
    Static,
    Dynamic,
    Optional,
}

/// Config source for language settings.
#[derive(Debug, Clone, PartialEq)]
pub enum ConfigSource {
    None,
    Toml(String),
    Inline,
}

/// Default mutability for variables created without a keyword.
#[derive(Debug, Clone, PartialEq)]
pub enum ImplicitMutability {
    /// Implicit variables are mutable.
    Mutable,
    /// Implicit variables are immutable.
    Immutable,
    /// Implicit variables start immutable and become mutable on reassignment.
    Infer,
}

/// Block style
#[derive(Debug, Clone, PartialEq)]
pub enum Blocks {
    Braces,
    Indent,
    Both,
}

/// Semicolon rules
#[derive(Debug, Clone, PartialEq)]
pub enum Semicolon {
    Required,
    Optional,
    None,
}

/// String quote style
#[derive(Debug, Clone, PartialEq)]
pub enum Strings {
    Double,
    Single,
    Both,
}

/// Execution mode
#[derive(Debug, Clone, PartialEq)]
pub enum Mode {
    Interpreter,
    Compiler,
    Both,
}

/// Library storage mode.
#[derive(Debug, Clone, PartialEq)]
pub enum LibsMode {
    Cargo,
    Local(String),
}

/// Distribution mode
#[derive(Debug, Clone, PartialEq)]
pub enum Dist {
    Standalone,
    Interpreted,
    Both,
}

/// Compatibility mode for versioning
#[derive(Debug, Clone, PartialEq)]
pub enum Compat {
    Strict,
    Loose,
}

/// Debug level
#[derive(Debug, Clone, PartialEq)]
pub enum Debug {
    StackTrace,
    Full,
}

/// Sandbox mode for runtime safety.
#[derive(Debug, Clone, PartialEq)]
pub enum SafeMode {
    Full,
    Safe,
}

/// CLI command type
pub enum Cli {
    Run,
    Build,
    Format,
    Check,
    Init,
    Repl,
    Test,
    Add,
    Update,
    Docs,
    Cancel,
    Lsp,
    Custom(Box<dyn Fn(Vec<String>) + Send + Sync>),
}

impl std::fmt::Debug for Cli {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Cli::Run => write!(f, "Run"),
            Cli::Build => write!(f, "Build"),
            Cli::Format => write!(f, "Format"),
            Cli::Check => write!(f, "Check"),
            Cli::Init => write!(f, "Init"),
            Cli::Repl => write!(f, "Repl"),
            Cli::Test => write!(f, "Test"),
            Cli::Add => write!(f, "Add"),
            Cli::Update => write!(f, "Update"),
            Cli::Docs => write!(f, "Docs"),
            Cli::Cancel => write!(f, "Cancel"),
            Cli::Lsp => write!(f, "Lsp"),
            Cli::Custom(_) => write!(f, "Custom"),
        }
    }
}

/// A module namespace of builtin functions.
pub struct Module {
    pub name: String,
    pub actions: HashMap<String, Action>,
}

impl Module {
    pub fn new(name: &str) -> Self {
        Self {
            name: name.to_string(),
            actions: HashMap::new(),
        }
    }

    pub fn action(&mut self, name: &str, action: Action) {
        self.actions.insert(name.to_string(), action);
    }
}

/// A value in the language
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
    Int(i64),
    Float(f64),
    Str(String),
    Bool(bool),
    Null,
    Array(Vec<Value>),
    Tuple(Vec<Value>),
    Map(HashMap<String, Value>),
    Set(Vec<Value>),
    Object(String, HashMap<String, Value>),
}

impl std::fmt::Display for Value {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Value::Int(n) => write!(f, "{}", n),
            Value::Float(n) => write!(f, "{}", n),
            Value::Str(s) => write!(f, "{}", s),
            Value::Bool(b) => write!(f, "{}", b),
            Value::Null => write!(f, "null"),
            Value::Array(arr) => {
                write!(f, "[")?;
                for (i, v) in arr.iter().enumerate() {
                    if i > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{}", v)?;
                }
                write!(f, "]")
            }
            Value::Tuple(items) => {
                write!(f, "(")?;
                for (i, v) in items.iter().enumerate() {
                    if i > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{}", v)?;
                }
                write!(f, ")")
            }
            Value::Map(map) => {
                write!(f, "{{")?;
                let mut first = true;
                for (k, v) in map {
                    if !first {
                        write!(f, ", ")?;
                    }
                    first = false;
                    write!(f, "{}: {}", k, v)?;
                }
                write!(f, "}}")
            }
            Value::Set(items) => {
                write!(f, "{{")?;
                for (i, v) in items.iter().enumerate() {
                    if i > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{}", v)?;
                }
                write!(f, "}}")
            }
            Value::Object(name, fields) => {
                write!(f, "{}{{", name)?;
                let mut first = true;
                for (k, v) in fields {
                    if !first {
                        write!(f, ", ")?;
                    }
                    first = false;
                    write!(f, "{}: {}", k, v)?;
                }
                write!(f, "}}")
            }
        }
    }
}

/// Interface for actions to interact with the interpreter/compiler state.
pub trait Interpretable {
    fn get_var(&self, name: &str) -> Option<Value>;
    fn set_var(&mut self, name: &str, val: Value, is_mut: bool);
    fn call_func(&mut self, name: &str, args: Vec<Value>) -> Result<Value, String>;
}

/// An action the language can perform, now with access to the interpreter/compiler.
pub type Action = Box<dyn Fn(&mut dyn Interpretable, Vec<Value>) -> Value + Send + Sync>;