@@ -180,6 +180,16 @@ function update_kwargs_and_metadata!(dict, kwargs, a, def, indices, type, var,
180
180
end
181
181
end
182
182
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
+
183
193
function parse_variable_def! (dict, mod, arg, varclass, kwargs, where_types;
184
194
def = nothing , indices:: Union{Vector{UnitRange{Int}}, Nothing} = nothing ,
185
195
type:: Type = Real, meta = Dict {DataType, Expr} ())
@@ -222,6 +232,66 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
222
232
varclass, where_types, meta)
223
233
return var, def, Dict ()
224
234
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
225
295
Expr (:(= ), a, b) => begin
226
296
Base. remove_linenums! (b)
227
297
def, meta = parse_default (mod, b)
@@ -268,11 +338,6 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
268
338
end
269
339
return var, def, Dict ()
270
340
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
276
341
_ => error (" $arg cannot be parsed" )
277
342
end
278
343
end
@@ -380,14 +445,23 @@ function parse_default(mod, a)
380
445
end
381
446
end
382
447
383
- function parse_metadata (mod, a)
448
+ function parse_metadata (mod, a:: Expr )
384
449
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)
386
452
Expr (:(= ), a, b) => Symbolics. option_to_metadata_type (Val (a)) => get_var (mod, b)
387
453
_ => error (" Cannot parse metadata $a " )
388
454
end
389
455
end
390
456
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
+
391
465
function _set_var_metadata! (metadata_with_exprs, a, m, v:: Expr )
392
466
push! (metadata_with_exprs, m => v)
393
467
a
@@ -645,6 +719,7 @@ function parse_variable_arg!(exprs, vs, dict, mod, arg, varclass, kwargs, where_
645
719
end
646
720
647
721
function convert_units (varunits:: DynamicQuantities.Quantity , value)
722
+ value isa Nothing && return nothing
648
723
DynamicQuantities. ustrip (DynamicQuantities. uconvert (
649
724
DynamicQuantities. SymbolicUnits. as_quantity (varunits), value))
650
725
end
@@ -656,6 +731,7 @@ function convert_units(
656
731
end
657
732
658
733
function convert_units (varunits:: Unitful.FreeUnits , value)
734
+ value isa Nothing && return nothing
659
735
Unitful. ustrip (varunits, value)
660
736
end
661
737
@@ -674,47 +750,50 @@ end
674
750
function parse_variable_arg (dict, mod, arg, varclass, kwargs, where_types)
675
751
vv, def, metadata_with_exprs = parse_variable_def! (
676
752
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
696
773
end
697
774
end
698
775
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
706
783
end
707
784
end
708
- end
709
785
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
715
791
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
718
797
end
719
798
720
799
function handle_conditional_vars! (
0 commit comments