Skip to content

Commit 51184bf

Browse files
committed
feat: support arbitrary length arrays with metadata and default
1 parent 1c939fe commit 51184bf

File tree

1 file changed

+96
-15
lines changed

1 file changed

+96
-15
lines changed

src/systems/model_parsing.jl

Lines changed: 96 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,96 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
222222
varclass, where_types, meta)
223223
return var, def, Dict()
224224
end
225+
Expr(:tuple, Expr(:ref, a, b...), y) => begin
226+
varname = Meta.isexpr(a, :call) ? a.args[1] : a
227+
push!(kwargs, Expr(:kw, varname, nothing))
228+
if varclass == :parameters
229+
var = :($varname = $first(@parameters $a[$(b...)] = ($varname, $y)))
230+
else
231+
var = :($varname = $first(@variables $a[$(b...)] = ($varname, $y)))
232+
end
233+
#TODO: update `dict` aka `Model.structure` with the metadata
234+
(:($varname...), var), nothing, Dict()
235+
end
236+
Expr(:(=), Expr(:ref, a, b...), y) => begin
237+
varname = Meta.isexpr(a, :call) ? a.args[1] : a
238+
if Meta.isexpr(y, :tuple)
239+
val, y = (y.args[1], y.args[2:end])
240+
push!(kwargs, Expr(:kw, varname, nothing))
241+
if varclass == :parameters
242+
var = :($varname = $varname === nothing ? $val : $varname;
243+
$varname = $first(@parameters $a[$(b...)] = (
244+
$varname, $(y...))))
245+
else
246+
var = :($varname = $varname === nothing ? $val : $varname;
247+
$varname = $first(@variables $a[$(b...)] = (
248+
$varname, $(y...))))
249+
end
250+
else
251+
push!(kwargs, Expr(:kw, varname, nothing))
252+
if varclass == :parameters
253+
var = :($varname = $varname === nothing ? $y : $varname; $varname = $first(@parameters $a[$(b...)] = $varname))
254+
else
255+
var = :($varname = $varname === nothing ? $y : $varname; $varname = $first(@variables $a[$(b...)] = $varname))
256+
end
257+
end
258+
#TODO: update `dict`` aka `Model.structure` with the metadata
259+
(:($varname...), var), nothing, Dict()
260+
end
261+
Expr(:(=), Expr(:(::), Expr(:ref, a, b...), n), y) => begin
262+
varname = Meta.isexpr(a, :call) ? a.args[1] : a
263+
if Meta.isexpr(y, :tuple)
264+
val, y = (y.args[1], y.args[2:end])
265+
push!(kwargs, Expr(:kw, varname, nothing))
266+
if varclass == :parameters
267+
var = :(
268+
$varname = $varname = $varname === nothing ? $val : $varname;
269+
$varname = $first(@parameters $a[$(b...)]::$n = ($varname, $(y...)))
270+
)
271+
else
272+
var = :($varname = $varname === nothing ? $val : $varname;
273+
$varname = $first(@variables $a[$(b...)]::$n = (
274+
$varname, $(y...))))
275+
end
276+
else
277+
push!(kwargs, Expr(:kw, varname, y))
278+
if varclass == :parameters
279+
var = :($varname = $first(@parameters $a[$(b...)]::$n = $varname))
280+
else
281+
var = :($varname = $first(@variables $a[$(b...)]::$n = $varname))
282+
end
283+
end
284+
#TODO: update `dict`` aka `Model.structure` with the metadata
285+
(:($varname...), var), nothing, Dict()
286+
end
287+
Expr(:tuple, Expr(:(::), Expr(:ref, a, b...), n), y) => begin
288+
varname = Meta.isexpr(a, :call) ? a.args[1] : a
289+
push!(kwargs, Expr(:kw, varname, nothing))
290+
if varclass == :parameters
291+
var = :($varname = $first(@parameters $a[$(b...)]::$n = ($varname, $y)))
292+
else
293+
var = :($varname = $first(@variables $a[$(b...)]::$n = ($varname, $y)))
294+
end
295+
#TODO: update `dict` aka `Model.structure` with the metadata
296+
(:($varname...), var), nothing, Dict()
297+
end
298+
Expr(:ref, a, b...) => begin
299+
varname = a isa Expr && a.head == :call ? a.args[1] : a
300+
push!(kwargs, Expr(:kw, varname, nothing))
301+
if varclass == :parameters
302+
var = :($varname = $first(@parameters $a[$(b...)] = $varname))
303+
elseif varclass == :variables
304+
var = :($varname = $first(@variables $a[$(b...)] = $varname))
305+
else
306+
throw("Symbolic array with arbitrary length is not handled for $varclass.
307+
Please open an issue with an example.")
308+
end
309+
dict[varclass] = get!(dict, varclass) do
310+
Dict{Symbol, Dict{Symbol, Any}}()
311+
end
312+
# dict[:kwargs][varname] = dict[varclass][varname] = Dict(:size => b)
313+
(:($varname...), var), nothing, Dict()
314+
end
225315
Expr(:(=), a, b) => begin
226316
Base.remove_linenums!(b)
227317
def, meta = parse_default(mod, b)
@@ -268,14 +358,6 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
268358
end
269359
return var, def, Dict()
270360
end
271-
Expr(:ref, a, b...) => begin
272-
if varclass == :parameters
273-
var = :($a = $first(@parameters $a[$(b...)]))
274-
else
275-
var = :($a = $first(@variables $a[$(b...)]))
276-
end
277-
(:($a...), var), nothing, Dict()
278-
end
279361
_ => error("$arg cannot be parsed")
280362
end
281363
end
@@ -677,11 +759,8 @@ end
677759
function parse_variable_arg(dict, mod, arg, varclass, kwargs, where_types)
678760
vv, def, metadata_with_exprs = parse_variable_def!(
679761
dict, mod, arg, varclass, kwargs, where_types)
680-
if vv isa Tuple
681-
return vv
682-
else
683-
name = getname(vv[1])
684-
762+
if !(vv isa Tuple)
763+
name = getname(vv)
685764
varexpr = if haskey(metadata_with_exprs, VariableUnit)
686765
unit = metadata_with_exprs[VariableUnit]
687766
quote
@@ -692,11 +771,11 @@ function parse_variable_arg(dict, mod, arg, varclass, kwargs, where_types)
692771
$setdefault($vv, $convert_units($unit, $name))
693772
catch e
694773
if isa(e, $(DynamicQuantities.DimensionError)) ||
695-
isa(e, $(Unitful.DimensionError))
774+
isa(e, $(Unitful.DimensionError))
696775
error("Unable to convert units for \'" * string(:($$vv)) * "\'")
697776
elseif isa(e, MethodError)
698777
error("No or invalid units provided for \'" * string(:($$vv)) *
699-
"\'")
778+
"\'")
700779
else
701780
rethrow(e)
702781
end
@@ -721,6 +800,8 @@ function parse_variable_arg(dict, mod, arg, varclass, kwargs, where_types)
721800

722801
push!(varexpr.args, metadata_expr)
723802
return vv isa Num ? name : :($name...), varexpr
803+
else
804+
return vv
724805
end
725806
end
726807

0 commit comments

Comments
 (0)