akaza 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +22 -0
- data/README.md +137 -0
- data/Rakefile +9 -0
- data/akaza.gemspec +33 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/str_to_ws.rb +12 -0
- data/lib/akaza.rb +12 -0
- data/lib/akaza/annotation.rb +35 -0
- data/lib/akaza/ast_ext.rb +61 -0
- data/lib/akaza/parser.rb +156 -0
- data/lib/akaza/version.rb +3 -0
- data/lib/akaza/vm.rb +87 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f8f268d8e1d526b8e7d63dba375322624e27a5af9c281f91101aa60c3ba5efc6
|
4
|
+
data.tar.gz: 561b42e5bac690f8c983cb03f992558ee5a35d24c81da8025973ff1a11b332a1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 250e590b52669d99cbd3bac3c942c38558f9fb270b60a273507d4695c249afdd238011013b364db491c9945c7b383446563533b18ee39ff71af1c26b5047d948
|
7
|
+
data.tar.gz: 2f6bac299e64ecaaa42a21d04de0c20393b9caab95cc1a01c5e9bdb3c486453f8fb53ea2aa68379758d3226c1a45299d8733c8dddfb15553c1bc0814dba3f246
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
akaza (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
minitest (5.11.3)
|
10
|
+
rake (12.3.2)
|
11
|
+
|
12
|
+
PLATFORMS
|
13
|
+
ruby
|
14
|
+
|
15
|
+
DEPENDENCIES
|
16
|
+
akaza!
|
17
|
+
bundler (~> 2.1.a)
|
18
|
+
minitest (>= 5)
|
19
|
+
rake (~> 12.0)
|
20
|
+
|
21
|
+
BUNDLED WITH
|
22
|
+
2.1.0.pre.1
|
data/README.md
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# Akaza
|
2
|
+
|
3
|
+
A cool Whitespace language implementation in Ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'akaza'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install akaza
|
20
|
+
|
21
|
+
|
22
|
+
## Requirements
|
23
|
+
|
24
|
+
* `RUBY_VERSION > '2.6'`
|
25
|
+
* It needs pattern match feature.
|
26
|
+
|
27
|
+
## Basic Usage
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'akaza'
|
31
|
+
|
32
|
+
# It use $stdin and $stdout
|
33
|
+
Akaza.eval(whitespace_code)
|
34
|
+
|
35
|
+
# Use other IO
|
36
|
+
input = StringIO.new(something)
|
37
|
+
output = StringIO.new
|
38
|
+
Akaza.eval(whitespace_code, input: input, output: output)
|
39
|
+
```
|
40
|
+
|
41
|
+
You can find example Whitespace programs from test/fixtures/ directory.
|
42
|
+
|
43
|
+
## Cool Usage
|
44
|
+
|
45
|
+
The basic usage is good, but it is not fun.
|
46
|
+
Akaza provides really "cool" interface to define a method with Whitespace.
|
47
|
+
You can write Whitespace in Ruby program directly!
|
48
|
+
|
49
|
+
For example:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
require 'akaza'
|
53
|
+
|
54
|
+
class A
|
55
|
+
extend Akaza::Annotation
|
56
|
+
|
57
|
+
whitespace def sum(a, b)
|
58
|
+
|
59
|
+
|
60
|
+
input=StringIO.new("#{a}\n#{b}\n")
|
61
|
+
output=StringIO.new
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
Akaza::Body
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
output.string.to_i
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
a = A.new
|
77
|
+
p a.sum(20, 22) # => 42
|
78
|
+
```
|
79
|
+
|
80
|
+
Cool! You no longer need to write Whitespace as a string literal. You can write Whitespace in Ruby seamlessly. It is elegant!
|
81
|
+
|
82
|
+
|
83
|
+
### Requirements of cool style
|
84
|
+
|
85
|
+
* Space, tab and newline in method body are evaluated as Whitespace program.
|
86
|
+
* Other characters are ignored for Whitespace, but they are evaluated as Ruby program.
|
87
|
+
* `Akaza::Body` is replaced with Whitespace code.
|
88
|
+
* `input` and `output` variables are necessary. They are IO.
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
Akaza provides a shorthand.
|
93
|
+
If `Akaza::Body` is omitted, the method only evaluates Whitespace program. The method receives `input` and `output`.
|
94
|
+
|
95
|
+
For example:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
require 'akaza'
|
99
|
+
|
100
|
+
class A
|
101
|
+
extend Akaza::Annotation
|
102
|
+
|
103
|
+
whitespace def sum(input, output)
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
This code is never evaluated.
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
So you can write any
|
113
|
+
sentences as comments!
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
a = A.new
|
123
|
+
input = StringIO.new("20\n22\n")
|
124
|
+
output = StringIO.new
|
125
|
+
a.sum(input, output)
|
126
|
+
p output.string
|
127
|
+
```
|
128
|
+
|
129
|
+
## Development
|
130
|
+
|
131
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
132
|
+
|
133
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
134
|
+
|
135
|
+
## Contributing
|
136
|
+
|
137
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pocke/akaza.
|
data/Rakefile
ADDED
data/akaza.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "akaza/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "akaza"
|
7
|
+
spec.version = Akaza::VERSION
|
8
|
+
spec.authors = ["Masataka Pocke Kuwabara"]
|
9
|
+
spec.email = ["kuwabara@pocke.me"]
|
10
|
+
|
11
|
+
spec.summary = %q{}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = "https://github.com/pocke/akaza"
|
14
|
+
|
15
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
19
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 2.1.a"
|
31
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
32
|
+
spec.add_development_dependency "minitest", ">= 5"
|
33
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "akaza"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/bin/str_to_ws.rb
ADDED
data/lib/akaza.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "akaza/version"
|
2
|
+
require 'akaza/ast_ext'
|
3
|
+
require 'akaza/annotation'
|
4
|
+
require 'akaza/parser'
|
5
|
+
require 'akaza/vm'
|
6
|
+
|
7
|
+
module Akaza
|
8
|
+
def self.eval(code, input: $stdin, output: $stdout)
|
9
|
+
commands = Parser.parse(code)
|
10
|
+
VM.new(commands, input, output).eval
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Akaza
|
2
|
+
module Annotation
|
3
|
+
using AstExt
|
4
|
+
|
5
|
+
def whitespace(method_name)
|
6
|
+
method = instance_method(method_name)
|
7
|
+
path = method.source_location[0]
|
8
|
+
ast = RubyVM::AbstractSyntaxTree.of(method)
|
9
|
+
|
10
|
+
placeholder = ast.find do |node|
|
11
|
+
case node
|
12
|
+
in [:COLON2, [:CONST, :Akaza], :Body] then true
|
13
|
+
else false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
first_index = ast.scope_args.last_index(path) - ast.first_index(path)
|
18
|
+
last_index = -1
|
19
|
+
code = ast.to_source(path)[first_index..last_index]
|
20
|
+
define_method("__#{method_name}_whitespace") do |input, output|
|
21
|
+
Akaza.eval(code, input: input, output: output)
|
22
|
+
end
|
23
|
+
|
24
|
+
undef_method method_name
|
25
|
+
if placeholder
|
26
|
+
original_code = ast.to_source(path)
|
27
|
+
s, e = placeholder.first_index(path) - ast.first_index(path), placeholder.last_index(path) - ast.first_index(path)
|
28
|
+
original_code[s..e] = "(__#{method_name}_whitespace(input, output))"
|
29
|
+
class_eval original_code
|
30
|
+
else
|
31
|
+
alias_method method_name, "__#{method_name}_whitespace"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Akaza
|
2
|
+
module AstExt
|
3
|
+
refine RubyVM::AbstractSyntaxTree::Node do
|
4
|
+
def to_source(path)
|
5
|
+
file_content(path)[first_index(path)..last_index(path)]
|
6
|
+
end
|
7
|
+
|
8
|
+
def traverse(&block)
|
9
|
+
block.call self
|
10
|
+
children.each do |child|
|
11
|
+
child.traverse(&block) if child.is_a?(RubyVM::AbstractSyntaxTree::Node)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def find(&block)
|
16
|
+
traverse do |node|
|
17
|
+
return node if block.call(node)
|
18
|
+
end
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def deconstruct
|
23
|
+
[type, *children]
|
24
|
+
end
|
25
|
+
|
26
|
+
# method node ext
|
27
|
+
|
28
|
+
def scope_body
|
29
|
+
children[2]
|
30
|
+
end
|
31
|
+
|
32
|
+
def scope_args
|
33
|
+
children[1]
|
34
|
+
end
|
35
|
+
|
36
|
+
def first_index(path)
|
37
|
+
return first_column if first_lineno == 1
|
38
|
+
|
39
|
+
lines = file_content(path).split("\n")
|
40
|
+
lines[0..(first_lineno - 2)].sum(&:size) +
|
41
|
+
first_lineno - 1 + # For \n
|
42
|
+
first_column
|
43
|
+
end
|
44
|
+
|
45
|
+
def last_index(path)
|
46
|
+
last_column = self.last_column - 1
|
47
|
+
return last_column if last_lineno == 1
|
48
|
+
|
49
|
+
lines = file_content(path).split("\n")
|
50
|
+
lines[0..(last_lineno - 2)].sum(&:size) +
|
51
|
+
last_lineno - 1 + # For \n
|
52
|
+
last_column
|
53
|
+
end
|
54
|
+
|
55
|
+
private def file_content(path)
|
56
|
+
@file_content ||= {}
|
57
|
+
@file_content[path] ||= File.binread(path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/akaza/parser.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
module Akaza
|
2
|
+
class Parser
|
3
|
+
EOF = Class.new(StandardError)
|
4
|
+
|
5
|
+
SPACE = " "
|
6
|
+
TAB = "\t"
|
7
|
+
NL = "\n"
|
8
|
+
|
9
|
+
def self.parse(code)
|
10
|
+
self.new(code).parse
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(code)
|
14
|
+
@io = StringIO.new(code)
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse
|
18
|
+
commands = []
|
19
|
+
|
20
|
+
loop do
|
21
|
+
case c = nextc
|
22
|
+
when SPACE
|
23
|
+
commands << parse_stack
|
24
|
+
when NL
|
25
|
+
commands << parse_flow
|
26
|
+
when TAB
|
27
|
+
case nextc
|
28
|
+
when SPACE
|
29
|
+
commands << parse_calc
|
30
|
+
when TAB
|
31
|
+
commands << parse_heap
|
32
|
+
when NL
|
33
|
+
commands << parse_io
|
34
|
+
end
|
35
|
+
else
|
36
|
+
raise "unreachable: #{c}"
|
37
|
+
end
|
38
|
+
rescue EOF
|
39
|
+
return commands
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private def parse_stack
|
44
|
+
case ch = nextc
|
45
|
+
when SPACE
|
46
|
+
[:stack, :push, nextint]
|
47
|
+
else
|
48
|
+
case c = [ch, nextc]
|
49
|
+
when [NL, SPACE]
|
50
|
+
[:stack, :dup]
|
51
|
+
when [NL, TAB]
|
52
|
+
[:stack, :swap]
|
53
|
+
when [NL, NL]
|
54
|
+
[:stack, :pop]
|
55
|
+
else
|
56
|
+
raise "unreachable: #{c}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private def parse_flow
|
62
|
+
case c = [nextc, nextc]
|
63
|
+
when [SPACE, SPACE]
|
64
|
+
[:flow, :def, nextlabel]
|
65
|
+
when [SPACE, TAB]
|
66
|
+
[:flow, :call, nextlabel]
|
67
|
+
when [SPACE, NL]
|
68
|
+
[:flow, :jump, nextlabel]
|
69
|
+
when [TAB, SPACE]
|
70
|
+
[:flow, :jump_if_zero, nextlabel]
|
71
|
+
when [TAB, TAB]
|
72
|
+
[:flow, :jump_if_neg, nextlabel]
|
73
|
+
when [TAB, NL]
|
74
|
+
[:flow, :end]
|
75
|
+
when [NL, NL]
|
76
|
+
[:flow, :exit]
|
77
|
+
else
|
78
|
+
raise "unreachable: #{c}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private def parse_calc
|
83
|
+
case c = [nextc, nextc]
|
84
|
+
when [SPACE, SPACE]
|
85
|
+
[:calc, :add]
|
86
|
+
when [SPACE, TAB]
|
87
|
+
[:calc, :sub]
|
88
|
+
when [SPACE, NL]
|
89
|
+
[:calc, :multi]
|
90
|
+
when [TAB, SPACE]
|
91
|
+
[:calc, :div]
|
92
|
+
when [TAB, TAB]
|
93
|
+
[:calc, :mod]
|
94
|
+
else
|
95
|
+
raise "unreachable: #{c}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private def parse_heap
|
100
|
+
case c = nextc
|
101
|
+
when SPACE
|
102
|
+
[:heap, :save]
|
103
|
+
when TAB
|
104
|
+
[:heap, :load]
|
105
|
+
else
|
106
|
+
raise "unreachable: #{c}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private def parse_io
|
111
|
+
case c = [nextc, nextc]
|
112
|
+
when [SPACE, SPACE]
|
113
|
+
[:io, :write_char]
|
114
|
+
when [SPACE, TAB]
|
115
|
+
[:io, :write_num]
|
116
|
+
when [TAB, SPACE]
|
117
|
+
[:io, :read_char]
|
118
|
+
when [TAB, NL]
|
119
|
+
[:io, :read_num]
|
120
|
+
else
|
121
|
+
raise "unreachable: #{c}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
private def nextc
|
126
|
+
case ch = @io.read(1)
|
127
|
+
when SPACE, TAB, NL
|
128
|
+
return ch
|
129
|
+
when nil
|
130
|
+
raise EOF
|
131
|
+
else
|
132
|
+
# comment
|
133
|
+
nextc
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
private def nextint
|
138
|
+
sign = nextc
|
139
|
+
int = +""
|
140
|
+
while (ch = nextc) != NL
|
141
|
+
int << ch
|
142
|
+
end
|
143
|
+
res = int.gsub(SPACE, '0').gsub(TAB, '1').to_i(2)
|
144
|
+
res = 0 - res if sign == TAB
|
145
|
+
res
|
146
|
+
end
|
147
|
+
|
148
|
+
private def nextlabel
|
149
|
+
label = +""
|
150
|
+
while (ch = nextc) != NL
|
151
|
+
label << ch
|
152
|
+
end
|
153
|
+
label
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
data/lib/akaza/vm.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
module Akaza
|
2
|
+
class VM
|
3
|
+
def initialize(commands, input, output)
|
4
|
+
@commands = commands
|
5
|
+
@input = input
|
6
|
+
@output = output
|
7
|
+
@stack = []
|
8
|
+
@heap = {}
|
9
|
+
@call_stack = []
|
10
|
+
@index = 0
|
11
|
+
@labels = {}
|
12
|
+
|
13
|
+
prepare_label
|
14
|
+
end
|
15
|
+
|
16
|
+
def eval
|
17
|
+
while true
|
18
|
+
case @commands[@index]
|
19
|
+
in [:stack, :push, number]
|
20
|
+
@stack.push number
|
21
|
+
in [:stack, :dup]
|
22
|
+
@stack.push @stack.last
|
23
|
+
in [:stack, :swap]
|
24
|
+
@stack[-1], @stack[-2] = @stack[-2], @stack[-1]
|
25
|
+
in [:stack, :pop]
|
26
|
+
@stack.pop
|
27
|
+
in [:calc, :add]
|
28
|
+
@stack.push @stack.pop + @stack.pop
|
29
|
+
in [:calc, :sub]
|
30
|
+
@stack.push @stack.pop - @stack.pop
|
31
|
+
in [:calc, :multi]
|
32
|
+
@stack.push @stack.pop * @stack.pop
|
33
|
+
in [:calc, :div]
|
34
|
+
@stack.push @stack.pop / @stack.pop
|
35
|
+
in [:calc, :mod]
|
36
|
+
@stack.push @stack.pop % @stack.pop
|
37
|
+
in [:heap, :save]
|
38
|
+
val = @stack.pop
|
39
|
+
addr = @stack.pop
|
40
|
+
@heap[addr] = val
|
41
|
+
in [:heap, :load]
|
42
|
+
addr = @stack.pop
|
43
|
+
@stack.push @heap[addr]
|
44
|
+
in [:flow, :def, label]
|
45
|
+
# does nothing
|
46
|
+
in [:flow, :call, label]
|
47
|
+
raise "unknwon label:#{label}" unless @labels.key?(label)
|
48
|
+
@call_stack.push @index
|
49
|
+
@index = @labels[label]
|
50
|
+
in [:flow, :jump, label]
|
51
|
+
raise "unknwon label:#{label}" unless @labels.key?(label)
|
52
|
+
@index = @labels[label]
|
53
|
+
in [:flow, :jump_if_zero, label]
|
54
|
+
@index = @labels[label] if @stack.pop == 0
|
55
|
+
in [:flow, :jump_if_neg, label]
|
56
|
+
@index = @labels[label] if @stack.pop < 0
|
57
|
+
in [:flow, :end]
|
58
|
+
@index = @call_stack.pop
|
59
|
+
in [:flow, :exit]
|
60
|
+
return
|
61
|
+
in [:io, :write_char]
|
62
|
+
@output.write @stack.pop.chr
|
63
|
+
in [:io, :write_num]
|
64
|
+
@output.write @stack.pop.to_s
|
65
|
+
in [:io, :read_char]
|
66
|
+
addr = @stack.pop
|
67
|
+
@heap[addr] = @input.read(1).ord
|
68
|
+
in [:io, :read_num]
|
69
|
+
addr = @stack.pop
|
70
|
+
@heap[addr] = @input.readline.to_i
|
71
|
+
end
|
72
|
+
@index += 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def prepare_label
|
77
|
+
@commands.each.with_index do |command, index|
|
78
|
+
case command
|
79
|
+
in [:flow, :def, label]
|
80
|
+
@labels[label] = index - 1
|
81
|
+
else
|
82
|
+
# skip
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: akaza
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Masataka Pocke Kuwabara
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-04-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.1.a
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.1.a
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5'
|
55
|
+
description: ''
|
56
|
+
email:
|
57
|
+
- kuwabara@pocke.me
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- akaza.gemspec
|
68
|
+
- bin/console
|
69
|
+
- bin/setup
|
70
|
+
- bin/str_to_ws.rb
|
71
|
+
- lib/akaza.rb
|
72
|
+
- lib/akaza/annotation.rb
|
73
|
+
- lib/akaza/ast_ext.rb
|
74
|
+
- lib/akaza/parser.rb
|
75
|
+
- lib/akaza/version.rb
|
76
|
+
- lib/akaza/vm.rb
|
77
|
+
homepage: https://github.com/pocke/akaza
|
78
|
+
licenses: []
|
79
|
+
metadata:
|
80
|
+
homepage_uri: https://github.com/pocke/akaza
|
81
|
+
source_code_uri: https://github.com/pocke/akaza
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubygems_version: 3.0.3
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: ''
|
101
|
+
test_files: []
|