rasel 1.1.3 → 1.1.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e383f8b5e25f0d283eeeb1eebf5bbe1572206494
4
- data.tar.gz: 4b53daac9f618a7be7188ba657703d88d62fbf1e
3
+ metadata.gz: 8b3b17070c0c2dd2bf982193c8becb0d2f079971
4
+ data.tar.gz: 053577514bcbe505c5c6bd1766ec0ddf52ae9974
5
5
  SHA512:
6
- metadata.gz: 5740ece90b2d4f2aafad4031a7f26dfc1d1d68338aaf9bfd8189bed6925e3421dbb47e10ce8aa2cd3e756117f04e0708afaec7e7dd3472fa3b4278e67eb98925
7
- data.tar.gz: 8ee6156d49f97c57682d97bab8762f70c69539259cdaf413289949d3b548afbfaad123b43b3a2bef7d6ffccb8fa4c2d2cf3b1533be28296b36e323d71808a88e
6
+ metadata.gz: bfe946adc630d7fe4c91c9d10f4407c3903dba8255d1c5531681ab387f8117bab5f084a59d9b010873d6e24d1936fe91030488963b43b3520d00367b289cd3f2
7
+ data.tar.gz: 5c86eb71eecd98797bfefd987400d25c7f91bce3270b3f3ee5588c42f4c80813d5b605e84cf8aa7af5cb5c72abb35792ab2cc278dfdad5a109209a0a1f297eae
data/bin/rasel-annotated CHANGED
@@ -3,4 +3,4 @@ Signal.trap(:INT){ abort "\n(interrupted by SIGINT)" }
3
3
 
4
4
  require_relative "../lib/rasel"
5
5
  require "json"
6
- exit RASEL(JSON.load(ARGF.read), STDOUT).exitcode
6
+ exit RASEL::run_annotated(JSON.load(ARGF.read), STDOUT).exitcode
data/bin/rasel-ide CHANGED
@@ -266,7 +266,7 @@ post "/run" do
266
266
  begin
267
267
  require "timeout"
268
268
  result = Timeout.timeout(2) do
269
- RASEL \
269
+ RASEL::run_annotated \
270
270
  JSON.load(File.read ARGV.first),
271
271
  StringIO.new,
272
272
  StringIO.new.tap{ |_| JSON.load(params.fetch "stdin").bytes.reverse_each &_.method(:ungetbyte) }
data/lib/rasel.rb CHANGED
@@ -2,6 +2,103 @@ Encoding::default_internal = Encoding::default_external = "ASCII-8BIT"
2
2
  END { RubyProf::FlatPrinter.new(RubyProf.stop).print STDERR, min_percent: 1 } if ENV["PROFILE"]
3
3
 
4
4
  module RASEL
5
+ ResultStruct = Struct.new :stdout, :stack, :exitcode
6
+
7
+ def self.run source, stdout = StringIO.new, stdin = STDIN
8
+ stack = []
9
+ pop = ->{ stack.pop || 0 }
10
+ error = Proc.new{ return RASEL::ResultStruct.new stdout, stack, 255 }
11
+
12
+ lines = source.tap{ |_| raise ArgumentError.new "empty source" if _.empty? }.gsub(/ +$/,"").split(?\n)
13
+ code = lines.map{ |_| _.ljust(lines.map(&:size).max).bytes }
14
+
15
+ dx, dy = 1, 0
16
+ x, y = -1, 0
17
+
18
+ # debugging and profiling (currently not maintained)
19
+ history = {}
20
+ debug_history = ENV.key? "DEBUG_HISTORY"
21
+ move = lambda do
22
+ y = (y + dy) % code.size
23
+ x = (x + dx) % code[y].size
24
+ next unless debug_history && (code[y][x] == 32 || code[y][x][0] == 32)
25
+ history[[x, y]] ||= 0
26
+ history[[x, y]] += 1
27
+ end
28
+ time = Time.now
29
+ thread = Thread.new do
30
+ loop do
31
+ unless Time.now < time + 1
32
+ time += 1
33
+ p history.sort_by(&:last).last(10)
34
+ end
35
+ sleep 0.1
36
+ end
37
+ end if debug_history
38
+ if ENV["PROFILE"]
39
+ require "ruby-prof"
40
+ RubyProf.start
41
+ end
42
+
43
+ reverse = ->{ dy, dx = -dy, -dx }
44
+ stringmode = false
45
+ debug = ENV.key? "DEBUG"
46
+ loop do
47
+ move[]
48
+ byte = code[y][x]
49
+ char = byte.chr
50
+ STDERR.puts [char, stringmode, (stack.last Integer ENV["DEBUG"] rescue stack)].inspect if debug
51
+
52
+ next stack.push byte if stringmode && char != ?"
53
+ return RASEL::ResultStruct.new stdout, stack, (
54
+ t = pop[]
55
+ 1 != t.denominator || t < 0 || t > 255 ? 255 : t.to_i
56
+ ) if char == ?@
57
+ case char
58
+ when ?\s
59
+
60
+ when ?0..?9 ; stack.push byte - 48
61
+ when ?A..?Z ; stack.push byte - 55
62
+ when ?" ; stringmode ^= true
63
+ when ?# ; move[]
64
+ when ?$ ; pop[]
65
+ when ?: ; stack.concat [pop[]] * 2
66
+ when ?- ; stack.push -(pop[] - pop[])
67
+ when ?/ ; b, a = pop[], pop[]; stack.push b.zero? ? 0 : Rational(a) / b
68
+ when ?% ; b, a = pop[], pop[]; stack.push b.zero? ? 0 : Rational(a) % b
69
+ when ?v ; dx, dy = 0, 1
70
+ when ?> ; dx, dy = 1, 0
71
+ when ?^ ; dx, dy = 0, -1
72
+ when ?< ; dx, dy = -1, 0
73
+ when ?? ; move[] if pop[] > 0
74
+ when ?\\
75
+ t = pop[]
76
+ error.call if 1 != t.denominator
77
+ stack.unshift 0 until stack.size > t
78
+ stack[-t-1], stack[-1] = stack[-1], stack[-t-1] unless 0 > t
79
+ when ?. ; stdout.print "#{_ = pop[]; 1 != _.denominator ? _.to_f : _.to_i} "
80
+ when ?, ; stdout.print "#{_ = pop[]; 1 != _.denominator ? error.call : _ < 0 || _ > 255 ? error.call : _.to_i.chr}"
81
+ when ?~ ; if _ = stdin.getbyte then stack.push _; move[] end
82
+ when ?&
83
+ getc = ->{ stdin.getc or throw nil }
84
+ catch nil do
85
+ nil until (?0..?9).include? c = getc[]
86
+ while (?0..?9).include? cc = stdin.getc ; c << cc end
87
+ stdin.ungetbyte cc if cc
88
+ stack.push c.to_i
89
+ move[]
90
+ end
91
+ when ?j
92
+ t = pop[]
93
+ error.call if 1 != t.denominator
94
+ y = (y + dy * t.to_i) % code.size
95
+ x = (x + dx * t.to_i) % code[y].size
96
+
97
+ else ; error.call
98
+ end
99
+ end
100
+ end
101
+
5
102
  require "delegate"
6
103
  class StackItem < DelegateClass Rational
7
104
  attr_reader :annotation
@@ -10,29 +107,13 @@ module RASEL
10
107
  @annotation = annotation || (n.annotation if n.respond_to? :annotation)
11
108
  end
12
109
  end
110
+ def self.run_annotated source, stdout = StringIO.new, stdin = STDIN
111
+ stack = []
112
+ pop = ->{ stack.pop || 0 }
113
+ error = Proc.new{ return ResultStruct.new stdout, stack, 255 }
13
114
 
14
- ResultStruct = Struct.new :stdout, :stack, :exitcode
15
-
16
- def self.write_pretty_json where, what
17
- File.write where, "[\n " + (
18
- what.map(&JSON.method(:dump)).join ",\n "
19
- ) + "\n]\n"
20
- end
21
- end
22
-
23
- def RASEL source, stdout = StringIO.new, stdin = STDIN
24
- stack = []
25
- pop = ->{ stack.pop || 0 }
26
- error = Proc.new{ return RASEL::ResultStruct.new stdout, stack, 255 }
27
-
28
- case source
29
- when String
30
- lines = source.tap{ |_| raise ArgumentError.new "empty source" if _.empty? }.gsub(/ +$/,"").split(?\n)
31
- code = lines.map{ |_| _.ljust(lines.map(&:size).max).bytes }
32
- when Array
33
- annotate = true
34
115
  code = Array.new(source.map{|y,|y}.max+1){ Array.new(source.map{|_,x,|x}.max+1){ " ".ord } }
35
- source.each{ |y, x, c, a| code[y][x] = [c.ord, a] }
116
+ source.each{ |y, x, c, a| code[y][x] = [c.ord, a] unless c.empty? }
36
117
  stdout.instance_eval do
37
118
  pos = self.pos
38
119
  old_puts = method :puts
@@ -40,7 +121,7 @@ def RASEL source, stdout = StringIO.new, stdin = STDIN
40
121
  define_singleton_method :puts do |str, reason|
41
122
  next if prev == dump = JSON.dump([reason, str])
42
123
  old_puts.call prev = dump
43
- if 200_000 < stdout.pos - pos
124
+ if 500_000 < stdout.pos - pos
44
125
  old_puts.call JSON.dump [:abort, "printed size"]
45
126
  error.call
46
127
  end
@@ -49,99 +130,87 @@ def RASEL source, stdout = StringIO.new, stdin = STDIN
49
130
  puts str, :print
50
131
  end
51
132
  end
52
- else
53
- raise ArgumentError.new "unsupported source class: #{source.class}"
54
- end
55
- dx, dy = 1, 0
56
- x, y = -1, 0
57
-
58
- # debugging and profiling (currently not maintained)
59
- history = {}
60
- debug_history = ENV.key? "DEBUG_HISTORY"
61
- move = lambda do
62
- y = (y + dy) % code.size
63
- x = (x + dx) % code[y].size
64
- next unless debug_history && (code[y][x] == 32 || code[y][x][0] == 32)
65
- history[[x, y]] ||= 0
66
- history[[x, y]] += 1
67
- end
68
- time = Time.now
69
- thread = Thread.new do
133
+
134
+ dx, dy = 1, 0
135
+ x, y = -1, 0
136
+
137
+ move = lambda do
138
+ y = (y + dy) % code.size
139
+ x = (x + dx) % code[y].size
140
+ end
141
+ time = Time.now
142
+
143
+ reverse = ->{ dy, dx = -dy, -dx }
144
+ stringmode = false
70
145
  loop do
71
- unless Time.now < time + 1
72
- time += 1
73
- p history.sort_by(&:last).last(10)
146
+ if 1 < Time.now - time
147
+ stdout.puts "timeout", :abort
148
+ error.call
74
149
  end
75
- sleep 0.1
76
- end
77
- end if debug_history
78
- if ENV["PROFILE"]
79
- require "ruby-prof"
80
- RubyProf.start
81
- end
150
+ stdout.puts stack.map{ |_| _.respond_to?(:annotation) && _.annotation ? [_, _.annotation] : _ }, :loop
82
151
 
83
- reverse = ->{ dy, dx = -dy, -dx }
84
- stringmode = false
85
- debug = ENV.key? "DEBUG"
86
- loop do
87
- if annotate && 1 < Time.now - time
88
- stdout.puts "timeout", :abort
89
- error.call
90
- end
91
- stdout.puts stack.map{ |_| _.respond_to?(:annotation) && _.annotation ? [_, _.annotation] : _ }, :loop if annotate
92
-
93
- move[]
94
- byte, annotation = code[y][x]
95
- char = byte.chr
96
- STDERR.puts [char, stringmode, (stack.last Integer ENV["DEBUG"] rescue stack)].inspect if debug
97
-
98
- next stack.push byte if stringmode && char != ?"
99
- return RASEL::ResultStruct.new stdout, stack, (
100
- t = pop[]
101
- 1 != t.denominator || t < 0 || t > 255 ? 255 : t.to_i
102
- ) if char == ?@
103
- case char
104
- when ?\s
105
-
106
- when ?0..?9 ; stack.push RASEL::StackItem.new byte - 48, annotation
107
- when ?A..?Z ; stack.push RASEL::StackItem.new byte - 55, annotation
108
- when ?" ; stringmode ^= true
109
- when ?# ; move[]
110
- when ?$ ; pop[]
111
- when ?: ; popped = pop[]; stack.push popped; stack.push RASEL::StackItem.new popped, annotation
112
- when ?- ; stack.push RASEL::StackItem.new -(pop[] - pop[]), annotation
113
- when ?/ ; b, a = pop[], pop[]; stack.push RASEL::StackItem.new b.zero? ? 0 : Rational(a) / b, annotation
114
- when ?% ; b, a = pop[], pop[]; stack.push RASEL::StackItem.new b.zero? ? 0 : Rational(a) % b, annotation
115
- when ?v ; dx, dy = 0, 1
116
- when ?> ; dx, dy = 1, 0
117
- when ?^ ; dx, dy = 0, -1
118
- when ?< ; dx, dy = -1, 0
119
- when ?? ; move[] if pop[] > 0
120
- when ?\\
121
- t = pop[]
122
- error.call if 1 != t.denominator
123
- stack.unshift 0 until stack.size > t
124
- stack[-t-1], stack[-1] = RASEL::StackItem.new(stack[-1], annotation), stack[-t-1] unless 0 > t
125
- # TODO: annotate prints
126
- when ?. ; stdout.print "#{_ = pop[]; 1 != _.denominator ? _.to_f : _.to_i} "
127
- when ?, ; stdout.print "#{_ = pop[]; 1 != _.denominator ? error.call : _ < 0 || _ > 255 ? error.call : _.to_i.chr}"
128
- when ?~ ; if _ = stdin.getbyte then stack.push RASEL::StackItem.new _, annotation; move[] end
129
- when ?&
130
- getc = ->{ stdin.getc or throw nil }
131
- catch nil do
132
- nil until (?0..?9).include? c = getc[]
133
- while (?0..?9).include? cc = stdin.getc ; c << cc end
134
- stdin.ungetbyte cc if cc
135
- stack.push RASEL::StackItem.new c.to_i, annotation
136
- move[]
137
- end
138
- when ?j
152
+ move[]
153
+ byte, annotation = code[y][x]
154
+ char = byte.chr
155
+
156
+ next stack.push StackItem.new byte, annotation if stringmode && char != ?"
157
+ return ResultStruct.new stdout, stack, (
139
158
  t = pop[]
140
- error.call if 1 != t.denominator
141
- y = (y + dy * t.to_i) % code.size
142
- x = (x + dx * t.to_i) % code[y].size
159
+ 1 != t.denominator || t < 0 || t > 255 ? 255 : t.to_i
160
+ ) if char == ?@
161
+ case char
162
+ when ?\s
163
+
164
+ when ?0..?9 ; stack.push StackItem.new byte - 48, annotation
165
+ when ?A..?Z ; stack.push StackItem.new byte - 55, annotation
166
+ when ?" ; stringmode ^= true
167
+ when ?# ; move[]
168
+ when ?$ ; pop[]
169
+ when ?: ; popped = pop[]; stack.push popped; stack.push StackItem.new popped, annotation
170
+ when ?- ; stack.push StackItem.new -(pop[] - pop[]), annotation
171
+ when ?/ ; b, a = pop[], pop[]; stack.push StackItem.new b.zero? ? 0 : Rational(a) / b, annotation
172
+ when ?% ; b, a = pop[], pop[]; stack.push StackItem.new b.zero? ? 0 : Rational(a) % b, annotation
173
+ when ?v ; dx, dy = 0, 1
174
+ when ?> ; dx, dy = 1, 0
175
+ when ?^ ; dx, dy = 0, -1
176
+ when ?< ; dx, dy = -1, 0
177
+ when ?? ; move[] if pop[] > 0
178
+ when ?\\
179
+ t = pop[]
180
+ error.call if 1 != t.denominator
181
+ stack.unshift 0 until stack.size > t
182
+ stack[-t-1], stack[-1] = StackItem.new(stack[-1], annotation), stack[-t-1] unless 0 > t
183
+ # TODO: annotate prints
184
+ when ?. ; stdout.print "#{_ = pop[]; 1 != _.denominator ? _.to_f : _.to_i} "
185
+ when ?, ; stdout.print "#{_ = pop[]; 1 != _.denominator ? error.call : _ < 0 || _ > 255 ? error.call : _.to_i.chr}"
186
+ when ?~ ; if _ = stdin.getbyte then stack.push StackItem.new _, annotation; move[] end
187
+ when ?&
188
+ getc = ->{ stdin.getc or throw nil }
189
+ catch nil do
190
+ nil until (?0..?9).include? c = getc[]
191
+ while (?0..?9).include? cc = stdin.getc ; c << cc end
192
+ stdin.ungetbyte cc if cc
193
+ stack.push StackItem.new c.to_i, annotation
194
+ move[]
195
+ end
196
+ when ?j
197
+ t = pop[]
198
+ error.call if 1 != t.denominator
199
+ y = (y + dy * t.to_i) % code.size
200
+ x = (x + dx * t.to_i) % code[y].size
143
201
 
144
- else ; error.call
202
+ else ; error.call
203
+ end
145
204
  end
146
205
  end
206
+
207
+ def self.write_pretty_json where, what
208
+ File.write where, "[\n " + (
209
+ what.map(&JSON.method(:dump)).join ",\n "
210
+ ) + "\n]\n"
211
+ end
212
+ end
213
+
214
+ def RASEL *args
215
+ RASEL::run *args
147
216
  end
data/rasel.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "rasel"
3
- spec.version = "1.1.3"
3
+ spec.version = "1.1.4"
4
4
  spec.summary = "Random Access Stack Esoteric Language"
5
5
 
6
6
  spec.author = "Victor Maslov aka Nakilon"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rasel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Maslov aka Nakilon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-01 00:00:00.000000000 Z
11
+ date: 2021-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: webrick