Skip to content

Commit 71ba105

Browse files
authored
Merge pull request #415 from mimiframework/eliminate_global_comp_dict
Eliminate global comp dict
2 parents 2eeca0f + 84eb98f commit 71ba105

11 files changed

+49
-101
lines changed

src/Mimi.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ end
8787

8888
# Components are defined here to allow pre-compilation to work
8989
function __init__()
90-
compdir = joinpath(dirname(@__FILE__), "components")
90+
compdir = joinpath(@__DIR__, "components")
9191
load_comps(compdir)
9292
end
9393

src/core/connections.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,7 @@ function add_connector_comps(md::ModelDef)
483483
end
484484

485485
# Fetch the definition of the appropriate connector commponent
486-
conn_name = num_dims == 1 ? :ConnectorCompVector : :ConnectorCompMatrix
487-
conn_comp_def = compdef(conn_name)
486+
conn_comp_def = (num_dims == 1 ? Mimi.ConnectorCompVector : Mimi.ConnectorCompMatrix)
488487
conn_comp_name = connector_comp_name(i)
489488

490489
# Add the connector component before the user-defined component that required it

src/core/defcomp.jl

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,14 @@ macro defcomp(comp_name, ex)
136136
comp_name = cmpname
137137
end
138138

139-
# We'll return a block of expressions that will define the component. First,
140-
# save the ComponentId to a variable with the same name as the component.
139+
# We'll return a block of expressions that will define the component.
141140
# @__MODULE__ is evaluated when the expanded macro is interpreted
142141
result = :(
143-
let current_module = @__MODULE__
144-
global const $comp_name = Mimi.ComponentId(nameof(current_module), $(QuoteNode(comp_name)))
142+
let current_module = @__MODULE__,
143+
comp_id = Mimi.ComponentId(nameof(current_module), $(QuoteNode(comp_name))),
144+
comp = Mimi.ComponentDef(comp_id)
145+
146+
global $comp_name = comp
145147
end
146148
)
147149

@@ -151,9 +153,6 @@ macro defcomp(comp_name, ex)
151153
push!(let_block, expr)
152154
end
153155

154-
newcomp = :(comp = new_comp($comp_name, $defcomp_verbosity))
155-
addexpr(newcomp)
156-
157156
for elt in elements
158157
@debug "elt: $elt"
159158

@@ -241,22 +240,22 @@ macro defcomp(comp_name, ex)
241240

242241
@debug " index $(Tuple(dimensions)), unit '$unit', desc '$desc'"
243242

244-
dflt = eval(dflt)
245-
if (dflt !== nothing && length(dimensions) != ndims(dflt))
246-
error("Default value has different number of dimensions ($(ndims(dflt))) than parameter '$name' ($(length(dimensions)))")
243+
if dflt !== nothing
244+
dflt = Base.eval(Main, dflt)
245+
if length(dimensions) != ndims(dflt)
246+
error("Default value has different number of dimensions ($(ndims(dflt))) than parameter '$name' ($(length(dimensions)))")
247+
end
247248
end
248249

249-
vartype = vartype === nothing ? Number : eval(vartype)
250+
vartype = (vartype === nothing ? Number : Base.eval(Main, vartype))
250251
addexpr(_generate_var_or_param(elt_type, name, vartype, dimensions, dflt, desc, unit))
251252

252253
else
253254
error("Unrecognized element type: $elt_type")
254255
end
255256
end
256257

257-
# addexpr(:($comp_name))
258258
addexpr(:(nothing)) # reduces noise
259-
260259
return esc(result)
261260
end
262261

@@ -297,7 +296,7 @@ macro defmodel(model_name, ex)
297296
addexpr(expr)
298297

299298
name = (alias === nothing ? comp_name : alias)
300-
expr = :(add_comp!($model_name, eval(comp_mod_name).$comp_name, $(QuoteNode(name))))
299+
expr = :(add_comp!($model_name, Mimi.ComponentId(comp_mod_name, $(QuoteNode(comp_name))), $(QuoteNode(name))))
301300

302301
# TBD: extend comp.var syntax to allow module name, e.g., FUND.economy.ygross
303302
elseif (@capture(elt, src_comp_.src_name_[arg_] => dst_comp_.dst_name_) ||

src/core/defs.jl

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,4 @@
1-
# Global component registry: @defcomp stores component definitions here
2-
global const _compdefs = Dict{ComponentId, ComponentDef}()
3-
4-
compdefs() = collect(values(_compdefs))
5-
6-
compdef(comp_id::ComponentId) = _compdefs[comp_id]
7-
8-
function compdef(comp_name::Symbol)
9-
matches = collect(Iterators.filter(obj -> name(obj) == comp_name, values(_compdefs)))
10-
count = length(matches)
11-
12-
if count == 1
13-
return matches[1]
14-
elseif count == 0
15-
error("Component $comp_name was not found in the global registry")
16-
else
17-
error("Multiple components named $comp_name were found in the global registry")
18-
end
19-
end
1+
compdef(comp_id::ComponentId) = getfield(getfield(Main, comp_id.module_name), comp_id.comp_name)
202

213
compdefs(md::ModelDef) = values(md.comp_defs)
224

@@ -27,10 +9,8 @@ hascomp(md::ModelDef, comp_name::Symbol) = haskey(md.comp_defs, comp_name)
279
compdef(md::ModelDef, comp_name::Symbol) = md.comp_defs[comp_name]
2810

2911
function reset_compdefs(reload_builtins=true)
30-
empty!(_compdefs)
31-
3212
if reload_builtins
33-
compdir = joinpath(dirname(@__FILE__), "..", "components")
13+
compdir = joinpath(@__DIR__, "..", "components")
3414
load_comps(compdir)
3515
end
3616
end
@@ -43,11 +23,14 @@ last_period(md::ModelDef, comp_def::ComponentDef) = last_period(comp_def) === no
4323

4424
# Return the module object for the component was defined in
4525
compmodule(comp_id::ComponentId) = comp_id.module_name
46-
4726
compname(comp_id::ComponentId) = comp_id.comp_name
4827

28+
compmodule(comp_def::ComponentDef) = compmodule(comp_def.comp_id)
29+
compname(comp_def::ComponentDef) = compname(comp_def.comp_id)
30+
31+
4932
function Base.show(io::IO, comp_id::ComponentId)
50-
print(io, "$(comp_id.module_name).$(comp_id.comp_name)")
33+
print(io, "<ComponentId $(comp_id.module_name).$(comp_id.comp_name)>")
5134
end
5235

5336
"""
@@ -61,40 +44,6 @@ number_type(md::ModelDef) = md.number_type
6144

6245
numcomponents(md::ModelDef) = length(md.comp_defs)
6346

64-
65-
function dump_components()
66-
for comp in compdefs()
67-
println("\n$(name(comp))")
68-
for (tag, objs) in ((:Variables, variables(comp)), (:Parameters, parameters(comp)), (:Dimensions, dimensions(comp)))
69-
println(" $tag")
70-
for obj in objs
71-
println(" $(obj.name) = $obj")
72-
end
73-
end
74-
end
75-
end
76-
77-
"""
78-
new_comp(comp_id::ComponentId, verbose::Bool=true)
79-
80-
Add an empty `ComponentDef` to the global component registry with the given
81-
`comp_id`. The empty `ComponentDef` must be populated with calls to `addvariable`,
82-
`addparameter`, etc.
83-
"""
84-
function new_comp(comp_id::ComponentId, verbose::Bool=true)
85-
if verbose
86-
if haskey(_compdefs, comp_id)
87-
@warn "Redefining component $comp_id"
88-
else
89-
@info "new component $comp_id"
90-
end
91-
end
92-
93-
comp_def = ComponentDef(comp_id)
94-
_compdefs[comp_id] = comp_def
95-
return comp_def
96-
end
97-
9847
"""
9948
delete!(m::ModelDef, component::Symbol
10049
@@ -529,13 +478,14 @@ function _add_anonymous_dims!(md::ModelDef, comp_def::ComponentDef)
529478
end
530479

531480
"""
532-
add_comp!(md::ModelDef, comp_def::ComponentDef; first=nothing, last=nothing, before=nothing, after=nothing)
481+
add_comp!(md::ModelDef, comp_def::ComponentDef, comp_name::Symbol=comp_def.comp_id.comp_name;
482+
first=nothing, last=nothing, before=nothing, after=nothing)
533483
534484
Add the component indicated by `comp_def` to the model indcated by `md`. The component is added at the
535485
end of the list unless one of the keywords, `first`, `last`, `before`, `after`. If the `comp_name`
536486
differs from that in the `comp_def`, a copy of `comp_def` is made and assigned the new name.
537487
"""
538-
function add_comp!(md::ModelDef, comp_def::ComponentDef, comp_name::Symbol;
488+
function add_comp!(md::ModelDef, comp_def::ComponentDef, comp_name::Symbol=comp_def.comp_id.comp_name;
539489
first::NothingInt=nothing, last::NothingInt=nothing,
540490
before::NothingSymbol=nothing, after::NothingSymbol=nothing)
541491

src/core/model.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ function add_comp!(m::Model, comp_id::ComponentId, comp_name::Symbol=comp_id.com
160160
return ComponentReference(m, comp_name)
161161
end
162162

163+
function add_comp!(m::Model, comp_def::ComponentDef, comp_name::Symbol=comp_def.comp_id.comp_name;
164+
first=nothing, last=nothing, before=nothing, after=nothing)
165+
add_comp!(m.md, comp_def, comp_name; first=first, last=last, before=before, after=after)
166+
decache(m)
167+
return ComponentReference(m, comp_name)
168+
end
169+
163170
"""
164171
replace_comp!(m::Model, comp_id::ComponentId, comp_name::Symbol=comp_id.comp_name;
165172
first::NothingSymbol=nothing, last::NothingSymbol=nothing,
@@ -183,6 +190,13 @@ function replace_comp!(m::Model, comp_id::ComponentId, comp_name::Symbol=comp_id
183190
return ComponentReference(m, comp_name)
184191
end
185192

193+
function replace_comp!(m::Model, comp_def::ComponentDef, comp_name::Symbol=comp_def.comp_id.comp_name;
194+
first::NothingSymbol=nothing, last::NothingSymbol=nothing,
195+
before::NothingSymbol=nothing, after::NothingSymbol=nothing,
196+
reconnect::Bool=true)
197+
replace_comp!(m, comp_def.comp_id, comp_name; first=first, last=last, before=before, after=after, reconnect=reconnect)
198+
end
199+
186200
"""
187201
components(m::Model)
188202

src/core/types.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,16 +357,15 @@ mutable struct ComponentInstance{TV <: ComponentInstanceVariables, TP <: Compone
357357

358358
comp_name = comp_id.comp_name
359359
module_name = comp_id.module_name
360-
comp_module = Base.eval(Main, module_name)
360+
comp_module = getfield(Main, module_name)
361361

362362
# TBD: use FunctionWrapper here?
363363
function get_func(name)
364364
func_name = Symbol("$(name)_$(comp_name)")
365365
try
366-
Base.eval(comp_module, func_name)
366+
getfield(comp_module, func_name)
367367
catch err
368368
# No need to warn about this...
369-
# @warn "Failed to evaluate function name $func_name in module $comp_module"
370369
nothing
371370
end
372371
end

test/test_components.jl

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ using Mimi
44
using Test
55

66
import Mimi:
7-
reset_compdefs, compdefs, compdef, compkeys, hascomp, _compdefs, first_period,
8-
last_period, compmodule, compname, numcomponents, dump_components,
7+
reset_compdefs, compdefs, compdef, compkeys, hascomp, first_period,
8+
last_period, compmodule, compname, numcomponents,
99
dim_keys, dim_values, dimensions
1010

1111
reset_compdefs()
1212

13-
@test length(_compdefs) == 3 # adder, ConnectorCompVector, ConnectorCompMatrix
14-
1513
my_model = Model()
1614

1715
# Try running model with no components
@@ -81,8 +79,7 @@ comps = collect(compdefs(my_model))
8179
# Test compdefs, compdef, compkeys, etc.
8280
@test comps == collect(compdefs(my_model.md))
8381
@test length(comps) == 3
84-
@test compdef(:testcomp3) == comps[3]
85-
@test_throws ErrorException compdef(:testcomp4) #this component does not exist
82+
@test testcomp3 == comps[3]
8683
@test [compkeys(my_model.md)...] == [:testcomp1, :testcomp2, :testcomp3]
8784
@test hascomp(my_model.md, :testcomp1) == true && hascomp(my_model.md, :testcomp4) == false
8885

@@ -93,12 +90,6 @@ comps = collect(compdefs(my_model))
9390
add_comp!(my_model, testcomp3, :testcomp3_v2)
9491
@test numcomponents(my_model) == 4
9592

96-
# Test reset_compdefs methods
97-
reset_compdefs()
98-
@test length(_compdefs) == 3 # adder, ConnectorCompVector, ConnectorCompMatrix
99-
reset_compdefs(false)
100-
@test length(_compdefs) == 0
101-
10293

10394
#------------------------------------------------------------------------------
10495
# Tests for component run periods when resetting the model's time dimension
@@ -115,7 +106,7 @@ end
115106

116107
# 1. Test resetting the time dimension without explicit first/last values
117108

118-
cd = compdef(testcomp1)
109+
cd = testcomp1
119110
@test cd.first === nothing # original component definition's first and last values are unset
120111
@test cd.last === nothing
121112

test/test_main.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ end
3838
foo1.par1 = 5.0
3939
end
4040

41-
@test length(compdefs()) == 4 # adder, 2 connectors, and foo1
42-
4341
# x1 = foo1(Float64, Dict{Symbol, Int}(:time=>10, :index1=>3))
4442
# x1 = foo1(Float64, Val{1}, Val{1}, Val{10}, Val{1}, Val{1}, Val{1}, Val{1}, Dict{Symbol, Int}(:time=>10, :index1=>3))
4543

test/test_main_variabletimestep.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ end
3838
# foo1.par2 = []
3939
end
4040

41-
@test length(compdefs()) == 4 # adder, 2 connectors, and foo1
42-
4341
# x1 = foo1(Float64, Dict{Symbol, Int}(:time=>10, :index1=>3))
4442
# x1 = foo1(Float64, Val{1}, Val{1}, Val{10}, Val{1}, Val{1}, Val{1}, Val{1}, Dict{Symbol, Int}(:time=>10, :index1=>3))
4543

test/test_metainfo.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ end
4040
c1 = compdef(test_model, :ch4forcing1)
4141
c2 = compdef(test_model, :ch4forcing2)
4242

43-
@test c1 == compdef(:ch4forcing1)
44-
@test_throws ErrorException compdef(:missingcomp)
43+
@test c1 == compdef(test_model, :ch4forcing1)
44+
@test_throws KeyError compdef(test_model, :missingcomp)
4545

4646
@test c2.comp_id.module_name == :TestMetaInfo
4747
@test c2.comp_id.comp_name == :ch4forcing1

0 commit comments

Comments
 (0)