///|
pub(all) enum Value {
  None
  Bool(Bool)
  Int(Int64)
  String(String)
  List(Ref[Array[Value]])
  Tuple(FixedArray[Value])
  Dict(Ref[Map[String, Value]])
  Function(String, (Array[Value], Map[String, Value]) -> Value raise Error)
  BuiltinFunction(
    String,
    (Array[Value], Map[String, Value]) -> Value raise Error
  )
} derive(Show)

///|
pub fn Value::is_truthy(self : Value) -> Bool {
  match self {
    None => false
    Bool(b) => b
    Int(n) => n != 0L
    String(s) => s != ""
    List(items) => items.val.length() > 0
    Tuple(items) => items.length() > 0
    Dict(items) => items.val.length() > 0
    Function(_, _) => true
    BuiltinFunction(_, _) => true
  }
}

///|
pub fn Value::type_name(self : Value) -> String {
  match self {
    None => "NoneType"
    Bool(_) => "bool"
    Int(_) => "int"
    String(_) => "string"
    List(_) => "list"
    Tuple(_) => "tuple"
    Dict(_) => "dict"
    Function(_, _) => "function"
    BuiltinFunction(_, _) => "builtin_function_or_method"
  }
}