Class: DSL::Maker
- Inherits:
-
Object
- Object
- DSL::Maker
- Defined in:
- lib/dsl/maker.rb,
lib/dsl/maker/version.rb
Overview
This is the base class we provide.
Defined Under Namespace
Modules: Boolean Classes: Alias, ArrayType, Base, HashType
Constant Summary collapse
- VERSION =
The current version of this library
'1.0.1'- Any =
Create the DSL::Maker::Any type identifier, equivalent to Object.
Object- Yes =
On = True = true
- No =
Off = False = false
- ArrayOf =
Class.new do def self.[](type) raise "Cannot make an array of an alias" if DSL::Maker.is_alias?(type) raise "Unknown type provided to ArrayOf" unless @@types.has_key?(type) || DSL::Maker.is_dsl?(type) @@arrays[type] ||= ArrayType.new(type) end end
- @@aliases =
{}
- @@arrays =
{}
Class Method Summary collapse
-
.add_entrypoint(name, args = {}, &defn_block) ⇒ Class
Add an entrypoint (top-level DSL element) to this class's DSL.
-
.add_helper(name, &block) ⇒ Object
This adds a helper function that's accessible within the DSL.
-
.add_type(type, &block) ⇒ Object
This adds a type coercion that's used when creating the DSL.
-
.add_verification(name, &block) ⇒ Object
This adds a verification that's executed after the DSL is finished parsing.
- .AliasOf(name) ⇒ Object
-
.entrypoint(name) ⇒ Class
This returns the DSL corresponding to the entrypoint's name.
-
.execute_dsl(&block) ⇒ Array
Execute the DSL provided in the block.
-
.generate_dsl(args = {}, &defn_block) ⇒ Class
Add the meat of a DSL block to some level of this class's DSL.
-
.has_helper?(name) ⇒ Boolean
This returns if the helper has been added with #add_helper.
- .is_alias?(type) ⇒ Boolean
- .is_array?(type) ⇒ Boolean
-
.parse_dsl(dsl = nil) ⇒ Array
Parse the DSL provided in the parameter.
-
.remove_helper(name) ⇒ Object
This removes a helper function that's been added with #add_helper.
Class Method Details
.add_entrypoint(name, args = {}, &defn_block) ⇒ Class
args could be a Hash (to be passed to generate_dsl()) or the result
Add an entrypoint (top-level DSL element) to this class's DSL.
This delegates to generate_dsl() for the majority of the work.
of a call to generate_dsl().
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/dsl/maker.rb', line 212 def self.add_entrypoint(name, args={}, &defn_block) symname = name.to_sym if is_entrypoint?(symname) raise "'#{name.to_s}' is already an entrypoint" end if is_dsl?(args) dsl_class = args else # Without defn_block, there's no way to give back the result of the # DSL parsing. So, raise an error if we don't get one. # TODO: Provide a default block that returns the datastructure as a HoH. raise "Block required for add_entrypoint" unless block_given? dsl_class = generate_dsl(args, &defn_block) end if @klass build_dsl_element(@klass, symname, dsl_class) else # FIXME: We shouldn't need the blank block here ... # This blank block is representative of the implicit (and missing) outermost # block around the DSL that we are not putting into place in :parse_dsl or # :execute_dsl. @klass = generate_dsl({ symname => dsl_class }) {} # This marks @klass as the root DSL class. @klass.parent_class = self end @entrypoints ||= {} return @entrypoints[symname] = dsl_class end |
.add_helper(name, &block) ⇒ Object
This adds a helper function that's accessible within the DSL.
Note: These helpers are global to all DSLs.
270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/dsl/maker.rb', line 270 def self.add_helper(name, &block) raise "Block required for add_helper" unless block_given? if has_helper? name raise "'#{name.to_s}' is already a helper" end base_class.class_eval do define_method(name.to_sym, &block) end return end |
.add_type(type, &block) ⇒ Object
These type coercions are global to all DSLs.
This adds a type coercion that's used when creating the DSL.
Your block will receive the following signature: |attr, *args| where 'attr' is the name of the attribute and *args are the arguments passed into your method within the DSL. You are responsible for acting as a mutator. You have __get() and __set() available for your use. These are aliases to instance_variable_get and instance_variable_set, respectively. Please read the coercions provided for you in this source file as examples.
153 154 155 156 157 158 159 160 |
# File 'lib/dsl/maker.rb', line 153 def self.add_type(type, &block) raise "Block required for add_type" unless block_given? raise "'#{type}' is already a type coercion" if @@types.has_key? type @@types[type] = block return end |
.add_verification(name, &block) ⇒ Object
These verifications are specific to the DSL you add them to.
Verifications are called in the order you specify them.
This adds a verification that's executed after the DSL is finished parsing.
The verification will be called with the value(s) returned by the entrypoint's execution. If the verification returns a true value (of any kind), then that will be raised as a runtime exception.
You can also call add_verification on the return values from generate_dsl() or add_entrypoint(). In those cases, omit the :name because you have already chosen the DSL layer you're adding the verification to.
326 327 328 329 330 331 |
# File 'lib/dsl/maker.rb', line 326 def self.add_verification(name, &block) raise "Block required for add_verification" unless block_given? raise "'#{name.to_s}' is not an entrypoint for a verification" unless is_entrypoint?(name) @entrypoints[name.to_sym].add_verification(&block) end |
.AliasOf(name) ⇒ Object
75 76 77 |
# File 'lib/dsl/maker.rb', line 75 def self.AliasOf(name) @@aliases[name] ||= Alias.new(name) end |
.entrypoint(name) ⇒ Class
This returns the DSL corresponding to the entrypoint's name.
254 255 256 257 258 259 260 |
# File 'lib/dsl/maker.rb', line 254 def self.entrypoint(name) unless is_entrypoint?(name) raise "'#{name.to_s}' is not an entrypoint" end return @entrypoints[name.to_sym] end |
.execute_dsl(&block) ⇒ Array
Execute the DSL provided in the block.
131 132 133 134 135 136 |
# File 'lib/dsl/maker.rb', line 131 def self.execute_dsl(&block) raise 'Must call add_entrypoint before execute_dsl' unless @klass raise 'Block required for execute_dsl' unless block_given? run_dsl { @klass.new.instance_eval(&block) } end |
.generate_dsl(args = {}, &defn_block) ⇒ Class
Add the meat of a DSL block to some level of this class's DSL.
In order for Docile to parse a DSL, each level must be represented by a different class. This method creates anonymous classes that each represents a different level in the DSL's structure.
The creation of each DSL element is delegated to build_dsl_element.
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 |
# File 'lib/dsl/maker.rb', line 174 def self.generate_dsl(args={}, &defn_block) raise 'Block required for generate_dsl' unless block_given? dsl_class = Class.new(base_class) do include DSL::Maker::Boolean class << self attr_accessor :parent_class, :verifications end define_method(:__apply) do |*args| instance_exec(*args, &defn_block) end end args.each do |name, type| if dsl_class.new.respond_to? name.to_sym raise "Illegal attribute name '#{name}'" end build_dsl_element(dsl_class, name, type) end return dsl_class end |
.has_helper?(name) ⇒ Boolean
This returns if the helper has been added with #add_helper
304 305 306 |
# File 'lib/dsl/maker.rb', line 304 def self.has_helper?(name) base_class.method_defined?(name.to_sym) end |
.is_alias?(type) ⇒ Boolean
78 79 80 |
# File 'lib/dsl/maker.rb', line 78 def self.is_alias?(type) type.instance_of? Alias end |
.is_array?(type) ⇒ Boolean
96 97 98 |
# File 'lib/dsl/maker.rb', line 96 def self.is_array?(type) type.instance_of? ArrayType end |
.parse_dsl(dsl = nil) ⇒ Array
Parse the DSL provided in the parameter.
119 120 121 122 123 124 |
# File 'lib/dsl/maker.rb', line 119 def self.parse_dsl(dsl=nil) raise 'Must call add_entrypoint before parse_dsl' unless @klass raise 'String required for parse_dsl' unless dsl.instance_of? String run_dsl { eval dsl, @klass.new.get_binding } end |
.remove_helper(name) ⇒ Object
This removes a helper function that's been added with #add_helper
289 290 291 292 293 294 295 296 297 |
# File 'lib/dsl/maker.rb', line 289 def self.remove_helper(name) unless has_helper? name raise "'#{name.to_s}' is not a helper" end base_class.class_eval do remove_method(name.to_sym) end end |