
use type

global check_recursion : Array[ptr] (.{})

+ fn value(data: $T) Value {

    #if is_nullable_type(T)
    if !isset(data) : return new_null()
    #end

    #if is_structural_type(T)
    #if is_pointer_type(T)
    if check_recursion.contains(data) : return new_string("(recursion)")
    check_recursion.append(data)
    #end
    #end

    #if type_has_method(T, to_json_value)
    let v = data.to_json_value()
    #elif is_integer_type(T)
    return new_int(data.to(type:int))
    #elif is_float_type(T)
    return new_float(data)
    #elif is_bool_type(T)
    return new_bool(data)
    #elif !is_structural_type(T)
    return new_null()
    // #print_type(T)
    // #error "Cannot convert value to json"
        // #if is_pointer_type(T)
        // return new_string(data.@cast(ptr))
        // #else
        // return data
        // #end
    #else
        // Structural
        let i = Map[Value]{}

        #loop object data as prop
        i.set(prop.name, value(prop.value))
        #end // End loop
        let v = new_object(i)
    #end

    #if is_structural_type(T)
    #if is_pointer_type(T)
    check_recursion.pop_last() _
    #end
    #end

    return v
}
