@@ -180,6 +180,16 @@ function update_kwargs_and_metadata!(dict, kwargs, a, def, indices, type, var,
180180 end
181181end
182182
183+ function unit_handled_variable_value (mod, y, varname)
184+ meta = parse_metadata (mod, y)
185+ varval = if meta isa Nothing || get (meta, VariableUnit, nothing ) isa Nothing
186+ varname
187+ else
188+ :($ convert_units ($ (meta[VariableUnit]), $ varname))
189+ end
190+ return varval
191+ end
192+
183193function parse_variable_def! (dict, mod, arg, varclass, kwargs, where_types;
184194 def = nothing , indices:: Union{Vector{UnitRange{Int}}, Nothing} = nothing ,
185195 type:: Type = Real, meta = Dict {DataType, Expr} ())
@@ -222,6 +232,66 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
222232 varclass, where_types, meta)
223233 return var, def, Dict ()
224234 end
235+ Expr (:tuple , Expr (:(:: ), Expr (:ref , a, b... ), type), y) || Expr (:tuple , Expr (:ref , a, b... ), y) => begin
236+ (@isdefined type) || (type = Real)
237+ varname = Meta. isexpr (a, :call ) ? a. args[1 ] : a
238+ push! (kwargs, Expr (:kw , varname, nothing ))
239+ varval = unit_handled_variable_value (mod, y, varname)
240+ if varclass == :parameters
241+ var = :($ varname = $ first (@parameters $ a[$ (b... )]:: $type = ($ varval, $ y)))
242+ else
243+ var = :($ varname = $ first (@variables $ a[$ (b... )]:: $type = ($ varval, $ y)))
244+ end
245+ # TODO : update `dict` aka `Model.structure` with the metadata
246+ (:($ varname... ), var), nothing , Dict ()
247+ end
248+ Expr (:(= ), Expr (:(:: ), Expr (:ref , a, b... ), type), y) || Expr (:(= ), Expr (:ref , a, b... ), y) => begin
249+ (@isdefined type) || (type = Real)
250+ varname = Meta. isexpr (a, :call ) ? a. args[1 ] : a
251+ if Meta. isexpr (y, :tuple )
252+ varval = unit_handled_variable_value (mod, y, varname)
253+ val, y = (y. args[1 ], y. args[2 : end ])
254+ push! (kwargs, Expr (:kw , varname, nothing ))
255+ if varclass == :parameters
256+ var = :($ varname = $ varname === nothing ? $ val : $ varname;
257+ $ varname = $ first (@parameters $ a[$ (b... )]:: $type = (
258+ $ varval, $ (y... ))))
259+ else
260+ var = :($ varname = $ varname === nothing ? $ val : $ varname;
261+ $ varname = $ first (@variables $ a[$ (b... )]:: $type = (
262+ $ varval, $ (y... ))))
263+ end
264+ else
265+ push! (kwargs, Expr (:kw , varname, nothing ))
266+ if varclass == :parameters
267+ var = :($ varname = $ varname === nothing ? $ y : $ varname;
268+ $ varname = $ first (@parameters $ a[$ (b... )]:: $type = $ varname))
269+ else
270+ var = :($ varname = $ varname === nothing ? $ y : $ varname;
271+ $ varname = $ first (@variables $ a[$ (b... )]:: $type = $ varname))
272+ end
273+ end
274+ # TODO : update `dict`` aka `Model.structure` with the metadata
275+ (:($ varname... ), var), nothing , Dict ()
276+ end
277+ Expr (:(:: ), Expr (:ref , a, b... ), type) || Expr (:ref , a, b... ) => begin
278+ (@isdefined type) || (type = Real)
279+ varname = a isa Expr && a. head == :call ? a. args[1 ] : a
280+ push! (kwargs, Expr (:kw , varname, nothing ))
281+ if varclass == :parameters
282+ var = :($ varname = $ first (@parameters $ a[$ (b... )]:: $type = $ varname))
283+ elseif varclass == :variables
284+ var = :($ varname = $ first (@variables $ a[$ (b... )]:: $type = $ varname))
285+ else
286+ throw (" Symbolic array with arbitrary length is not handled for $varclass .
287+ Please open an issue with an example." )
288+ end
289+ dict[varclass] = get! (dict, varclass) do
290+ Dict {Symbol, Dict{Symbol, Any}} ()
291+ end
292+ # dict[:kwargs][varname] = dict[varclass][varname] = Dict(:size => b)
293+ (:($ varname... ), var), nothing , Dict ()
294+ end
225295 Expr (:(= ), a, b) => begin
226296 Base. remove_linenums! (b)
227297 def, meta = parse_default (mod, b)
@@ -268,11 +338,6 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
268338 end
269339 return var, def, Dict ()
270340 end
271- Expr (:ref , a, b... ) => begin
272- indices = map (i -> UnitRange (i. args[2 ], i. args[end ]), b)
273- parse_variable_def! (dict, mod, a, varclass, kwargs, where_types;
274- def, indices, type, meta)
275- end
276341 _ => error (" $arg cannot be parsed" )
277342 end
278343end
@@ -380,14 +445,23 @@ function parse_default(mod, a)
380445 end
381446end
382447
383- function parse_metadata (mod, a)
448+ function parse_metadata (mod, a:: Expr )
384449 MLStyle. @match a begin
385- Expr (:vect , eles... ) => Dict (parse_metadata (mod, e) for e in eles)
450+ Expr (:vect , b... ) => Dict (parse_metadata (mod, m) for m in b)
451+ Expr (:tuple , a, b... ) => parse_metadata (mod, b)
386452 Expr (:(= ), a, b) => Symbolics. option_to_metadata_type (Val (a)) => get_var (mod, b)
387453 _ => error (" Cannot parse metadata $a " )
388454 end
389455end
390456
457+ function parse_metadata (mod, metadata:: AbstractArray )
458+ ret = Dict ()
459+ for m in metadata
460+ merge! (ret, parse_metadata (mod, m))
461+ end
462+ ret
463+ end
464+
391465function _set_var_metadata! (metadata_with_exprs, a, m, v:: Expr )
392466 push! (metadata_with_exprs, m => v)
393467 a
@@ -645,6 +719,7 @@ function parse_variable_arg!(exprs, vs, dict, mod, arg, varclass, kwargs, where_
645719end
646720
647721function convert_units (varunits:: DynamicQuantities.Quantity , value)
722+ value isa Nothing && return nothing
648723 DynamicQuantities. ustrip (DynamicQuantities. uconvert (
649724 DynamicQuantities. SymbolicUnits. as_quantity (varunits), value))
650725end
@@ -656,6 +731,7 @@ function convert_units(
656731end
657732
658733function convert_units (varunits:: Unitful.FreeUnits , value)
734+ value isa Nothing && return nothing
659735 Unitful. ustrip (varunits, value)
660736end
661737
@@ -674,47 +750,50 @@ end
674750function parse_variable_arg (dict, mod, arg, varclass, kwargs, where_types)
675751 vv, def, metadata_with_exprs = parse_variable_def! (
676752 dict, mod, arg, varclass, kwargs, where_types)
677- name = getname (vv)
678-
679- varexpr = if haskey (metadata_with_exprs, VariableUnit)
680- unit = metadata_with_exprs[VariableUnit]
681- quote
682- $ name = if $ name === nothing
683- $ setdefault ($ vv, $ def)
684- else
685- try
686- $ setdefault ($ vv, $ convert_units ($ unit, $ name))
687- catch e
688- if isa (e, $ (DynamicQuantities. DimensionError)) ||
689- isa (e, $ (Unitful. DimensionError))
690- error (" Unable to convert units for \' " * string (:($$ vv)) * " \' " )
691- elseif isa (e, MethodError)
692- error (" No or invalid units provided for \' " * string (:($$ vv)) *
693- " \' " )
694- else
695- rethrow (e)
753+ if ! (vv isa Tuple)
754+ name = getname (vv)
755+ varexpr = if haskey (metadata_with_exprs, VariableUnit)
756+ unit = metadata_with_exprs[VariableUnit]
757+ quote
758+ $ name = if $ name === nothing
759+ $ setdefault ($ vv, $ def)
760+ else
761+ try
762+ $ setdefault ($ vv, $ convert_units ($ unit, $ name))
763+ catch e
764+ if isa (e, $ (DynamicQuantities. DimensionError)) ||
765+ isa (e, $ (Unitful. DimensionError))
766+ error (" Unable to convert units for \' " * string (:($$ vv)) * " \' " )
767+ elseif isa (e, MethodError)
768+ error (" No or invalid units provided for \' " * string (:($$ vv)) *
769+ " \' " )
770+ else
771+ rethrow (e)
772+ end
696773 end
697774 end
698775 end
699- end
700- else
701- quote
702- $ name = if $ name === nothing
703- $ setdefault ( $ vv, $ def)
704- else
705- $ setdefault ( $ vv, $ name)
776+ else
777+ quote
778+ $ name = if $ name === nothing
779+ $ setdefault ( $ vv, $ def)
780+ else
781+ $ setdefault ( $ vv, $ name)
782+ end
706783 end
707784 end
708- end
709785
710- metadata_expr = Expr (:block )
711- for (k, v) in metadata_with_exprs
712- push! (metadata_expr. args,
713- :($ name = $ wrap ($ set_scalar_metadata ($ unwrap ($ name), $ k, $ v))))
714- end
786+ metadata_expr = Expr (:block )
787+ for (k, v) in metadata_with_exprs
788+ push! (metadata_expr. args,
789+ :($ name = $ wrap ($ set_scalar_metadata ($ unwrap ($ name), $ k, $ v))))
790+ end
715791
716- push! (varexpr. args, metadata_expr)
717- return vv isa Num ? name : :($ name... ), varexpr
792+ push! (varexpr. args, metadata_expr)
793+ return vv isa Num ? name : :($ name... ), varexpr
794+ else
795+ return vv
796+ end
718797end
719798
720799function handle_conditional_vars! (
0 commit comments