NickelEval.jl (2890B)
1 module NickelEval 2 3 export nickel_eval, nickel_eval_file, @ncl_str, NickelError, NickelEnum 4 export nickel_to_json, nickel_to_yaml, nickel_to_toml 5 export check_ffi_available, build_ffi 6 export nickel_open, NickelValue, NickelSession, nickel_kind 7 8 """ 9 NickelError <: Exception 10 11 Exception thrown when Nickel evaluation fails. 12 13 # Fields 14 - `message::String`: The error message from Nickel 15 16 # Examples 17 ```julia 18 try 19 nickel_eval("{ x = }") # syntax error 20 catch e 21 if e isa NickelError 22 println("Nickel error: ", e.message) 23 end 24 end 25 ``` 26 """ 27 struct NickelError <: Exception 28 message::String 29 end 30 31 Base.showerror(io::IO, e::NickelError) = print(io, "NickelError: ", e.message) 32 33 """ 34 NickelEnum 35 36 Represents a Nickel enum value. 37 38 # Fields 39 - `tag::Symbol`: The enum variant name 40 - `arg::Any`: The argument (nothing for simple enums) 41 42 # Examples 43 ```julia 44 result = nickel_eval("let x = 'Some 42 in x") 45 result.tag # => :Some 46 result.arg # => 42 47 result == :Some # => true 48 49 result = nickel_eval("let x = 'None in x") 50 result.tag # => :None 51 result.arg # => nothing 52 ``` 53 """ 54 struct NickelEnum 55 tag::Symbol 56 arg::Any 57 end 58 59 # Convenience: compare enum to symbol 60 Base.:(==)(e::NickelEnum, s::Symbol) = e.tag == s 61 Base.:(==)(s::Symbol, e::NickelEnum) = e.tag == s 62 63 # Pretty printing 64 function Base.show(io::IO, e::NickelEnum) 65 if e.arg === nothing 66 print(io, "'", e.tag) 67 else 68 print(io, "'", e.tag, " ", repr(e.arg)) 69 end 70 end 71 72 # ── Lazy evaluation types ───────────────────────────────────────────────────── 73 74 """ 75 NickelSession 76 77 Owns a Nickel evaluation context for lazy (shallow) evaluation. 78 Tracks all allocated expressions and frees them on `close`. 79 80 Not thread-safe. All access must occur on a single thread. 81 """ 82 mutable struct NickelSession 83 ctx::Ptr{Cvoid} # Ptr{LibNickel.nickel_context} — Cvoid avoids forward ref 84 exprs::Vector{Ptr{Cvoid}} # tracked allocations, freed on close 85 closed::Bool 86 end 87 88 """ 89 NickelValue 90 91 A lazy reference to a Nickel expression. Accessing fields (`.field` or `["field"]`) 92 evaluates only the requested sub-expression. Use `collect` to materialize the 93 full subtree into plain Julia types. 94 95 # Examples 96 ```julia 97 nickel_open("{ x = 1, y = { z = 2 } }") do cfg 98 cfg.x # => 1 99 cfg.y.z # => 2 100 collect(cfg) # => Dict("x" => 1, "y" => Dict("z" => 2)) 101 end 102 ``` 103 """ 104 struct NickelValue 105 session::NickelSession 106 expr::Ptr{Cvoid} # Ptr{LibNickel.nickel_expr} 107 end 108 109 """ 110 @ncl_str -> Any 111 112 String macro for inline Nickel evaluation. 113 114 # Examples 115 ```julia 116 julia> ncl"1 + 1" 117 2 118 119 julia> ncl"{ x = 10 }"["x"] 120 10 121 ``` 122 """ 123 macro ncl_str(code) 124 :(nickel_eval($code)) 125 end 126 127 include("ffi.jl") 128 129 function __init__() 130 __init_ffi__() 131 end 132 133 end # module