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 +4 -4
- data/bin/rasel-annotated +1 -1
- data/bin/rasel-ide +1 -1
- data/lib/rasel.rb +179 -110
- data/rasel.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b3b17070c0c2dd2bf982193c8becb0d2f079971
|
4
|
+
data.tar.gz: 053577514bcbe505c5c6bd1766ec0ddf52ae9974
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfe946adc630d7fe4c91c9d10f4407c3903dba8255d1c5531681ab387f8117bab5f084a59d9b010873d6e24d1936fe91030488963b43b3520d00367b289cd3f2
|
7
|
+
data.tar.gz: 5c86eb71eecd98797bfefd987400d25c7f91bce3270b3f3ee5588c42f4c80813d5b605e84cf8aa7af5cb5c72abb35792ab2cc278dfdad5a109209a0a1f297eae
|
data/bin/rasel-annotated
CHANGED
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
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
146
|
+
if 1 < Time.now - time
|
147
|
+
stdout.puts "timeout", :abort
|
148
|
+
error.call
|
74
149
|
end
|
75
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
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
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.
|
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-
|
11
|
+
date: 2021-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: webrick
|