///|
/// Typed inputs accepted by the `sympify` coercion entrypoint.
pub(all) enum SympifyInput {
FromExpr(Expr)
FromBool(Bool)
FromInt(Int)
FromRational(@symnum.BigRational)
FromFloat(Float)
FromComplexFloat(ComplexFloat)
NumberSymbol(NumberSymbolKind)
SymbolName(String)
DummyName(String)
WildName(String)
WildSpec(String, Array[SympifyInput], Array[WildProperty])
FunctionHeadName(String)
UndefinedFunctionName(String)
Application(SympifyInput, Array[SympifyInput])
Tuple(Array[SympifyInput])
Dict(Array[(SympifyInput, SympifyInput)])
}
///|
/// Convert a typed value into a core symbolic expression.
///
/// - Does: Lifts a supported host-side input into `Expr`.
/// - Input: A `SympifyInput`.
/// - Returns: A single `Expr`.
/// - Limits: This is typed lifting, not full textual parsing; text parsing
/// belongs in `symparse`.
///
/// ```mbt check
/// test "symcore sympify lifts typed inputs into expr" {
/// let expr = sympify(
/// SympifyInput::Tuple([
/// SympifyInput::FromInt(1),
/// SympifyInput::SymbolName("x"),
/// ]),
/// )
/// inspect(@symprint.pretty_string(expr), content="(1, x)")
/// }
/// ```
pub fn sympify(input : SympifyInput) -> Expr {
match input {
SympifyInput::FromExpr(expr) => normalize_legacy_expr(expr)
SympifyInput::FromBool(value) => Expr::Boolean(value)
SympifyInput::FromInt(value) => int(value)
SympifyInput::FromRational(value) => Expr::Number(value)
SympifyInput::FromFloat(value) => Expr::Float(value)
SympifyInput::FromComplexFloat(value) => Expr::ComplexFloat(value)
SympifyInput::NumberSymbol(kind) => Expr::NumberSymbol(kind)
SympifyInput::SymbolName(name) => Expr::Symbol(name)
SympifyInput::DummyName(name) => dummy(name~)
SympifyInput::WildName(name) => Expr::Wild(name, [], [])
SympifyInput::WildSpec(name, exclude, properties) =>
Expr::Wild(name, exclude.map(sympify), properties)
SympifyInput::FunctionHeadName(name) => Expr::FunctionHead(name)
SympifyInput::UndefinedFunctionName(name) => Expr::UndefinedFunction(name)
SympifyInput::Application(head, args) => {
let head_expr = sympify(head)
let arg_exprs = args.map(sympify)
match apply(head_expr, arg_exprs) {
Some(expr) => expr
None => Expr::Apply(head_expr, arg_exprs)
}
}
SympifyInput::Tuple(items) => Expr::Tuple(items.map(sympify))
SympifyInput::Dict(items) => {
let out : Array[(Expr, Expr)] = []
for item in items {
let (key, value) = item
out.push((sympify(key), sympify(value)))
}
Expr::Dict(out)
}
}
}
///|
/// Treat a string as a symbolic name and lift it into `Expr`.
pub fn sympify_name(name : String) -> Expr {
sympify(SympifyInput::SymbolName(name))
}
///|
/// Lift a tuple payload into a first-class core tuple node.
pub fn sympify_tuple(items : Array[SympifyInput]) -> Expr {
sympify(SympifyInput::Tuple(items))
}
///|
/// Lift dictionary-like key/value pairs into a first-class core dict node.
pub fn sympify_dict(items : Array[(SympifyInput, SympifyInput)]) -> Expr {
sympify(SympifyInput::Dict(items))
}