@@ -51,7 +51,7 @@ function _model_macro(mod, name, expr, isconnector)
5151 c_evts = []
5252 d_evts = []
5353 kwargs = OrderedCollections. OrderedSet ()
54- where_types = Expr[]
54+ where_types = Union{Symbol, Expr} []
5555
5656 push! (exprs. args, :(variables = []))
5757 push! (exprs. args, :(parameters = []))
143143pop_structure_dict! (dict, key) = length (dict[key]) == 0 && pop! (dict, key)
144144
145145function update_kwargs_and_metadata! (dict, kwargs, a, def, indices, type, var,
146- varclass, where_types)
146+ varclass, where_types, meta )
147147 if indices isa Nothing
148- push! (kwargs, Expr (:kw , Expr (:(:: ), a, Union{Nothing, type}), nothing ))
148+ if ! isnothing (meta) && haskey (meta, VariableUnit)
149+ uvar = gensym ()
150+ push! (where_types, uvar)
151+ push! (kwargs, Expr (:kw , :($ a:: Union{Nothing, $uvar} ), nothing ))
152+ else
153+ push! (kwargs, Expr (:kw , :($ a:: Union{Nothing, $type} ), nothing ))
154+ end
149155 dict[:kwargs ][getname (var)] = Dict (:value => def, :type => type)
150156 else
151157 vartype = gensym (:T )
@@ -154,7 +160,11 @@ function update_kwargs_and_metadata!(dict, kwargs, a, def, indices, type, var,
154160 Expr (:(:: ), a,
155161 Expr (:curly , :Union , :Nothing , Expr (:curly , :AbstractArray , vartype))),
156162 nothing ))
157- push! (where_types, :($ vartype <: $type ))
163+ if ! isnothing (meta) && haskey (meta, VariableUnit)
164+ push! (where_types, vartype)
165+ else
166+ push! (where_types, :($ vartype <: $type ))
167+ end
158168 dict[:kwargs ][getname (var)] = Dict (:value => def, :type => AbstractArray{type})
159169 end
160170 if dict[varclass] isa Vector
166176
167177function parse_variable_def! (dict, mod, arg, varclass, kwargs, where_types;
168178 def = nothing , indices:: Union{Vector{UnitRange{Int}}, Nothing} = nothing ,
169- type:: Type = Real)
179+ type:: Type = Real, meta = Dict {DataType, Expr} () )
170180 metatypes = [(:connection_type , VariableConnectType),
171181 (:description , VariableDescription),
172182 (:unit , VariableUnit),
@@ -186,29 +196,31 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
186196 a:: Symbol => begin
187197 var = generate_var! (dict, a, varclass; indices, type)
188198 update_kwargs_and_metadata! (dict, kwargs, a, def, indices, type, var,
189- varclass, where_types)
199+ varclass, where_types, meta )
190200 return var, def, Dict ()
191201 end
192202 Expr (:(:: ), a, type) => begin
193203 type = getfield (mod, type)
194- parse_variable_def! (dict, mod, a, varclass, kwargs, where_types; def, type)
204+ parse_variable_def! (
205+ dict, mod, a, varclass, kwargs, where_types; def, type, meta)
195206 end
196207 Expr (:(:: ), Expr (:call , a, b), type) => begin
197208 type = getfield (mod, type)
198209 def = _type_check! (def, a, type, varclass)
199- parse_variable_def! (dict, mod, a, varclass, kwargs, where_types; def, type)
210+ parse_variable_def! (
211+ dict, mod, a, varclass, kwargs, where_types; def, type, meta)
200212 end
201213 Expr (:call , a, b) => begin
202214 var = generate_var! (dict, a, b, varclass, mod; indices, type)
203215 update_kwargs_and_metadata! (dict, kwargs, a, def, indices, type, var,
204- varclass, where_types)
216+ varclass, where_types, meta )
205217 return var, def, Dict ()
206218 end
207219 Expr (:(= ), a, b) => begin
208220 Base. remove_linenums! (b)
209221 def, meta = parse_default (mod, b)
210222 var, def, _ = parse_variable_def! (
211- dict, mod, a, varclass, kwargs, where_types; def, type)
223+ dict, mod, a, varclass, kwargs, where_types; def, type, meta )
212224 if dict[varclass] isa Vector
213225 dict[varclass][1 ][getname (var)][:default ] = def
214226 else
@@ -231,9 +243,9 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
231243 return var, def, Dict ()
232244 end
233245 Expr (:tuple , a, b) => begin
234- var, def, _ = parse_variable_def! (
235- dict, mod, a, varclass, kwargs, where_types; type)
236246 meta = parse_metadata (mod, b)
247+ var, def, _ = parse_variable_def! (
248+ dict, mod, a, varclass, kwargs, where_types; type, meta)
237249 if meta != = nothing
238250 for (type, key) in metatypes
239251 if (mt = get (meta, key, nothing )) != = nothing
@@ -253,7 +265,7 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
253265 Expr (:ref , a, b... ) => begin
254266 indices = map (i -> UnitRange (i. args[2 ], i. args[end ]), b)
255267 parse_variable_def! (dict, mod, a, varclass, kwargs, where_types;
256- def, indices, type)
268+ def, indices, type, meta )
257269 end
258270 _ => error (" $arg cannot be parsed" )
259271 end
@@ -611,16 +623,58 @@ function parse_variable_arg!(exprs, vs, dict, mod, arg, varclass, kwargs, where_
611623 push! (exprs, ex)
612624end
613625
626+ function convert_units (varunits:: DynamicQuantities.Quantity , value)
627+ DynamicQuantities. ustrip (DynamicQuantities. uconvert (
628+ DynamicQuantities. SymbolicUnits. as_quantity (varunits), value))
629+ end
630+
631+ function convert_units (
632+ varunits:: DynamicQuantities.Quantity , value:: AbstractArray{T} ) where {T}
633+ DynamicQuantities. ustrip .(DynamicQuantities. uconvert .(
634+ DynamicQuantities. SymbolicUnits. as_quantity (varunits), value))
635+ end
636+
637+ function convert_units (varunits:: Unitful.FreeUnits , value)
638+ Unitful. ustrip (varunits, value)
639+ end
640+
641+ function convert_units (varunits:: Unitful.FreeUnits , value:: AbstractArray{T} ) where {T}
642+ Unitful. ustrip .(varunits, value)
643+ end
644+
614645function parse_variable_arg (dict, mod, arg, varclass, kwargs, where_types)
615646 vv, def, metadata_with_exprs = parse_variable_def! (
616647 dict, mod, arg, varclass, kwargs, where_types)
617648 name = getname (vv)
618649
619- varexpr = quote
620- $ name = if $ name === nothing
621- $ setdefault ($ vv, $ def)
622- else
623- $ setdefault ($ vv, $ name)
650+ varexpr = if haskey (metadata_with_exprs, VariableUnit)
651+ unit = metadata_with_exprs[VariableUnit]
652+ quote
653+ $ name = if $ name === nothing
654+ $ setdefault ($ vv, $ def)
655+ else
656+ try
657+ $ setdefault ($ vv, $ convert_units ($ unit, $ name))
658+ catch e
659+ if isa (e, $ (DynamicQuantities. DimensionError)) ||
660+ isa (e, $ (Unitful. DimensionError))
661+ error (" Unable to convert units for \' " * string (:($$ vv)) * " \' " )
662+ elseif isa (e, MethodError)
663+ error (" No or invalid units provided for \' " * string (:($$ vv)) *
664+ " \' " )
665+ else
666+ rethrow (e)
667+ end
668+ end
669+ end
670+ end
671+ else
672+ quote
673+ $ name = if $ name === nothing
674+ $ setdefault ($ vv, $ def)
675+ else
676+ $ setdefault ($ vv, $ name)
677+ end
624678 end
625679 end
626680
0 commit comments