oppen 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a496d964de133aa177270080b9444d8e9ef865ce1b355bef4a6c4a43462d48c
4
- data.tar.gz: d2955b0983ef133fd374c1c46fc3424d9cff05c4ec910a6ca5ad94ec3f2db78d
3
+ metadata.gz: 81c1832fc106f4f4622738ad55ea231c66bdb40a96523d9913b3426781aed296
4
+ data.tar.gz: 9c5797979a36d529317bf31cdc85a158309c26f5a0c298f8cd1e577a83f4386a
5
5
  SHA512:
6
- metadata.gz: d4319e6b5be2d8fa394cf8d6cd593c4e8ab0b5c1c0a313cc42e287a93b46e23a95d844b8bddd01e5547ac67faa4b04395d5edb5ae911380572a0df1b7acf0c95
7
- data.tar.gz: 680e57e6f38f4cda980b57d04e787b4b33becc7b45de4c73810b243e82169411d62cd0d34b56a67df3e96debcc6d8a2ad777046aedec342429792fc91f3b3346
6
+ metadata.gz: e6a37e27b916fc83323a4b4b387c3990265094ac0c326b5770328ce8d43977b421c8cc0b2092b3c8a877d619ee56578abee1c0f5b2af9390c12f696211eb6446
7
+ data.tar.gz: 2548a7c7cd71299b8779714537916cf603f72a57bf2d02cf0ebcad163bafe7d53299e833cae07ada8a8cc30ddf2ba4e7ef19df6556656c2c920a90478c734ce4
@@ -33,15 +33,15 @@ module Oppen
33
33
  # Delimiter between lines in output
34
34
  attr_reader :new_line
35
35
 
36
- # Page margin (Called length in the original paper).
37
- attr_reader :margin
36
+ # Maximum allowed width for printing (Called length in the original paper).
37
+ attr_reader :width
38
38
 
39
39
  # Current available space (Called index in the original paper).
40
40
  #
41
41
  # @return [Integer] Current available space (Called index in the original paper).
42
42
  attr_reader :space
43
43
 
44
- def initialize(margin, new_line, config, space, out)
44
+ def initialize(width, new_line, config, space, out)
45
45
  @buffer = out
46
46
  @config = config
47
47
  @genspace =
@@ -55,8 +55,8 @@ module Oppen
55
55
  end
56
56
  @items = []
57
57
  @new_line = new_line
58
- @margin = margin
59
- @space = margin
58
+ @width = width
59
+ @space = width
60
60
  end
61
61
 
62
62
  # Returns the output of the print stack
@@ -71,32 +71,32 @@ module Oppen
71
71
  # @note Called Print in the original paper.
72
72
  #
73
73
  # @param token [Token]
74
- # @param token_length [Integer]
74
+ # @param token_width [Integer]
75
75
  #
76
76
  # @return [Nil]
77
- def print(token, token_length)
77
+ def print(token, token_width)
78
78
  case token
79
79
  in Token::Begin
80
- handle_begin token, token_length
80
+ handle_begin token, token_width
81
81
  in Token::End
82
82
  handle_end
83
83
  in Token::Break
84
- handle_break token, token_length
84
+ handle_break token, token_width
85
85
  in Token::String
86
- handle_string token, token_length
86
+ handle_string token, token_width
87
87
  end
88
88
  end
89
89
 
90
90
  # Handle Begin Token.
91
91
  #
92
92
  # @param token [Token]
93
- # @param token_length [Integer]
93
+ # @param token_width [Integer]
94
94
  #
95
95
  # @return [Nil]
96
96
  #
97
97
  # @see Token::Begin
98
- def handle_begin(token, token_length)
99
- if token_length > space
98
+ def handle_begin(token, token_width)
99
+ if token_width > space
100
100
  type =
101
101
  if token.break_type == Token::BreakType::CONSISTENT
102
102
  Token::BreakType::CONSISTENT
@@ -129,16 +129,16 @@ module Oppen
129
129
  # Handle Break Token.
130
130
  #
131
131
  # @param token [Token]
132
- # @param token_length [Integer]
132
+ # @param token_width [Integer]
133
133
  #
134
134
  # @return [Nil]
135
135
  #
136
136
  # @see Token::Break
137
- def handle_break(token, token_length)
137
+ def handle_break(token, token_width)
138
138
  block = top
139
139
  case block.break_type
140
140
  in Token::BreakType::FITS
141
- @space -= token.length
141
+ @space -= token.width
142
142
  write token
143
143
  in Token::BreakType::CONSISTENT
144
144
  @space = block.offset - token.offset
@@ -146,23 +146,23 @@ module Oppen
146
146
  if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
147
147
  token.offset
148
148
  else
149
- margin - space
149
+ width - space
150
150
  end
151
151
  write token.line_continuation
152
152
  print_new_line indent
153
153
  in Token::BreakType::INCONSISTENT
154
- if token_length > space
154
+ if token_width > space
155
155
  @space = block.offset - token.offset
156
156
  indent =
157
157
  if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
158
158
  token.offset
159
159
  else
160
- margin - space
160
+ width - space
161
161
  end
162
162
  write token.line_continuation
163
163
  print_new_line indent
164
164
  else
165
- @space -= token.length
165
+ @space -= token.width
166
166
  write token
167
167
  end
168
168
  end
@@ -171,13 +171,13 @@ module Oppen
171
171
  # Handle String Token.
172
172
  #
173
173
  # @param token [Token]
174
- # @param token_length [Integer]
174
+ # @param token_width [Integer]
175
175
  #
176
176
  # @return [Nil]
177
177
  #
178
178
  # @see Token::String
179
- def handle_string(token, token_length)
180
- @space = [0, space - token_length].max
179
+ def handle_string(token, token_width)
180
+ @space = [0, space - token_width].max
181
181
  write token
182
182
  end
183
183
 
@@ -222,8 +222,8 @@ module Oppen
222
222
  def print_new_line(amount)
223
223
  write new_line
224
224
  if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
225
- @space = margin - top.offset - amount
226
- indent margin - space
225
+ @space = width - top.offset - amount
226
+ indent width - space
227
227
  else
228
228
  indent amount
229
229
  end
data/lib/oppen/printer.rb CHANGED
@@ -4,6 +4,7 @@ require 'stringio'
4
4
 
5
5
  require_relative 'scan_stack'
6
6
  require_relative 'print_stack'
7
+ require_relative 'utils'
7
8
 
8
9
  # Oppen.
9
10
  module Oppen
@@ -48,9 +49,18 @@ module Oppen
48
49
  # @note Called token in the original paper.
49
50
  attr_reader :tokens
50
51
 
51
- # @note Called PrettyPrintInit in the original paper.
52
+ # Some description
52
53
  #
53
- # @param margin [Integer] maximum line width desired.
54
+ # @example
55
+ # "This is a string" # => and this is a comment
56
+ # out = Oppen::Wadler.new (margin: 13) # Hawn
57
+ # # Baliz
58
+ #
59
+ # @example
60
+ # "This is a string" # => and this is a comment
61
+ # # var = 12
62
+ #
63
+ # @param width [Integer] maximum line width desired.
54
64
  # @param new_line [String] the delimiter between lines.
55
65
  # @param config [Config]
56
66
  # @param space [String, Proc] could be a String or a callable.
@@ -60,18 +70,18 @@ module Oppen
60
70
  # If it's a callable, it will receive `n` and it needs to return
61
71
  # a string.
62
72
  # @param out [Object] should have a write and string method
63
- def initialize(margin, new_line, config = Config.oppen,
73
+ def initialize(width, new_line, config = Config.oppen,
64
74
  space = ' ', out = StringIO.new)
65
75
  # Maximum size if the stacks
66
- n = 3 * margin
76
+ n = 3 * width
67
77
 
68
78
  @config = config
69
79
  @left = 0
70
80
  @left_total = 1
71
- @print_stack = PrintStack.new margin, new_line, config, space, out
81
+ @print_stack = PrintStack.new width, new_line, config, space, out
72
82
  @right = 0
73
83
  @right_total = 1
74
- @scan_stack = ScanStack.new n
84
+ @scan_stack = ScanStack.new n, config
75
85
  @size = Array.new n
76
86
  @tokens = Array.new n
77
87
  end
@@ -148,7 +158,7 @@ module Oppen
148
158
  tokens[right] = token
149
159
  size[right] = -1
150
160
  scan_stack.push right
151
- if config&.eager_print &&
161
+ if config&.eager_print? &&
152
162
  (!scan_stack.empty? && right_total - left_total < print_stack.space)
153
163
  check_stack 0
154
164
  advance_left tokens[left], size[left]
@@ -174,7 +184,7 @@ module Oppen
174
184
  scan_stack.push right
175
185
  tokens[right] = token
176
186
  size[right] = -right_total
177
- @right_total += token.length
187
+ @right_total += token.width
178
188
  end
179
189
 
180
190
  # Handle String Token.
@@ -184,12 +194,12 @@ module Oppen
184
194
  # @see Token::String
185
195
  def handle_string(token)
186
196
  if scan_stack.empty?
187
- print_stack.print token, token.length
197
+ print_stack.print token, token.width
188
198
  else
189
199
  advance_right
190
200
  tokens[right] = token
191
- size[right] = token.length
192
- @right_total += token.length
201
+ size[right] = token.width
202
+ @right_total += token.width
193
203
  check_stream
194
204
  end
195
205
  end
@@ -220,7 +230,10 @@ module Oppen
220
230
  @right = (right + 1) % scan_stack.length
221
231
  return if right != left
222
232
 
223
- raise 'Token queue full'
233
+ raise 'Token queue full' if !config.upsize_stack?
234
+
235
+ @size, = Utils.upsize_circular_array(@size, @left)
236
+ @tokens, @left, @right = Utils.upsize_circular_array(@tokens, @left)
224
237
  end
225
238
 
226
239
  # Advances the `left` pointer and lets the print stack
@@ -229,16 +242,16 @@ module Oppen
229
242
  # @note Called AdvanceLeft as well in the original paper.
230
243
  #
231
244
  # @return [Nil]
232
- def advance_left(token, token_length)
233
- return if token_length.negative?
245
+ def advance_left(token, token_width)
246
+ return if token_width.negative?
234
247
 
235
- print_stack.print token, token_length
248
+ print_stack.print token, token_width
236
249
 
237
250
  case token
238
251
  when Token::Break
239
- @left_total += token.length
252
+ @left_total += token.width
240
253
  when Token::String
241
- @left_total += token_length
254
+ @left_total += token_width
242
255
  end
243
256
 
244
257
  return if left == right
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'utils'
4
+
3
5
  # Oppen.
4
6
  module Oppen
5
7
  # A fixed-size stack that can be popped from top and bottom.
6
8
  class ScanStack
7
- def initialize(size)
9
+ def initialize(size, config)
8
10
  @bottom = 0
11
+ @config = config
9
12
  @empty = true
10
13
  @stack = Array.new(size)
11
14
  @top = 0
@@ -68,7 +71,9 @@ module Oppen
68
71
  else
69
72
  @top = increment(@top)
70
73
  if @top == @bottom
71
- raise 'Stack full'
74
+ raise 'Stack full' if !@config.upsize_stack?
75
+
76
+ @stack, @bottom, @top = Utils.upsize_circular_array(@stack, @bottom)
72
77
  end
73
78
  end
74
79
  @stack[@top] = value
data/lib/oppen/token.rb CHANGED
@@ -18,60 +18,50 @@ module Oppen
18
18
  CONSISTENT = 2
19
19
  end
20
20
 
21
- # Default token length
21
+ # Default token width
22
22
  # @return [Integer]
23
- def length
24
- 0
25
- end
23
+ def width = 0
26
24
 
27
25
  # String Token.
28
26
  class String < Token
29
27
  # @return [String] String value.
30
28
  attr_reader :value
29
+ # @return [Integer]
30
+ attr_reader :width
31
31
 
32
- def initialize(value)
32
+ def initialize(value, width: value.length)
33
33
  @value = value
34
+ @width = width
34
35
  super()
35
36
  end
36
37
 
37
- # @return [Integer]
38
- def length
39
- value.length
40
- end
41
-
42
38
  # @return [String]
43
- def to_s
44
- value
45
- end
39
+ def to_s = value
46
40
  end
47
41
 
48
42
  # Break Token.
49
43
  class Break < Token
50
- # @return [String] Break strings.
51
- attr_reader :str
52
44
  # @return [String] If a new line is needed display this string before the new line
53
45
  attr_reader :line_continuation
54
46
  # @return [Integer] Indentation.
55
47
  attr_reader :offset
48
+ # @return [String] Break strings.
49
+ attr_reader :str
50
+ # @return [Integer]
51
+ attr_reader :width
56
52
 
57
- def initialize(str = ' ', line_continuation: '', offset: 0)
53
+ def initialize(str = ' ', width: str.length, line_continuation: '', offset: 0)
58
54
  raise ArgumentError, 'line_continuation cannot be nil' if line_continuation.nil?
59
55
 
60
56
  @line_continuation = line_continuation
61
57
  @offset = offset
62
58
  @str = str
59
+ @width = width
63
60
  super()
64
61
  end
65
62
 
66
- # @return [Integer]
67
- def length
68
- str.length
69
- end
70
-
71
63
  # @return [String]
72
- def to_s
73
- str
74
- end
64
+ def to_s = str
75
65
  end
76
66
 
77
67
  # Distinguished instance of Break which forces a line break.
@@ -79,9 +69,7 @@ module Oppen
79
69
  # Mock string that represents an infinite string to force new line.
80
70
  class LineBreakString
81
71
  # @return [Integer]
82
- def length
83
- 999_999
84
- end
72
+ def length = 999_999
85
73
  end
86
74
 
87
75
  def initialize(line_continuation: '', offset: 0)
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Oppen.
4
+ module Oppen
5
+ # Utils.
6
+ module Utils
7
+ # Rotates circular array and triples its size.
8
+ # @param arr [Array]
9
+ # @param offset [Integer] Rotation amount
10
+ #
11
+ # @return [Array(Array, Integer, Integer)] upsized array, lhs, rhs
12
+ def self.upsize_circular_array(arr, offset)
13
+ size = arr.size
14
+ arr = arr.rotate(offset)
15
+ arr.fill(nil, size, 2 * size)
16
+ [arr, 0, size]
17
+ end
18
+ end
19
+ end
data/lib/oppen/version.rb CHANGED
@@ -5,5 +5,5 @@ module Oppen
5
5
  # Oppen version
6
6
  #
7
7
  # @return [String] current version
8
- VERSION = '0.9.0' # managed by release.sh
8
+ VERSION = '0.9.1' # managed by release.sh
9
9
  end
data/lib/oppen.rb CHANGED
@@ -18,15 +18,15 @@ module Oppen
18
18
  # to indent.
19
19
  # If it's a callable, it will receive `n` and it needs to return
20
20
  # a string.
21
- # @param margin [Integer] maximum line width desired
22
21
  # @param new_line [String] the delimiter between lines
23
22
  # @param out [Object] should have a write and string method
24
23
  # @param tokens [Array[Token]] the list of tokens to be printed
24
+ # @param width [Integer] maximum line width desired
25
25
  #
26
26
  # @return [String] output of the pretty printer
27
27
  def self.print(config: Config.oppen, space: ' ',
28
- margin: 80, new_line: "\n", out: StringIO.new, tokens: [])
29
- printer = Printer.new margin, new_line, config, space, out
28
+ new_line: "\n", out: StringIO.new, tokens: [], width: 80)
29
+ printer = Printer.new width, new_line, config, space, out
30
30
  tokens.each do |token|
31
31
  printer.print token
32
32
  end
@@ -47,10 +47,17 @@ module Oppen
47
47
  end
48
48
 
49
49
  attr_accessor :indent_anchor
50
+
51
+ def initialize(indent_anchor: IndentAnchor::ON_BREAK, eager_print: false, upsize_stack: false)
52
+ @indent_anchor = indent_anchor
53
+ @eager_print = eager_print
54
+ @upsize_stack = upsize_stack
55
+ end
56
+
50
57
  # Print groups eagerly
51
58
  #
52
59
  # @example
53
- # out = Oppen::Wadler.new (margin: 13)
60
+ # out = Oppen::Wadler.new (width: 13)
54
61
  # out.group {
55
62
  # out.group {
56
63
  # out.text 'abc'
@@ -76,12 +83,9 @@ module Oppen
76
83
  # # jkl
77
84
  #
78
85
  # @return [Boolean]
79
- attr_accessor :eager_print
86
+ def eager_print? = @eager_print
80
87
 
81
- def initialize(indent_anchor: IndentAnchor::ON_BREAK, eager_print: false)
82
- @indent_anchor = indent_anchor
83
- @eager_print = eager_print
84
- end
88
+ def upsize_stack? = @upsize_stack
85
89
 
86
90
  # Default config for Oppen usage
87
91
  # @return [Config]
@@ -91,25 +95,27 @@ module Oppen
91
95
 
92
96
  # Default config for Wadler usage
93
97
  # @return [Config]
94
- def self.wadler(eager_print: true)
95
- new(indent_anchor: IndentAnchor::ON_BEGIN, eager_print:)
98
+ def self.wadler(eager_print: true, upsize_stack: true)
99
+ new(indent_anchor: IndentAnchor::ON_BEGIN, eager_print:, upsize_stack:)
96
100
  end
97
101
  end
98
102
 
99
103
  # @param value [String]
104
+ # @param width [Integer] token width that defaults to value.length
100
105
  #
101
106
  # @return [Oppen::Token::String] a new String token
102
- def self.string(value)
103
- Token::String.new(value)
107
+ def self.string(value, width: value.length)
108
+ Token::String.new(value, width:)
104
109
  end
105
110
 
106
111
  # @param str [String]
107
112
  # @param line_continuation [String] If a new line is needed display this string before the new line
108
113
  # @param offset [Integer]
114
+ # @param width [Integer] token width that defaults to str.length
109
115
  #
110
116
  # @return [Oppen::Token::Break] a new Break token
111
- def self.break(str = ' ', line_continuation: '', offset: 0)
112
- Token::Break.new(str, line_continuation:, offset:)
117
+ def self.break(str = ' ', line_continuation: '', offset: 0, width: str.length)
118
+ Token::Break.new(str, width:, line_continuation:, offset:)
113
119
  end
114
120
 
115
121
  # @param line_continuation [String] If a new line is needed display this string before the new line
data/lib/wadler/print.rb CHANGED
@@ -7,10 +7,10 @@ module Oppen
7
7
  attr_reader :config
8
8
  attr_reader :current_indent
9
9
  attr_reader :space
10
- attr_reader :margin
11
10
  attr_reader :new_line
12
11
  attr_reader :out
13
12
  attr_reader :tokens
13
+ attr_reader :width
14
14
 
15
15
  # @param config [Oppen::Config]
16
16
  # @param space [String, Proc] could be a String or a callable.
@@ -19,15 +19,15 @@ module Oppen
19
19
  # to indent.
20
20
  # If it's a callable, it will receive `n` and it needs to return
21
21
  # a string.
22
- # @param margin [Integer]
23
22
  # @param new_line [String]
24
23
  # @param out [Object] should have a write and string method
24
+ # @param width [Integer]
25
25
  def initialize(config: Config.wadler, space: ' ',
26
- margin: 80, new_line: "\n", out: StringIO.new)
26
+ new_line: "\n", out: StringIO.new, width: 80)
27
27
  @config = config
28
28
  @current_indent = 0
29
29
  @space = space
30
- @margin = margin
30
+ @width = width
31
31
  @new_line = new_line
32
32
  @out = out
33
33
  @tokens = []
@@ -38,7 +38,7 @@ module Oppen
38
38
  if !tokens.last.is_a? Oppen::Token::EOF
39
39
  tokens << Oppen.eof
40
40
  end
41
- Oppen.print(tokens:, margin:, new_line:, config:, space:, out:)
41
+ Oppen.print(tokens:, new_line:, config:, space:, out:, width:)
42
42
  end
43
43
 
44
44
  # @param indent [Integer] group indentation
@@ -110,16 +110,16 @@ module Oppen
110
110
  # @param value [String]
111
111
  #
112
112
  # @return [Nil]
113
- def text(value)
114
- tokens << Oppen.string(value)
113
+ def text(value, width: value.length)
114
+ tokens << Oppen.string(value, width:)
115
115
  end
116
116
 
117
117
  # @param str [String]
118
118
  # @param line_continuation [String] If a new line is needed display this string before the new line
119
119
  #
120
120
  # @return [Nil]
121
- def breakable(str = ' ', line_continuation: '')
122
- tokens << Oppen.break(str, line_continuation:, offset: current_indent)
121
+ def breakable(str = ' ', width: str.length, line_continuation: '')
122
+ tokens << Oppen.break(str, width:, line_continuation:, offset: current_indent)
123
123
  end
124
124
 
125
125
  # @param line_continuation [String] If a new line is needed display this string before the new line
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oppen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amine Mike El Maalouf <amine.el-maalouf@epita.fr>
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-09-27 00:00:00.000000000 Z
12
+ date: 2024-10-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Implementation of the Oppen's pretty printing algorithm
15
15
  email:
@@ -24,6 +24,7 @@ files:
24
24
  - lib/oppen/printer.rb
25
25
  - lib/oppen/scan_stack.rb
26
26
  - lib/oppen/token.rb
27
+ - lib/oppen/utils.rb
27
28
  - lib/oppen/version.rb
28
29
  - lib/wadler/print.rb
29
30
  homepage: http://github.com/Faveod/oppen-ruby