postsvg 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +49 -533
  3. data/Gemfile +1 -1
  4. data/lib/postsvg/cli.rb +5 -10
  5. data/lib/postsvg/color.rb +132 -0
  6. data/lib/postsvg/format_number.rb +22 -0
  7. data/lib/postsvg/graphics_context.rb +1 -2
  8. data/lib/postsvg/matrix.rb +106 -0
  9. data/lib/postsvg/model/literals/array.rb +41 -0
  10. data/lib/postsvg/model/literals/dictionary.rb +34 -0
  11. data/lib/postsvg/model/literals/hex.rb +37 -0
  12. data/lib/postsvg/model/literals/name.rb +40 -0
  13. data/lib/postsvg/model/literals/number.rb +36 -0
  14. data/lib/postsvg/model/literals/procedure.rb +41 -0
  15. data/lib/postsvg/model/literals/string.rb +30 -0
  16. data/lib/postsvg/model/literals.rb +19 -0
  17. data/lib/postsvg/model/operator.rb +58 -0
  18. data/lib/postsvg/model/operators/arithmetic.rb +264 -0
  19. data/lib/postsvg/model/operators/boolean.rb +182 -0
  20. data/lib/postsvg/model/operators/color.rb +74 -0
  21. data/lib/postsvg/model/operators/container.rb +186 -0
  22. data/lib/postsvg/model/operators/control_flow.rb +119 -0
  23. data/lib/postsvg/model/operators/device.rb +21 -0
  24. data/lib/postsvg/model/operators/dictionary.rb +118 -0
  25. data/lib/postsvg/model/operators/font.rb +121 -0
  26. data/lib/postsvg/model/operators/graphics_state.rb +84 -0
  27. data/lib/postsvg/model/operators/painting.rb +29 -0
  28. data/lib/postsvg/model/operators/path.rb +169 -0
  29. data/lib/postsvg/model/operators/stack.rb +72 -0
  30. data/lib/postsvg/model/operators/transformations.rb +103 -0
  31. data/lib/postsvg/model/operators.rb +89 -0
  32. data/lib/postsvg/model/program.rb +68 -0
  33. data/lib/postsvg/model/token.rb +43 -0
  34. data/lib/postsvg/model.rb +17 -0
  35. data/lib/postsvg/options.rb +1 -1
  36. data/lib/postsvg/parser/postscript_parser.rb +7 -7
  37. data/lib/postsvg/renderer.rb +3 -7
  38. data/lib/postsvg/serializer.rb +325 -0
  39. data/lib/postsvg/source/ast_builder.rb +308 -0
  40. data/lib/postsvg/source/lexer.rb +322 -0
  41. data/lib/postsvg/source/operand_stack.rb +55 -0
  42. data/lib/postsvg/source.rb +21 -0
  43. data/lib/postsvg/svg/clip_path_registry.rb +1 -3
  44. data/lib/postsvg/svg/element.rb +1 -3
  45. data/lib/postsvg/svg/elements/ellipse.rb +1 -2
  46. data/lib/postsvg/svg/elements/svg.rb +1 -2
  47. data/lib/postsvg/svg/paint.rb +1 -1
  48. data/lib/postsvg/svg/path_data/parser.rb +6 -10
  49. data/lib/postsvg/svg/stroke.rb +2 -4
  50. data/lib/postsvg/svg/transform_list.rb +1 -1
  51. data/lib/postsvg/svg_builder.rb +11 -15
  52. data/lib/postsvg/translation/arc_converter.rb +12 -22
  53. data/lib/postsvg/translation/bounding_box.rb +4 -7
  54. data/lib/postsvg/translation/handlers/circle_handler.rb +2 -2
  55. data/lib/postsvg/translation/handlers/ellipse_handler.rb +3 -8
  56. data/lib/postsvg/translation/handlers/group_handler.rb +1 -2
  57. data/lib/postsvg/translation/handlers/image_handler.rb +2 -3
  58. data/lib/postsvg/translation/handlers/line_handler.rb +2 -6
  59. data/lib/postsvg/translation/handlers/open_handler.rb +2 -3
  60. data/lib/postsvg/translation/handlers/path_handler.rb +41 -57
  61. data/lib/postsvg/translation/handlers/polygon_handler.rb +2 -4
  62. data/lib/postsvg/translation/handlers/polyline_handler.rb +2 -4
  63. data/lib/postsvg/translation/handlers/rect_handler.rb +5 -10
  64. data/lib/postsvg/translation/handlers/shared.rb +11 -11
  65. data/lib/postsvg/translation/handlers/svg_handler.rb +2 -3
  66. data/lib/postsvg/translation/handlers/text_handler.rb +7 -8
  67. data/lib/postsvg/translation/handlers.rb +1 -2
  68. data/lib/postsvg/translation/ps_renderer.rb +1 -2
  69. data/lib/postsvg/version.rb +1 -1
  70. data/lib/postsvg/visitors/ps_visitor/arithmetic.rb +6 -6
  71. data/lib/postsvg/visitors/ps_visitor/color.rb +5 -8
  72. data/lib/postsvg/visitors/ps_visitor/common.rb +2 -1
  73. data/lib/postsvg/visitors/ps_visitor/container.rb +13 -13
  74. data/lib/postsvg/visitors/ps_visitor/control_flow.rb +3 -3
  75. data/lib/postsvg/visitors/ps_visitor/dictionary.rb +4 -8
  76. data/lib/postsvg/visitors/ps_visitor/font.rb +4 -14
  77. data/lib/postsvg/visitors/ps_visitor/graphics_state.rb +4 -4
  78. data/lib/postsvg/visitors/ps_visitor/painting.rb +1 -1
  79. data/lib/postsvg/visitors/ps_visitor/path.rb +4 -9
  80. data/lib/postsvg.rb +37 -42
  81. metadata +36 -16
@@ -0,0 +1,264 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module Arithmetic
7
+ BINARY_DEFAULT = { consumes: 2, produces: 1 }.freeze
8
+ UNARY_DEFAULT = { consumes: 1, produces: 1 }.freeze
9
+
10
+ class Add < Operator
11
+ register_as "add", **BINARY_DEFAULT
12
+ def self.from_operands(stack)
13
+ b = stack.pop_number
14
+ a = stack.pop_number
15
+ new(operand_a: a, operand_b: b)
16
+ end
17
+ attr_reader :operand_a, :operand_b
18
+ def initialize(operand_a:, operand_b:)
19
+ @operand_a = operand_a
20
+ @operand_b = operand_b
21
+ freeze
22
+ end
23
+ end
24
+
25
+ class Sub < Operator
26
+ register_as "sub", **BINARY_DEFAULT
27
+ def self.from_operands(stack)
28
+ b = stack.pop_number
29
+ a = stack.pop_number
30
+ new(operand_a: a, operand_b: b)
31
+ end
32
+ attr_reader :operand_a, :operand_b
33
+ def initialize(operand_a:, operand_b:)
34
+ @operand_a = operand_a
35
+ @operand_b = operand_b
36
+ freeze
37
+ end
38
+ end
39
+
40
+ class Mul < Operator
41
+ register_as "mul", **BINARY_DEFAULT
42
+ def self.from_operands(stack)
43
+ b = stack.pop_number
44
+ a = stack.pop_number
45
+ new(operand_a: a, operand_b: b)
46
+ end
47
+ attr_reader :operand_a, :operand_b
48
+ def initialize(operand_a:, operand_b:)
49
+ @operand_a = operand_a
50
+ @operand_b = operand_b
51
+ freeze
52
+ end
53
+ end
54
+
55
+ class Div < Operator
56
+ register_as "div", **BINARY_DEFAULT
57
+ def self.from_operands(stack)
58
+ b = stack.pop_number
59
+ a = stack.pop_number
60
+ new(operand_a: a, operand_b: b)
61
+ end
62
+ attr_reader :operand_a, :operand_b
63
+ def initialize(operand_a:, operand_b:)
64
+ @operand_a = operand_a
65
+ @operand_b = operand_b
66
+ freeze
67
+ end
68
+ end
69
+
70
+ class Idiv < Operator
71
+ register_as "idiv", **BINARY_DEFAULT
72
+ def self.from_operands(stack)
73
+ b = stack.pop_number.to_i
74
+ a = stack.pop_number.to_i
75
+ new(operand_a: a, operand_b: b)
76
+ end
77
+ attr_reader :operand_a, :operand_b
78
+ def initialize(operand_a:, operand_b:)
79
+ @operand_a = operand_a
80
+ @operand_b = operand_b
81
+ freeze
82
+ end
83
+ end
84
+
85
+ class Mod < Operator
86
+ register_as "mod", **BINARY_DEFAULT
87
+ def self.from_operands(stack)
88
+ b = stack.pop_number.to_i
89
+ a = stack.pop_number.to_i
90
+ new(operand_a: a, operand_b: b)
91
+ end
92
+ attr_reader :operand_a, :operand_b
93
+ def initialize(operand_a:, operand_b:)
94
+ @operand_a = operand_a
95
+ @operand_b = operand_b
96
+ freeze
97
+ end
98
+ end
99
+
100
+ class Neg < Operator
101
+ register_as "neg", **UNARY_DEFAULT
102
+ attr_reader :operand
103
+ def initialize(operand:)
104
+ @operand = operand
105
+ freeze
106
+ end
107
+ def self.from_operands(stack)
108
+ new(operand: stack.pop_number)
109
+ end
110
+ end
111
+
112
+ class Abs < Operator
113
+ register_as "abs", **UNARY_DEFAULT
114
+ attr_reader :operand
115
+ def initialize(operand:)
116
+ @operand = operand
117
+ freeze
118
+ end
119
+ def self.from_operands(stack)
120
+ new(operand: stack.pop_number)
121
+ end
122
+ end
123
+
124
+ class Ceiling < Operator
125
+ register_as "ceiling", **UNARY_DEFAULT
126
+ attr_reader :operand
127
+ def initialize(operand:)
128
+ @operand = operand
129
+ freeze
130
+ end
131
+ def self.from_operands(stack)
132
+ new(operand: stack.pop_number)
133
+ end
134
+ end
135
+
136
+ class Floor < Operator
137
+ register_as "floor", **UNARY_DEFAULT
138
+ attr_reader :operand
139
+ def initialize(operand:)
140
+ @operand = operand
141
+ freeze
142
+ end
143
+ def self.from_operands(stack)
144
+ new(operand: stack.pop_number)
145
+ end
146
+ end
147
+
148
+ class Round < Operator
149
+ register_as "round", **UNARY_DEFAULT
150
+ attr_reader :operand
151
+ def initialize(operand:)
152
+ @operand = operand
153
+ freeze
154
+ end
155
+ def self.from_operands(stack)
156
+ new(operand: stack.pop_number)
157
+ end
158
+ end
159
+
160
+ class Truncate < Operator
161
+ register_as "truncate", **UNARY_DEFAULT
162
+ attr_reader :operand
163
+ def initialize(operand:)
164
+ @operand = operand
165
+ freeze
166
+ end
167
+ def self.from_operands(stack)
168
+ new(operand: stack.pop_number)
169
+ end
170
+ end
171
+
172
+ class Sqrt < Operator
173
+ register_as "sqrt", **UNARY_DEFAULT
174
+ attr_reader :operand
175
+ def initialize(operand:)
176
+ @operand = operand
177
+ freeze
178
+ end
179
+ def self.from_operands(stack)
180
+ new(operand: stack.pop_number)
181
+ end
182
+ end
183
+
184
+ class Atan < Operator
185
+ register_as "atan", **BINARY_DEFAULT
186
+ def self.from_operands(stack)
187
+ b = stack.pop_number
188
+ a = stack.pop_number
189
+ new(operand_a: a, operand_b: b)
190
+ end
191
+ attr_reader :operand_a, :operand_b
192
+ def initialize(operand_a:, operand_b:)
193
+ @operand_a = operand_a
194
+ @operand_b = operand_b
195
+ freeze
196
+ end
197
+ end
198
+
199
+ class Cos < Operator
200
+ register_as "cos", **UNARY_DEFAULT
201
+ attr_reader :operand
202
+ def initialize(operand:)
203
+ @operand = operand
204
+ freeze
205
+ end
206
+ def self.from_operands(stack)
207
+ new(operand: stack.pop_number)
208
+ end
209
+ end
210
+
211
+ class Sin < Operator
212
+ register_as "sin", **UNARY_DEFAULT
213
+ attr_reader :operand
214
+ def initialize(operand:)
215
+ @operand = operand
216
+ freeze
217
+ end
218
+ def self.from_operands(stack)
219
+ new(operand: stack.pop_number)
220
+ end
221
+ end
222
+
223
+ class Ln < Operator
224
+ register_as "ln", **UNARY_DEFAULT
225
+ attr_reader :operand
226
+ def initialize(operand:)
227
+ @operand = operand
228
+ freeze
229
+ end
230
+ def self.from_operands(stack)
231
+ new(operand: stack.pop_number)
232
+ end
233
+ end
234
+
235
+ class Log < Operator
236
+ register_as "log", **UNARY_DEFAULT
237
+ attr_reader :operand
238
+ def initialize(operand:)
239
+ @operand = operand
240
+ freeze
241
+ end
242
+ def self.from_operands(stack)
243
+ new(operand: stack.pop_number)
244
+ end
245
+ end
246
+
247
+ class Exp < Operator
248
+ register_as "exp", **BINARY_DEFAULT
249
+ def self.from_operands(stack)
250
+ b = stack.pop_number
251
+ a = stack.pop_number
252
+ new(operand_a: a, operand_b: b)
253
+ end
254
+ attr_reader :operand_a, :operand_b
255
+ def initialize(operand_a:, operand_b:)
256
+ @operand_a = operand_a
257
+ @operand_b = operand_b
258
+ freeze
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module Boolean
7
+ # PS boolean literals. They look like operator tokens but
8
+ # push constant Boolean values. Modeled as zero-arity
9
+ # operators so the parser/registry handle them naturally.
10
+ class True < Operator
11
+ register_as "true", consumes: 0, produces: 1
12
+ end
13
+
14
+ class False < Operator
15
+ register_as "false", consumes: 0, produces: 1
16
+ end
17
+
18
+ class Eq < Operator
19
+ register_as "eq"
20
+ def self.from_operands(stack)
21
+ b = stack.pop
22
+ a = stack.pop
23
+ new(operand_a: a, operand_b: b)
24
+ end
25
+ attr_reader :operand_a, :operand_b
26
+ def initialize(operand_a:, operand_b:)
27
+ @operand_a = operand_a
28
+ @operand_b = operand_b
29
+ freeze
30
+ end
31
+ end
32
+
33
+ class Ne < Operator
34
+ register_as "ne"
35
+ def self.from_operands(stack)
36
+ b = stack.pop
37
+ a = stack.pop
38
+ new(operand_a: a, operand_b: b)
39
+ end
40
+ attr_reader :operand_a, :operand_b
41
+ def initialize(operand_a:, operand_b:)
42
+ @operand_a = operand_a
43
+ @operand_b = operand_b
44
+ freeze
45
+ end
46
+ end
47
+
48
+ class Gt < Operator
49
+ register_as "gt"
50
+ def self.from_operands(stack)
51
+ b = stack.pop_number
52
+ a = stack.pop_number
53
+ new(operand_a: a, operand_b: b)
54
+ end
55
+ attr_reader :operand_a, :operand_b
56
+ def initialize(operand_a:, operand_b:)
57
+ @operand_a = operand_a
58
+ @operand_b = operand_b
59
+ freeze
60
+ end
61
+ end
62
+
63
+ class Ge < Operator
64
+ register_as "ge"
65
+ def self.from_operands(stack)
66
+ b = stack.pop_number
67
+ a = stack.pop_number
68
+ new(operand_a: a, operand_b: b)
69
+ end
70
+ attr_reader :operand_a, :operand_b
71
+ def initialize(operand_a:, operand_b:)
72
+ @operand_a = operand_a
73
+ @operand_b = operand_b
74
+ freeze
75
+ end
76
+ end
77
+
78
+ class Lt < Operator
79
+ register_as "lt"
80
+ def self.from_operands(stack)
81
+ b = stack.pop_number
82
+ a = stack.pop_number
83
+ new(operand_a: a, operand_b: b)
84
+ end
85
+ attr_reader :operand_a, :operand_b
86
+ def initialize(operand_a:, operand_b:)
87
+ @operand_a = operand_a
88
+ @operand_b = operand_b
89
+ freeze
90
+ end
91
+ end
92
+
93
+ class Le < Operator
94
+ register_as "le"
95
+ def self.from_operands(stack)
96
+ b = stack.pop_number
97
+ a = stack.pop_number
98
+ new(operand_a: a, operand_b: b)
99
+ end
100
+ attr_reader :operand_a, :operand_b
101
+ def initialize(operand_a:, operand_b:)
102
+ @operand_a = operand_a
103
+ @operand_b = operand_b
104
+ freeze
105
+ end
106
+ end
107
+
108
+ class And < Operator
109
+ register_as "and"
110
+ def self.from_operands(stack)
111
+ b = stack.pop
112
+ a = stack.pop
113
+ new(operand_a: a, operand_b: b)
114
+ end
115
+ attr_reader :operand_a, :operand_b
116
+ def initialize(operand_a:, operand_b:)
117
+ @operand_a = operand_a
118
+ @operand_b = operand_b
119
+ freeze
120
+ end
121
+ end
122
+
123
+ class Or < Operator
124
+ register_as "or"
125
+ def self.from_operands(stack)
126
+ b = stack.pop
127
+ a = stack.pop
128
+ new(operand_a: a, operand_b: b)
129
+ end
130
+ attr_reader :operand_a, :operand_b
131
+ def initialize(operand_a:, operand_b:)
132
+ @operand_a = operand_a
133
+ @operand_b = operand_b
134
+ freeze
135
+ end
136
+ end
137
+
138
+ class Xor < Operator
139
+ register_as "xor"
140
+ def self.from_operands(stack)
141
+ b = stack.pop
142
+ a = stack.pop
143
+ new(operand_a: a, operand_b: b)
144
+ end
145
+ attr_reader :operand_a, :operand_b
146
+ def initialize(operand_a:, operand_b:)
147
+ @operand_a = operand_a
148
+ @operand_b = operand_b
149
+ freeze
150
+ end
151
+ end
152
+
153
+ class Not < Operator
154
+ register_as "not"
155
+ attr_reader :operand
156
+ def initialize(operand:)
157
+ @operand = operand
158
+ freeze
159
+ end
160
+ def self.from_operands(stack)
161
+ new(operand: stack.pop)
162
+ end
163
+ end
164
+
165
+ class Bitshift < Operator
166
+ register_as "bitshift"
167
+ def self.from_operands(stack)
168
+ shift = stack.pop_number.to_i
169
+ value = stack.pop_number.to_i
170
+ new(operand: value, shift: shift)
171
+ end
172
+ attr_reader :operand, :shift
173
+ def initialize(operand:, shift:)
174
+ @operand = operand
175
+ @shift = shift
176
+ freeze
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module Color
7
+ class Setgray < Operator
8
+ register_as "setgray"
9
+ attr_reader :gray
10
+ def initialize(gray:)
11
+ @gray = gray
12
+ freeze
13
+ end
14
+ def self.from_operands(stack)
15
+ new(gray: stack.pop_number)
16
+ end
17
+ end
18
+
19
+ class Setrgbcolor < Operator
20
+ register_as "setrgbcolor"
21
+ attr_reader :red, :green, :blue
22
+ def initialize(red:, green:, blue:)
23
+ @red = red
24
+ @green = green
25
+ @blue = blue
26
+ freeze
27
+ end
28
+ def self.from_operands(stack)
29
+ blue = stack.pop_number
30
+ green = stack.pop_number
31
+ red = stack.pop_number
32
+ new(red: red, green: green, blue: blue)
33
+ end
34
+ end
35
+
36
+ class Setcmykcolor < Operator
37
+ register_as "setcmykcolor"
38
+ attr_reader :cyan, :magenta, :yellow, :key
39
+ def initialize(cyan:, magenta:, yellow:, key:)
40
+ @cyan = cyan
41
+ @magenta = magenta
42
+ @yellow = yellow
43
+ @key = key
44
+ freeze
45
+ end
46
+ def self.from_operands(stack)
47
+ key = stack.pop_number
48
+ yellow = stack.pop_number
49
+ magenta = stack.pop_number
50
+ cyan = stack.pop_number
51
+ new(cyan: cyan, magenta: magenta, yellow: yellow, key: key)
52
+ end
53
+ end
54
+
55
+ class Sethsbcolor < Operator
56
+ register_as "sethsbcolor"
57
+ attr_reader :hue, :saturation, :brightness
58
+ def initialize(hue:, saturation:, brightness:)
59
+ @hue = hue
60
+ @saturation = saturation
61
+ @brightness = brightness
62
+ freeze
63
+ end
64
+ def self.from_operands(stack)
65
+ brightness = stack.pop_number
66
+ saturation = stack.pop_number
67
+ hue = stack.pop_number
68
+ new(hue: hue, saturation: saturation, brightness: brightness)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module Container
7
+ class Length < Operator
8
+ register_as "length", consumes: 1, produces: 1
9
+ attr_reader :operand
10
+ def initialize(operand:)
11
+ @operand = operand
12
+ freeze
13
+ end
14
+ def self.from_operands(stack)
15
+ new(operand: stack.pop)
16
+ end
17
+ end
18
+
19
+ class Get < Operator
20
+ register_as "get", consumes: 2, produces: 1
21
+ attr_reader :operand, :key
22
+ def initialize(operand:, key:)
23
+ @operand = operand
24
+ @key = key
25
+ freeze
26
+ end
27
+ def self.from_operands(stack)
28
+ key = stack.pop
29
+ coll = stack.pop
30
+ new(operand: coll, key: key)
31
+ end
32
+ end
33
+
34
+ class Put < Operator
35
+ register_as "put", consumes: 3, produces: 0
36
+ attr_reader :operand, :key, :value
37
+ def initialize(operand:, key:, value:)
38
+ @operand = operand
39
+ @key = key
40
+ @value = value
41
+ freeze
42
+ end
43
+ def self.from_operands(stack)
44
+ value = stack.pop
45
+ key = stack.pop
46
+ coll = stack.pop
47
+ new(operand: coll, key: key, value: value)
48
+ end
49
+ end
50
+
51
+ class Getinterval < Operator
52
+ register_as "getinterval", consumes: 3, produces: 1
53
+ attr_reader :operand, :start, :count
54
+ def initialize(operand:, start:, count:)
55
+ @operand = operand
56
+ @start = start
57
+ @count = count
58
+ freeze
59
+ end
60
+ def self.from_operands(stack)
61
+ count = stack.pop_number.to_i
62
+ start = stack.pop_number.to_i
63
+ coll = stack.pop
64
+ new(operand: coll, start: start, count: count)
65
+ end
66
+ end
67
+
68
+ class Putinterval < Operator
69
+ register_as "putinterval", consumes: 3, produces: 0
70
+ attr_reader :operand, :start, :source
71
+ def initialize(operand:, start:, source:)
72
+ @operand = operand
73
+ @start = start
74
+ @source = source
75
+ freeze
76
+ end
77
+ def self.from_operands(stack)
78
+ source = stack.pop
79
+ start = stack.pop_number.to_i
80
+ coll = stack.pop
81
+ new(operand: coll, start: start, source: source)
82
+ end
83
+ end
84
+
85
+ class Forall < Operator
86
+ register_as "forall", consumes: 2, produces: 0
87
+ attr_reader :collection, :body
88
+ def initialize(collection:, body:)
89
+ @collection = collection
90
+ @body = body
91
+ freeze
92
+ end
93
+ def self.from_operands(stack)
94
+ body = stack.pop
95
+ coll = stack.pop
96
+ new(collection: coll, body: body)
97
+ end
98
+ end
99
+
100
+ class Astore < Operator
101
+ register_as "astore", consumes: 1, produces: 1
102
+ attr_reader :array, :length
103
+ def initialize(array:, length:)
104
+ @array = array
105
+ @length = length
106
+ freeze
107
+ end
108
+ def self.from_operands(stack)
109
+ arr = stack.pop
110
+ length = stack.pop_number.to_i
111
+ new(array: arr, length: length)
112
+ end
113
+ end
114
+
115
+ class Search < Operator
116
+ register_as "search", consumes: 2, produces: 1
117
+ attr_reader :target, :pattern
118
+ def initialize(target:, pattern:)
119
+ @target = target
120
+ @pattern = pattern
121
+ freeze
122
+ end
123
+ def self.from_operands(stack)
124
+ pattern = stack.pop
125
+ target = stack.pop
126
+ new(target: target, pattern: pattern)
127
+ end
128
+ end
129
+
130
+ class Anchorsearch < Operator
131
+ register_as "anchorsearch", consumes: 2, produces: 1
132
+ attr_reader :target, :pattern
133
+ def initialize(target:, pattern:)
134
+ @target = target
135
+ @pattern = pattern
136
+ freeze
137
+ end
138
+ def self.from_operands(stack)
139
+ pattern = stack.pop
140
+ target = stack.pop
141
+ new(target: target, pattern: pattern)
142
+ end
143
+ end
144
+
145
+ class Token < Operator
146
+ register_as "token", consumes: 1, produces: 1
147
+ attr_reader :target
148
+ def initialize(target:)
149
+ @target = target
150
+ freeze
151
+ end
152
+ def self.from_operands(stack)
153
+ new(target: stack.pop)
154
+ end
155
+ end
156
+
157
+ class String < Operator
158
+ register_as "string", consumes: 1, produces: 1
159
+ attr_reader :count
160
+ def initialize(count:)
161
+ @count = count
162
+ freeze
163
+ end
164
+ def self.from_operands(stack)
165
+ new(count: stack.pop_number.to_i)
166
+ end
167
+ end
168
+
169
+ class Cvs < Operator
170
+ register_as "cvs", consumes: 2, produces: 1
171
+ attr_reader :value, :target
172
+ def initialize(value:, target:)
173
+ @value = value
174
+ @target = target
175
+ freeze
176
+ end
177
+ def self.from_operands(stack)
178
+ target = stack.pop
179
+ value = stack.pop
180
+ new(value: value, target: target)
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end