Module: Origen::Loader
- Defined in:
- lib/origen/loader.rb
Overview
This module is responsible for enhancing how Ruby requires and loads files to support loading of classes and modules from an application’s app dir without having to require them.
It also implements the <model>.load_block method that loads files from app/blocks.
Defined Under Namespace
Modules: ModuleConstMissing
Class Method Summary collapse
- ._unload(path, name, children) ⇒ Object private
- .disable_origen_load_extensions! ⇒ Object
- .enable_origen_load_extensions! ⇒ Object
- .load_attributes(file, model) ⇒ Object private
-
.load_block(model, options = {}) ⇒ Object
If a block definition exists for the given model, then this will load it and apply it to the model.
- .load_block_file(file, model) ⇒ Object private
- .record_const(name) ⇒ Object private
-
.unload ⇒ Object
private
Unload all constants (classes and modules) that have been auto-loaded since this was last called.
- .with_parameters_transaction(type) ⇒ Object private
Class Method Details
._unload(path, name, children) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/origen/loader.rb', line 25 def self._unload(path, name, children) path << name children.each do |name, children| _unload(path, name, children) end const = path.join('::') if @loaded_consts[const] path[0...-1].join('::').constantize.send :remove_const, path.last # puts "******** Unloading: #{const}" end path.pop end |
.disable_origen_load_extensions! ⇒ Object
403 404 405 |
# File 'lib/origen/loader.rb', line 403 def self.disable_origen_load_extensions! ModuleConstMissing.exclude_from(Module) end |
.enable_origen_load_extensions! ⇒ Object
399 400 401 |
# File 'lib/origen/loader.rb', line 399 def self.enable_origen_load_extensions! Module.class_eval { include ModuleConstMissing } end |
.load_attributes(file, model) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/origen/loader.rb', line 56 def self.load_attributes(file, model) if model.respond_to?(:is_an_origen_model?) attributes = model.attributes.dup else attributes = {} end vars = model.instance_variables if load_block_file(file, model) # Update the value of any pre-existing attribute that could have just changed attributes.each do |a, v| attributes[a] = model.instance_variable_get("@#{a}") end # And add any new ones that were encountered for the first time (model.instance_variables - vars).each do |var| val = model.instance_variable_get(var) attribute = var.to_s.sub('@', '') attributes[attribute.to_sym] = val unless model.respond_to?(attribute) model.define_singleton_method(attribute) do instance_variable_get(var) end end if val == true || val == false attribute += '?' unless model.respond_to?(attribute) model.define_singleton_method(attribute) do instance_variable_get(var) end end end end if model.respond_to?(:is_an_origen_model?) attributes.freeze model.instance_variable_set(:@attributes, attributes) end true end end |
.load_block(model, options = {}) ⇒ Object
If a block definition exists for the given model, then this will load it and apply it to the model. if options is passed, it will first try to load the files for the class name contained in that option, even if its from a plugin app. Additionally, any bugs/features will be inherited as well unless disable_bug_inheritance or disable_feature_inheritance options are passed Returns true if a model is found and loaded, otherwise nil.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/origen/loader.rb', line 123 def self.load_block(model, = {}) model = model.model # Ensure we have a handle on the model and not its controller loaded = nil if [:inherit] # pass down any bugs/features from the inherited block class unless [:disable_bug_inheritance] model.class.instance_variable_set(:@bugs, [:inherit].constantize.bugs.merge(model.class.bugs)) end unless [:disable_feature_inheritance] model.class.instance_variable_set(:@features, [:inherit].constantize.features.merge(model.class.features)) end end if local_app = [:app] || model.app if [:path] local_full_paths = Array([:path]) else local_full_paths = model.class.to_s.split('::') local_full_paths.shift # Throw away the app namespace local_full_paths = [local_full_paths.join('/')] end app_paths_map = { local_app => local_full_paths } if [:inherit] # update app_paths_map with the relevant inherited files inherit_full_paths = [:inherit].split('::') inherit_app = Origen.app(inherit_full_paths.shift.underscore.to_sym) inherit_full_paths = [inherit_full_paths.join('/')] # merge to get inherit ordered in the beginning app_paths_map = { inherit_app => inherit_full_paths }.merge(app_paths_map) end # load the inherit files, then the current app's block files app_paths_map.each do |app, full_paths| full_paths.each do |full_path| paths = full_path.to_s.split('/') key = '' only = Array([:only]) if [:only] except = Array([:except]) if [:except] path = paths.map(&:underscore).join('/') # If the path refers to a nested sub-block then don't load the full hierarchy since they # don't support inheritance or derivatives, modify the paths array so that only the sub-block # level will be loaded and nothing else. paths = [path] if app.blocks_files[path] && app.blocks_files[path][:_sub_block] # These will be loaded first, followed by the rest in an undefined order. # Attributes and parameters are first so that they may be referenced in the other files. # Sub-blocks was added early due to a corner case issue that could be encountered if the pins or # regs imported an Origen exported file that defined a module with the same name as a sub-block # class, in that case the sub-block class would not be auto-loaded. load_first = [:attributes, :parameters, :sub_blocks] load_first.each do |type| unless (only && !only.include?(type)) || (except && except.include?(type)) with_parameters_transaction(type) do paths.each_with_index do |path, i| key = i == 0 ? path.underscore : "#{key}/#{path.underscore}" if app.blocks_files[key] && app.blocks_files[key][type] app.blocks_files[key][type].each do |f| if type == :attributes success = load_attributes(f, model) else success = load_block_file(f, model) end loaded ||= success end end end end end end # Now load the rest paths.each_with_index do |path, i| key = i == 0 ? path.underscore : "#{key}/#{path.underscore}" if app.blocks_files[key] app.blocks_files[key].each do |type, files| unless type == :_sub_block || load_first.include?(type) || (only && !only.include?(type)) || (except && except.include?(type)) files.each { |f| success = load_block_file(f, model); loaded ||= success } end end end end end end end loaded end |
.load_block_file(file, model) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
96 97 98 99 100 101 102 103 104 |
# File 'lib/origen/loader.rb', line 96 def self.load_block_file(file, model) file = file.to_s if File.exist?(file) File.open(file, 'r') do |f| model.instance_eval(f.read, file) end end true end |
.record_const(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/origen/loader.rb', line 39 def self.record_const(name) @consts_hierarchy ||= {} @loaded_consts ||= {} @loaded_consts[name] = true pointer = nil name.split('::').each do |name| if pointer pointer[name] ||= {} pointer = pointer[name] else @consts_hierarchy[name] ||= {} pointer = @consts_hierarchy[name] end end end |
.unload ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Unload all constants (classes and modules) that have been auto-loaded since this was last called
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/origen/loader.rb', line 10 def self.unload # puts "******** LOADED CONSTS@ #{@loaded_consts}" path = [] (@consts_hierarchy || {}).each do |name, children| _unload(path, name, children) end @consts_hierarchy = {} @loaded_consts = {} (Origen.app.plugins + [Origen.app]).each do |app| app.instance_variable_set(:@blocks_files, nil) end nil end |
.with_parameters_transaction(type) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
107 108 109 110 111 112 113 114 115 |
# File 'lib/origen/loader.rb', line 107 def self.with_parameters_transaction(type) if type == :parameters Origen::Parameters.transaction do yield end else yield end end |