Class: Postsvg::Visitors::PsVisitor
- Inherits:
-
Object
- Object
- Postsvg::Visitors::PsVisitor
- Includes:
- Arithmetic, Boolean, Color, Common, Container, ControlFlow, Device, Dictionary, Font, GraphicsState, Painting, Path, Stack, Transformations
- Defined in:
- lib/postsvg/visitors/ps_visitor.rb,
lib/postsvg/visitors/ps_visitor/font.rb,
lib/postsvg/visitors/ps_visitor/path.rb,
lib/postsvg/visitors/ps_visitor/color.rb,
lib/postsvg/visitors/ps_visitor/stack.rb,
lib/postsvg/visitors/ps_visitor/common.rb,
lib/postsvg/visitors/ps_visitor/device.rb,
lib/postsvg/visitors/ps_visitor/boolean.rb,
lib/postsvg/visitors/ps_visitor/painting.rb,
lib/postsvg/visitors/ps_visitor/container.rb,
lib/postsvg/visitors/ps_visitor/arithmetic.rb,
lib/postsvg/visitors/ps_visitor/dictionary.rb,
lib/postsvg/visitors/ps_visitor/control_flow.rb,
lib/postsvg/visitors/ps_visitor/graphics_state.rb,
lib/postsvg/visitors/ps_visitor/transformations.rb
Overview
Walks a Model::Program and emits SVG via a SvgBuilder. Holds a GraphicsStack (immutable snapshots), an operand stack (for PostScript execution semantics that aren't expressed directly in the operator node — e.g. user-defined procedures that call arithmetic), and a current-path accumulator.
Dispatch is per-category: a separate module mixed in for each Model::Operators::* namespace. New operator categories = new module + include line, not a switch edit.
Defined Under Namespace
Modules: Arithmetic, Boolean, Color, Common, Container, ControlFlow, Device, Dictionary, Font, GraphicsState, Painting, Path, Stack, Transformations Classes: PathState
Constant Summary collapse
- MAX_RECURSION =
256
Constants included from ControlFlow
Instance Attribute Summary collapse
-
#builder ⇒ Object
readonly
Returns the value of attribute builder.
-
#graphics ⇒ Object
readonly
Returns the value of attribute graphics.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#stack ⇒ Object
readonly
Returns the value of attribute stack.
Instance Method Summary collapse
-
#dispatch(method_name, operator, ctx) ⇒ Object
Public entry: dispatch an operator node.
-
#initialize(builder:, graphics: GraphicsStack.new) ⇒ PsVisitor
constructor
A new instance of PsVisitor.
-
#pop_number ⇒ Object
Helper for popping numbers off the operand stack.
- #pop_value ⇒ Object
- #visit_array(node, _ctx) ⇒ Object
- #visit_dictionary(node, _ctx) ⇒ Object
- #visit_hex(node, _ctx) ⇒ Object
-
#visit_invoke_procedure(invocation, _ctx) ⇒ Object
InvokeProcedure: descend into the body with the current state.
- #visit_name(node, _ctx) ⇒ Object
-
#visit_number(node, _ctx) ⇒ Object
Literal visits push themselves onto the operand stack.
- #visit_procedure(node, _ctx) ⇒ Object
-
#visit_program(program) ⇒ Object
Visit a Program body.
- #visit_string_literal(node, _ctx) ⇒ Object
-
#visit_unknown(operator, _ctx) ⇒ Object
Default: unhandled operator becomes a comment.
Methods included from Common
#lookup_dict, #normalize_key, #numeric_value, #string_value, #truthy?
Methods included from Container
#visit_anchorsearch, #visit_astore, #visit_cvs, #visit_forall, #visit_get, #visit_getinterval, #visit_length, #visit_put, #visit_putinterval, #visit_search, #visit_string, #visit_token
Methods included from Font
#visit_charpath, #visit_findfont, #visit_scalefont, #visit_setfont, #visit_show, #visit_stringwidth, #visit_xyshow
Methods included from Device
#visit_copypage, #visit_nulldevice, #visit_showpage
Methods included from ControlFlow
#descend_into_procedure, #visit_exec, #visit_exit, #visit_for, #visit_if, #visit_ifelse, #visit_loop, #visit_quit, #visit_repeat, #visit_stopped
Methods included from Dictionary
#dict_stack, #visit_begin, #visit_countdictstack, #visit_currentdict, #visit_def, #visit_dict, #visit_dictstack, #visit_end, #visit_known, #visit_load, #visit_maxlength, #visit_store
Methods included from Transformations
#visit_concat, #visit_currentmatrix, #visit_dtransform, #visit_idtransform, #visit_itransform, #visit_matrix, #visit_rotate, #visit_scale, #visit_setmatrix, #visit_transform, #visit_translate
Methods included from GraphicsState
#visit_grestore, #visit_grestoreall, #visit_gsave, #visit_setdash, #visit_setlinecap, #visit_setlinejoin, #visit_setlinewidth, #visit_setmiterlimit
Methods included from Color
#visit_setcmykcolor, #visit_setgray, #visit_sethsbcolor, #visit_setrgbcolor
Methods included from Painting
#visit_clip, #visit_eoclip, #visit_eofill, #visit_fill, #visit_stroke
Methods included from Path
#visit_arc, #visit_arcn, #visit_closepath, #visit_currentpoint, #visit_curveto, #visit_lineto, #visit_moveto, #visit_newpath, #visit_rcurveto, #visit_rlineto, #visit_rmoveto
Methods included from Boolean
#visit_and, #visit_bitshift, #visit_eq, #visit_false, #visit_ge, #visit_gt, #visit_le, #visit_lt, #visit_ne, #visit_not, #visit_or, #visit_true, #visit_xor
Methods included from Arithmetic
#visit_abs, #visit_add, #visit_atan, #visit_ceiling, #visit_cos, #visit_div, #visit_exp, #visit_floor, #visit_idiv, #visit_ln, #visit_log, #visit_mod, #visit_mul, #visit_neg, #visit_round, #visit_sin, #visit_sqrt, #visit_sub, #visit_truncate
Methods included from Stack
#visit_clear, #visit_count, #visit_dup, #visit_exch, #visit_index, #visit_pop, #visit_roll
Constructor Details
#initialize(builder:, graphics: GraphicsStack.new) ⇒ PsVisitor
Returns a new instance of PsVisitor.
34 35 36 37 38 39 40 41 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 34 def initialize(builder:, graphics: GraphicsStack.new) @builder = builder @graphics = graphics @stack = [] # operand stack for execution semantics @path = PathState.new @dict_stack = [{}] # runtime dict stack (mirrors PLRM dict stack) @recursion_depth = 0 end |
Instance Attribute Details
#builder ⇒ Object (readonly)
Returns the value of attribute builder.
32 33 34 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 32 def builder @builder end |
#graphics ⇒ Object (readonly)
Returns the value of attribute graphics.
32 33 34 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 32 def graphics @graphics end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
32 33 34 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 32 def path @path end |
#stack ⇒ Object (readonly)
Returns the value of attribute stack.
32 33 34 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 32 def stack @stack end |
Instance Method Details
#dispatch(method_name, operator, ctx) ⇒ Object
Public entry: dispatch an operator node. Called from Model::Operator#accept.
45 46 47 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 45 def dispatch(method_name, operator, ctx) public_send(method_name, operator, ctx) end |
#pop_number ⇒ Object
Helper for popping numbers off the operand stack.
104 105 106 107 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 104 def pop_number v = @stack.pop numeric_value(v) end |
#pop_value ⇒ Object
109 110 111 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 109 def pop_value @stack.pop || Model::Computed.new(operator_keyword: "(missing)") end |
#visit_array(node, _ctx) ⇒ Object
73 74 75 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 73 def visit_array(node, _ctx) @stack << node.elements end |
#visit_dictionary(node, _ctx) ⇒ Object
81 82 83 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 81 def visit_dictionary(node, _ctx) @stack << node end |
#visit_hex(node, _ctx) ⇒ Object
69 70 71 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 69 def visit_hex(node, _ctx) @stack << node end |
#visit_invoke_procedure(invocation, _ctx) ⇒ Object
InvokeProcedure: descend into the body with the current state.
91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 91 def visit_invoke_procedure(invocation, _ctx) @recursion_depth += 1 if @recursion_depth > MAX_RECURSION raise RecursionLimitError, "procedure #{invocation.name} exceeded recursion limit #{MAX_RECURSION}" end invocation.procedure.body.each { |node| node.accept(self, nil) } ensure @recursion_depth -= 1 end |
#visit_name(node, _ctx) ⇒ Object
61 62 63 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 61 def visit_name(node, _ctx) @stack << node end |
#visit_number(node, _ctx) ⇒ Object
Literal visits push themselves onto the operand stack.
57 58 59 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 57 def visit_number(node, _ctx) @stack << node.value end |
#visit_procedure(node, _ctx) ⇒ Object
77 78 79 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 77 def visit_procedure(node, _ctx) @stack << node end |
#visit_program(program) ⇒ Object
Visit a Program body.
50 51 52 53 54 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 50 def visit_program(program) program.body.each do |statement| statement.accept(self, nil) end end |
#visit_string_literal(node, _ctx) ⇒ Object
65 66 67 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 65 def visit_string_literal(node, _ctx) @stack << node.value end |
#visit_unknown(operator, _ctx) ⇒ Object
Default: unhandled operator becomes a comment.
86 87 88 |
# File 'lib/postsvg/visitors/ps_visitor.rb', line 86 def visit_unknown(operator, _ctx) @builder.comment("unhandled operator: #{operator.keyword}") end |