245
245
function parse_variable_def! (dict, mod, arg, varclass, kwargs, where_types;
246
246
def = nothing , indices:: Union{Vector{UnitRange{Int}}, Nothing} = nothing ,
247
247
type:: Type = Real, meta = Dict {DataType, Expr} ())
248
- metatypes = [(:connection_type , VariableConnectType),
249
- (:description , VariableDescription),
250
- (:unit , VariableUnit),
251
- (:bounds , VariableBounds),
252
- (:noise , VariableNoiseType),
253
- (:input , VariableInput),
254
- (:output , VariableOutput),
255
- (:irreducible , VariableIrreducible),
256
- (:state_priority , VariableStatePriority),
257
- (:misc , VariableMisc),
258
- (:disturbance , VariableDisturbance),
259
- (:tunable , VariableTunable),
260
- (:dist , VariableDistribution)]
261
-
262
248
arg isa LineNumberNode && return
263
249
MLStyle. @match arg begin
264
250
a:: Symbol => begin
@@ -284,27 +270,86 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
284
270
varclass, where_types, meta)
285
271
return var, def, Dict ()
286
272
end
273
+ Expr (:tuple , Expr (:(:: ), Expr (:ref , a, indices... ), type), meta_val) ||
274
+ Expr (:tuple , Expr (:ref , a, indices... ), meta_val) => begin
275
+ (@isdefined type) || (type = Real)
276
+ varname = Meta. isexpr (a, :call ) ? a. args[1 ] : a
277
+ push! (kwargs, Expr (:kw , varname, nothing ))
278
+ meta = parse_metadata (mod, meta_val)
279
+ varval = (@isdefined default_val) ? default_val :
280
+ unit_handled_variable_value (meta, varname)
281
+ if varclass == :parameters
282
+ var = :($ varname = $ first (@parameters ($ a[$ (indices... )]:: $type = $ varval),
283
+ $ meta_val))
284
+ else
285
+ var = :($ varname = $ first (@variables ($ a[$ (indices)]:: $type = $ varval),
286
+ $ meta_val))
287
+ end
288
+ push_array_kwargs_and_metadata! (
289
+ dict, indices, meta, type, varclass, varname, varval)
290
+ (:($ varname... ), var), nothing , Dict ()
291
+ end
292
+ Expr (:(= ), Expr (:(:: ), Expr (:ref , a, indices... ), type), def_n_meta) ||
293
+ Expr (:(= ), Expr (:ref , a, indices... ), def_n_meta) => begin
294
+ (@isdefined type) || (type = Real)
295
+ varname = Meta. isexpr (a, :call ) ? a. args[1 ] : a
296
+ if Meta. isexpr (def_n_meta, :tuple )
297
+ meta = parse_metadata (mod, def_n_meta)
298
+ varval = unit_handled_variable_value (meta, varname)
299
+ val, def_n_meta = (def_n_meta. args[1 ], def_n_meta. args[2 : end ])
300
+ push! (kwargs, Expr (:kw , varname, nothing ))
301
+ if varclass == :parameters
302
+ var = :($ varname = $ varname === nothing ? $ val : $ varname;
303
+ $ varname = $ first (@parameters ($ a[$ (indices... )]:: $type = $ varval),
304
+ $ (def_n_meta... )))
305
+ else
306
+ var = :($ varname = $ varname === nothing ? $ val : $ varname;
307
+ $ varname = $ first (@variables $ a[$ (indices... )]:: $type = (
308
+ $ varval),
309
+ $ (def_n_meta... )))
310
+ end
311
+ else
312
+ push! (kwargs, Expr (:kw , varname, nothing ))
313
+ if varclass == :parameters
314
+ var = :($ varname = $ varname === nothing ? $ def_n_meta : $ varname;
315
+ $ varname = $ first (@parameters $ a[$ (indices... )]:: $type = $ varname))
316
+ else
317
+ var = :($ varname = $ varname === nothing ? $ def_n_meta : $ varname;
318
+ $ varname = $ first (@variables $ a[$ (indices... )]:: $type = $ varname))
319
+ end
320
+ varval, meta = def_n_meta, nothing
321
+ end
322
+ push_array_kwargs_and_metadata! (
323
+ dict, indices, meta, type, varclass, varname, varval)
324
+ (:($ varname... ), var), nothing , Dict ()
325
+ end
326
+ Expr (:(:: ), Expr (:ref , a, indices... ), type) ||
327
+ Expr (:ref , a, indices... ) => begin
328
+ (@isdefined type) || (type = Real)
329
+ varname = a isa Expr && a. head == :call ? a. args[1 ] : a
330
+ push! (kwargs, Expr (:kw , varname, nothing ))
331
+ if varclass == :parameters
332
+ var = :($ varname = $ first (@parameters $ a[$ (indices... )]:: $type = $ varname))
333
+ elseif varclass == :variables
334
+ var = :($ varname = $ first (@variables $ a[$ (indices... )]:: $type = $ varname))
335
+ else
336
+ throw (" Symbolic array with arbitrary length is not handled for $varclass .
337
+ Please open an issue with an example." )
338
+ end
339
+ push_array_kwargs_and_metadata! (
340
+ dict, indices, nothing , type, varclass, varname, nothing )
341
+ (:($ varname... ), var), nothing , Dict ()
342
+ end
287
343
Expr (:(= ), a, b) => begin
288
344
Base. remove_linenums! (b)
289
345
def, meta = parse_default (mod, b)
290
346
var, def, _ = parse_variable_def! (
291
347
dict, mod, a, varclass, kwargs, where_types; def, type, meta)
292
- if dict[varclass] isa Vector
293
- dict[varclass][1 ][getname (var)][:default ] = def
294
- else
295
- dict[varclass][getname (var)][:default ] = def
296
- end
348
+ varclass_dict = dict[varclass] isa Vector ? Ref (dict[varclass][1 ]) :
349
+ Ref (dict[varclass])
350
+ varclass_dict[][getname (var)][:default ] = def
297
351
if meta != = nothing
298
- for (type, key) in metatypes
299
- if (mt = get (meta, key, nothing )) != = nothing
300
- key == VariableConnectType && (mt = nameof (mt))
301
- if dict[varclass] isa Vector
302
- dict[varclass][1 ][getname (var)][type] = mt
303
- else
304
- dict[varclass][getname (var)][type] = mt
305
- end
306
- end
307
- end
352
+ update_readable_metadata! (varclass_dict[], meta, getname (var))
308
353
var, metadata_with_exprs = set_var_metadata (var, meta)
309
354
return var, def, metadata_with_exprs
310
355
end
@@ -314,27 +359,15 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
314
359
meta = parse_metadata (mod, b)
315
360
var, def, _ = parse_variable_def! (
316
361
dict, mod, a, varclass, kwargs, where_types; type, meta)
362
+ varclass_dict = dict[varclass] isa Vector ? Ref (dict[varclass][1 ]) :
363
+ Ref (dict[varclass])
317
364
if meta != = nothing
318
- for (type, key) in metatypes
319
- if (mt = get (meta, key, nothing )) != = nothing
320
- key == VariableConnectType && (mt = nameof (mt))
321
- if dict[varclass] isa Vector
322
- dict[varclass][1 ][getname (var)][type] = mt
323
- else
324
- dict[varclass][getname (var)][type] = mt
325
- end
326
- end
327
- end
365
+ update_readable_metadata! (varclass_dict[], meta, getname (var))
328
366
var, metadata_with_exprs = set_var_metadata (var, meta)
329
367
return var, def, metadata_with_exprs
330
368
end
331
369
return var, def, Dict ()
332
370
end
333
- Expr (:ref , a, b... ) => begin
334
- indices = map (i -> UnitRange (i. args[2 ], i. args[end ]), b)
335
- parse_variable_def! (dict, mod, a, varclass, kwargs, where_types;
336
- def, indices, type, meta)
337
- end
338
371
_ => error (" $arg cannot be parsed" )
339
372
end
340
373
end
@@ -442,14 +475,23 @@ function parse_default(mod, a)
442
475
end
443
476
end
444
477
445
- function parse_metadata (mod, a)
478
+ function parse_metadata (mod, a:: Expr )
446
479
MLStyle. @match a begin
447
- Expr (:vect , eles... ) => Dict (parse_metadata (mod, e) for e in eles)
480
+ Expr (:vect , b... ) => Dict (parse_metadata (mod, m) for m in b)
481
+ Expr (:tuple , a, b... ) => parse_metadata (mod, b)
448
482
Expr (:(= ), a, b) => Symbolics. option_to_metadata_type (Val (a)) => get_var (mod, b)
449
483
_ => error (" Cannot parse metadata $a " )
450
484
end
451
485
end
452
486
487
+ function parse_metadata (mod, metadata:: AbstractArray )
488
+ ret = Dict ()
489
+ for m in metadata
490
+ merge! (ret, parse_metadata (mod, m))
491
+ end
492
+ ret
493
+ end
494
+
453
495
function _set_var_metadata! (metadata_with_exprs, a, m, v:: Expr )
454
496
push! (metadata_with_exprs, m => v)
455
497
a
@@ -707,6 +749,7 @@ function parse_variable_arg!(exprs, vs, dict, mod, arg, varclass, kwargs, where_
707
749
end
708
750
709
751
function convert_units (varunits:: DynamicQuantities.Quantity , value)
752
+ value isa Nothing && return nothing
710
753
DynamicQuantities. ustrip (DynamicQuantities. uconvert (
711
754
DynamicQuantities. SymbolicUnits. as_quantity (varunits), value))
712
755
end
@@ -718,6 +761,7 @@ function convert_units(
718
761
end
719
762
720
763
function convert_units (varunits:: Unitful.FreeUnits , value)
764
+ value isa Nothing && return nothing
721
765
Unitful. ustrip (varunits, value)
722
766
end
723
767
@@ -736,47 +780,50 @@ end
736
780
function parse_variable_arg (dict, mod, arg, varclass, kwargs, where_types)
737
781
vv, def, metadata_with_exprs = parse_variable_def! (
738
782
dict, mod, arg, varclass, kwargs, where_types)
739
- name = getname (vv)
740
-
741
- varexpr = if haskey (metadata_with_exprs, VariableUnit)
742
- unit = metadata_with_exprs[VariableUnit]
743
- quote
744
- $ name = if $ name === $ NO_VALUE
745
- $ setdefault ($ vv, $ def)
746
- else
747
- try
748
- $ setdefault ($ vv, $ convert_units ($ unit, $ name))
749
- catch e
750
- if isa (e, $ (DynamicQuantities. DimensionError)) ||
751
- isa (e, $ (Unitful. DimensionError))
752
- error (" Unable to convert units for \' " * string (:($$ vv)) * " \' " )
753
- elseif isa (e, MethodError)
754
- error (" No or invalid units provided for \' " * string (:($$ vv)) *
755
- " \' " )
756
- else
757
- rethrow (e)
783
+ if ! (vv isa Tuple)
784
+ name = getname (vv)
785
+ varexpr = if haskey (metadata_with_exprs, VariableUnit)
786
+ unit = metadata_with_exprs[VariableUnit]
787
+ quote
788
+ $ name = if $ name === $ NO_VALUE
789
+ $ setdefault ($ vv, $ def)
790
+ else
791
+ try
792
+ $ setdefault ($ vv, $ convert_units ($ unit, $ name))
793
+ catch e
794
+ if isa (e, $ (DynamicQuantities. DimensionError)) ||
795
+ isa (e, $ (Unitful. DimensionError))
796
+ error (" Unable to convert units for \' " * string (:($$ vv)) * " \' " )
797
+ elseif isa (e, MethodError)
798
+ error (" No or invalid units provided for \' " * string (:($$ vv)) *
799
+ " \' " )
800
+ else
801
+ rethrow (e)
802
+ end
758
803
end
759
804
end
760
805
end
761
- end
762
- else
763
- quote
764
- $ name = if $ name === $ NO_VALUE
765
- $ setdefault ( $ vv, $ def)
766
- else
767
- $ setdefault ( $ vv, $ name)
806
+ else
807
+ quote
808
+ $ name = if $ name === $ NO_VALUE
809
+ $ setdefault ( $ vv, $ def)
810
+ else
811
+ $ setdefault ( $ vv, $ name)
812
+ end
768
813
end
769
814
end
770
- end
771
815
772
- metadata_expr = Expr (:block )
773
- for (k, v) in metadata_with_exprs
774
- push! (metadata_expr. args,
775
- :($ name = $ wrap ($ set_scalar_metadata ($ unwrap ($ name), $ k, $ v))))
776
- end
816
+ metadata_expr = Expr (:block )
817
+ for (k, v) in metadata_with_exprs
818
+ push! (metadata_expr. args,
819
+ :($ name = $ wrap ($ set_scalar_metadata ($ unwrap ($ name), $ k, $ v))))
820
+ end
777
821
778
- push! (varexpr. args, metadata_expr)
779
- return vv isa Num ? name : :($ name... ), varexpr
822
+ push! (varexpr. args, metadata_expr)
823
+ return vv isa Num ? name : :($ name... ), varexpr
824
+ else
825
+ return vv
826
+ end
780
827
end
781
828
782
829
function handle_conditional_vars! (
0 commit comments