Class: Oozby::Preprocessor
- Inherits:
-
Object
- Object
- Oozby::Preprocessor
- Defined in:
- lib/oozby/preprocessor.rb,
lib/oozby/preprocessor-definitions.rb
Overview
The Oozby Method Preprocessor handles requests via the transform_call method and transforms the Oozby::Element passed in, patching in any extra features and trying to alert the user of obvious bugs
Constant Summary collapse
- NoResolution =
never pass resolution data in to these methods - it’s pointless:
%i(translate rotate scale mirror resize difference union intersection hull minkowski color)
- DefaultOpenSCADMethods =
list of OpenSCAD standard methods - these can pass through without error:
%i( cube sphere cylinder polyhedron circle square polygon scale resize rotate translate mirror multmatrix color minkowski hull linear_extrude rotate_extrude import import_dxf projection union difference intersection render echo )
- @@system_methods =
remember list of public methods defined so far - these are system ones
public_instance_methods(false)
Instance Attribute Summary collapse
-
#call ⇒ Object
Returns the value of attribute call.
-
#openscad_methods ⇒ Object
Returns the value of attribute openscad_methods.
Class Method Summary collapse
-
.default_filters(*list) ⇒ Object
sets a list of default filters which aren’t reset after each method def.
-
.filter(filter_name, *options) ⇒ Object
set a filter to be added only to the next method def.
-
.filters_for(method_name) ⇒ Object
get list of filters for a method name.
- .finalize_filter(method_name) ⇒ Object
-
.method_added(method_name) ⇒ Object
detect a method def, store it’s filters and reset for next def.
-
.oozby_alias(from, to, **extra_args) ⇒ Object
alias an name to an openscad method optionally with extra defaults useful for giving things more descriptive names, where those names imply different defaults, like hexagon -> circle(sides: 6).
-
.passthrough(method_name, *arg_names) ⇒ Object
don’t want to define a primary processor method? pass it through manually.
Instance Method Summary collapse
-
#args_parse(info, *arg_names) ⇒ Object
parse arguments like openscad does.
-
#capture(&proc) ⇒ Object
capture contents of a block as openscad code, returning AST array.
- #cube(size: [1,1,1], center: false, corner_radius: 0) ⇒ Object
- #cylinder(h: 1, r1: nil, r2: nil, r: nil, center: false, corner_radius: 0) ⇒ Object
-
#initialize(env: nil, ooz: nil) ⇒ Preprocessor
constructor
setup a new method preprocessor.
-
#known ⇒ Object
array of all known method names.
-
#known?(name) ⇒ Boolean
does this processor know of a method named whatever?.
-
#primary_method_args ⇒ Object
generates argument list to call a primary method processor.
-
#primary_processors ⇒ Object
list of primary processor methods.
-
#redirect(new_method) ⇒ Object
rewrite this method to a different method name and primary processor and whatever else.
- #run_filters(method_name) ⇒ Object
- #square(size: [1,1], center: false, corner_radius: 0) ⇒ Object
-
#transform_call(call_info) ⇒ Object
accepts an Oozby::Element and transforms it according to the processors’ rules.
Constructor Details
#initialize(env: nil, ooz: nil) ⇒ Preprocessor
setup a new method preprocessor
72 73 74 75 76 |
# File 'lib/oozby/preprocessor.rb', line 72 def initialize env: nil, ooz: nil @env = env @parent = ooz @openscad_methods = DefaultOpenSCADMethods.dup end |
Instance Attribute Details
#call ⇒ Object
Returns the value of attribute call.
70 71 72 |
# File 'lib/oozby/preprocessor.rb', line 70 def call @call end |
#openscad_methods ⇒ Object
Returns the value of attribute openscad_methods.
70 71 72 |
# File 'lib/oozby/preprocessor.rb', line 70 def openscad_methods @openscad_methods end |
Class Method Details
.default_filters(*list) ⇒ Object
sets a list of default filters which aren’t reset after each method def
11 12 13 14 |
# File 'lib/oozby/preprocessor.rb', line 11 def default_filters *list @@default_filters = list.map { |x| if x.is_a? Array then x else [x] end } @@queued_filters = @@default_filters.dup end |
.filter(filter_name, *options) ⇒ Object
set a filter to be added only to the next method def
17 18 19 20 21 |
# File 'lib/oozby/preprocessor.rb', line 17 def filter filter_name, * @@queued_filters ||= @@default_filters.dup @@queued_filters.delete_if { |x| x[0] == filter_name } # replace default definitions @@queued_filters.push([filter_name, *]) # add new filter definition end |
.filters_for(method_name) ⇒ Object
get list of filters for a method name
41 42 43 |
# File 'lib/oozby/preprocessor.rb', line 41 def filters_for method_name @@method_filters[method_name] || [] end |
.finalize_filter(method_name) ⇒ Object
29 30 31 32 |
# File 'lib/oozby/preprocessor.rb', line 29 def finalize_filter method_name @@method_filters[method_name] = @@queued_filters @@queued_filters = @@default_filters.dup end |
.method_added(method_name) ⇒ Object
detect a method def, store it’s filters and reset for next def
24 25 26 27 |
# File 'lib/oozby/preprocessor.rb', line 24 def method_added method_name finalize_filter method_name super end |
.oozby_alias(from, to, **extra_args) ⇒ Object
alias an name to an openscad method optionally with extra defaults useful for giving things more descriptive names, where those names imply different defaults, like hexagon -> circle(sides: 6)
48 49 50 51 52 53 54 |
# File 'lib/oozby/preprocessor.rb', line 48 def oozby_alias from, to, **extra_args define_method(from) do call.named_args.merge!(extra_args) #{ |key,l,r| l } # left op wins conflicts run_filters to redirect to end end |
.passthrough(method_name, *arg_names) ⇒ Object
don’t want to define a primary processor method? pass it through manually
35 36 37 38 |
# File 'lib/oozby/preprocessor.rb', line 35 def passthrough method_name, *arg_names arg_list = arg_names.map { |x| "#{x}: nil" }.join(', ') define_method method_name, &eval("->(#{arg_list}) {nil}") end |
Instance Method Details
#args_parse(info, *arg_names) ⇒ Object
parse arguments like openscad does
155 156 157 158 159 160 161 162 163 |
# File 'lib/oozby/preprocessor.rb', line 155 def args_parse(info, *arg_names) args = info.named_args.dup info.args.length.times do |index| warn "Overwriting argument #{arg_names[index]}" if args.key? arg_names[index] args[arg_names[index]] = info.args[index] end args end |
#capture(&proc) ⇒ Object
capture contents of a block as openscad code, returning AST array
166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/oozby/preprocessor.rb', line 166 def capture &proc env = @env (env._subscope { env.preprocessor(false) { env._execute_oozby(&proc) } }).find { |x| x.is_a? Oozby::Element }.tap { |x| x.modifier = "#{call.modifier}#{x.modifier}" if call.modifier } end |
#cube(size: [1,1,1], center: false, corner_radius: 0) ⇒ Object
25 26 27 28 |
# File 'lib/oozby/preprocessor-definitions.rb', line 25 def cube size: [1,1,1], center: false, corner_radius: 0 return rounded_rectangular_prism(size: size, center: center, corner_radius: corner_radius) if corner_radius > 0 return call end |
#cylinder(h: 1, r1: nil, r2: nil, r: nil, center: false, corner_radius: 0) ⇒ Object
34 35 36 37 38 |
# File 'lib/oozby/preprocessor-definitions.rb', line 34 def cylinder h: 1, r1: nil, r2: nil, r: nil, center: false, corner_radius: 0 r1, r2 = r, r if r unless r1 || r2 return rounded_cylinder(h: h, r1: r1, r2: r2, center: center, corner_radius: corner_radius) if corner_radius > 0 return call end |
#known ⇒ Object
array of all known method names
140 141 142 143 144 145 |
# File 'lib/oozby/preprocessor.rb', line 140 def known list = @openscad_methods.dup list.push *primary_processors list.push *@@method_filters.keys list.uniq end |
#known?(name) ⇒ Boolean
does this processor know of a method named whatever?
135 136 137 |
# File 'lib/oozby/preprocessor.rb', line 135 def known? name known.include? name.to_sym end |
#primary_method_args ⇒ Object
generates argument list to call a primary method processor
114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/oozby/preprocessor.rb', line 114 def primary_method_args # :nodoc: # grab the primary processor primary = self.class.public_instance_method(call.method.to_sym) params = primary.parameters # parse the processor method's signature param_names = params.select { |x| x.first == :key }.map { |x| x[1] } # filter down args to only those requested calling_args = call.named_args.dup # convert unnamed call args to named args calling_args.merge! args_parse(call, *param_names) # delete any args the receiver can't handle calling_args.delete_if { |k,v| not param_names.include?(k) } if calling_args.empty? then [] else [calling_args] end end |
#primary_processors ⇒ Object
list of primary processor methods
130 131 132 |
# File 'lib/oozby/preprocessor.rb', line 130 def primary_processors @primary_processors ||= public_methods(false) - @@system_methods end |
#redirect(new_method) ⇒ Object
rewrite this method to a different method name and primary processor and whatever else
148 149 150 151 |
# File 'lib/oozby/preprocessor.rb', line 148 def redirect new_method call.method = new_method.to_sym public_send(new_method, *primary_method_args) if self.respond_to? new_method end |
#run_filters(method_name) ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/oozby/preprocessor.rb', line 104 def run_filters method_name # apply the other filters filters = self.class.filters_for(method_name) filters.each do |filter_data| filter_name, *filter_args = filter_data send(filter_name, *filter_args) end end |
#square(size: [1,1], center: false, corner_radius: 0) ⇒ Object
48 49 50 51 |
# File 'lib/oozby/preprocessor-definitions.rb', line 48 def square size: [1,1], center: false, corner_radius: 0 return rounded_rectangle(size: size, center: center, corner_radius: corner_radius) if corner_radius > 0 return call end |
#transform_call(call_info) ⇒ Object
accepts an Oozby::Element and transforms it according to the processors’ rules
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/oozby/preprocessor.rb', line 79 def transform_call call_info raise "call info isn't Oozby::Element #{call_info.inspect}" unless call_info.is_a? Oozby::Element @call = call_info @original_method = @call.method run_filters call_info.method.to_sym methods = primary_processors # if a primary processor is defined for this kind of call if methods.include? call_info.method.to_sym # call the primary processor result = public_send(call_info.method, *primary_method_args) # replace the ast content with the processor's output if result.is_a? Hash or result.is_a? Oozby::Element # replace called item with this new stuff return result elsif result != nil # ignore nil - we don't need to do anything for that! raise "#{@original_method} preprocessor returned invalid result #{result.inspect}" end end return call_info end |