rasel 1.1.3 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|