uby_interpreter 1.0.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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2EwYzRjY2ZhMDhkMDhjZjgzZWIzMTBlNjE4ZWQ2MmM0YTQ4NGJiYg==
5
+ data.tar.gz: !binary |-
6
+ OWU5MWNhOTA4MDEwNDdlNTBjZWJlOThiMDRkMjE0YzBkMzgxMDUwOA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NWE1MDUyNGY5MjFjMGY4MjEwMTk5M2FhMmU4MzNiNDc3MjJkNDAxY2QxM2Q0
10
+ MDJiNTI0ZDVkMjMwYTUyOWU2MDY2YzFiNjRmMGQ2ZTg2NDUyZjg3MGQwNTVm
11
+ MDk2NzU2OTI1ZGIxNDMzNTFjNmFlZDA5NWQzZDNiY2JjMmNhZWY=
12
+ data.tar.gz: !binary |-
13
+ OTE2NDhmZDUzMTU0OWI4MjU0OWE3ZTkxMWExN2NhMmQ3NTczOGY1MTMwYTE1
14
+ OTU0MGM1NWQ2YTZmYmE3YzNkZmViMGM0YjQxNjI0YzI0OWQ0ODliYTI3Zjk1
15
+ YWFmZDJlYjRiOGUwMWQzZGU3NDE2MGM2MzA5OTdkNWViYTI0MmQ=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in uby_interpreter.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Hrvoje Šimić
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # UbyInterpreter
2
+
3
+ Ruby-like interpreter implementation.
4
+
5
+ Based on a [talk](https://www.youtube.com/watch?v=r1JMxJ06I98) by [Ryan Davis](https://github.com/zenspider).
6
+
7
+ ## Features
8
+
9
+ * Basic numeric types, true, false, strings, arrays, hashes and nil
10
+ * Conditional branching and looping
11
+ * Primitive and user defined functions
12
+ * Local variables and variable scoping
13
+ * Test-driven, extensible, patterns-based design
14
+ * ~130 LOC for implementation, ~70 LOC for tests
15
+ * Fits in one head
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ gem 'uby_interpreter'
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install uby_interpreter
30
+
31
+ ## Running tests
32
+
33
+ $ rake
34
+
35
+ ## Contributing
36
+
37
+ 1. Fork it
38
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
39
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
40
+ 4. Push to the branch (`git push origin my-new-feature`)
41
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = 'test/**/*_test.rb'
7
+ end
8
+
9
+ task :default => [:test]
@@ -0,0 +1,158 @@
1
+ require "sexp_processor"
2
+ require "ruby19_parser"
3
+
4
+ class UbyInterpreter < SexpInterpreter
5
+
6
+ VERSION = "1.0.0"
7
+
8
+ class Environment
9
+ def [] k
10
+ self.all[k]
11
+ end
12
+
13
+ def []= k, v
14
+ @env.last[k] = v
15
+ end
16
+
17
+ def all
18
+ @env.inject(&:merge)
19
+ end
20
+
21
+ def scope
22
+ @env.push({})
23
+
24
+ yield
25
+ ensure
26
+ @env.pop
27
+ end
28
+
29
+ def initialize
30
+ @env = [{}]
31
+ end
32
+ end
33
+
34
+ attr_accessor :parser, :env
35
+
36
+ def initialize
37
+ super
38
+
39
+ self.parser = Ruby19Parser.new
40
+ self.env = Environment.new
41
+ end
42
+
43
+ def eval src
44
+ process parse src
45
+ end
46
+
47
+ def parse src
48
+ self.parser.process src
49
+ end
50
+
51
+ def process_lit s
52
+ s.last
53
+ end
54
+
55
+ def process_if s
56
+ _, c, t, f = s
57
+
58
+ c = process c
59
+
60
+ if c then
61
+ process t
62
+ else
63
+ process f
64
+ end
65
+ end
66
+
67
+ def process_nil s
68
+ nil
69
+ end
70
+
71
+ def process_true s
72
+ true
73
+ end
74
+
75
+ def process_false s
76
+ false
77
+ end
78
+
79
+ def process_call s
80
+ _, recv, msg, *args = s
81
+
82
+ recv = process recv
83
+ args.map! {|sub| process sub}
84
+
85
+ if recv then
86
+ recv.send(msg, *args)
87
+ else
88
+ self.env.scope do
89
+ decls, body = self.env[msg]
90
+
91
+ decls.rest.zip(args).each do |name, val|
92
+ self.env[name] = val
93
+ end
94
+
95
+ process_block s(:block, *body)
96
+ end
97
+ end
98
+ end
99
+
100
+ def process_block s
101
+ result = nil
102
+ s.rest.each do |sub|
103
+ result = process sub
104
+ end
105
+ result
106
+ end
107
+
108
+ def process_lasgn s
109
+ _, n, v = s
110
+
111
+ self.env[n] = process v
112
+ end
113
+
114
+ def process_lvar s
115
+ _, n = s
116
+ self.env[n]
117
+ end
118
+
119
+ def process_defn s
120
+ _, name, args, *body = s
121
+
122
+ self.env[name] = [args, body]
123
+
124
+ nil
125
+ end
126
+
127
+ def process_while s
128
+ _, cond, *body = s
129
+ body.pop
130
+
131
+ while process cond
132
+ process_block s(:block, *body)
133
+ end
134
+ end
135
+
136
+ def process_str s
137
+ _, string = s
138
+
139
+ string
140
+ end
141
+
142
+ def process_array s
143
+ _, *args = s
144
+
145
+ args.map {|arg| arg.last}
146
+ end
147
+
148
+ def process_hash s
149
+ _, *args = s
150
+
151
+ args.each_slice(2).inject({}) do |hash, pair|
152
+ (_, key), (_, value) = pair
153
+
154
+ hash[key] = value
155
+ hash
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,90 @@
1
+ require "minitest/autorun"
2
+ require "uby_interpreter"
3
+
4
+ class UbyInterpreterTest < MiniTest::Test
5
+ attr_accessor :int
6
+
7
+ def setup
8
+ self.int = UbyInterpreter.new
9
+ end
10
+
11
+ def assert_eval exp, src, msg = nil
12
+ assert_equal exp, int.eval(src), msg
13
+ end
14
+
15
+ def test_sanity
16
+ assert_eval 3, "3"
17
+ assert_eval 7, "3 + 4"
18
+ end
19
+
20
+ def test_if
21
+ assert 42, "if true then 42 else 24 end"
22
+ end
23
+
24
+ def test_if_falsey
25
+ assert_eval 24, "if nil then 42 else 24 end"
26
+ assert_eval 24, "if false then 42 else 24 end"
27
+ end
28
+
29
+ def test_lvar
30
+ assert_eval 42, "x = 42; x"
31
+ end
32
+
33
+ def test_defn
34
+ assert_eval nil, <<-EOM
35
+ def double n
36
+ 2 * n
37
+ end
38
+ EOM
39
+
40
+ assert_eval 42, "double(21)"
41
+ end
42
+
43
+ def define_fib
44
+ assert_eval nil, <<-END
45
+ def fib n
46
+ if n <= 2 then
47
+ 1
48
+ else
49
+ fib(n - 2) + fib(n - 1)
50
+ end
51
+ end
52
+ END
53
+ end
54
+
55
+ def test_fib
56
+ define_fib
57
+
58
+ assert_eval 8, "fib(6)"
59
+ end
60
+
61
+ def test_while_sum_of_fibs
62
+ define_fib
63
+
64
+ assert_eval 1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + 34 + 55, <<-EOM
65
+ n = 1
66
+ sum = 0
67
+ while n <= 10
68
+ sum += fib(n)
69
+ n += 1
70
+ end
71
+ sum
72
+ EOM
73
+ end
74
+
75
+ def test_strings
76
+ assert_eval "i can has strings", %Q{"i can has strings"}
77
+ assert_eval "I CAN HAS STRINGS", %Q{"i can has strings".upcase}
78
+ end
79
+
80
+ def test_arrays
81
+ assert_eval [1, 2, 3], "[1, 2, 3]"
82
+ assert_eval [1, 2, 3, 4, 5, 6], "[1, 2, 3] + [4, 5, 6]"
83
+ assert_eval 1, "[1, 2, 3].first"
84
+ end
85
+
86
+ def test_hashes
87
+ hash = {:foo => :bar, :baz => :biz}
88
+ assert_eval hash, "{:foo => :bar, :baz => :biz}"
89
+ end
90
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require "uby_interpreter"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "uby_interpreter"
9
+ spec.version = UbyInterpreter::VERSION
10
+ spec.authors = ["Hrvoje Šimić"]
11
+ spec.email = ["shime.ferovac@gmail.com"]
12
+ spec.description = %q{Simple Ruby interpreter}
13
+ spec.summary = %q{Simple Ruby interpreter}
14
+ spec.homepage = "https://github.com/shime/uby_interpreter"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+ spec.add_runtime_dependency "ruby_parser"
22
+ spec.add_runtime_dependency "sexp_processor"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "minitest"
27
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: uby_interpreter
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Hrvoje Šimić
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby_parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sexp_processor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Simple Ruby interpreter
84
+ email:
85
+ - shime.ferovac@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - Gemfile
92
+ - LICENSE.txt
93
+ - README.md
94
+ - Rakefile
95
+ - lib/uby_interpreter.rb
96
+ - test/uby_interpreter_test.rb
97
+ - uby_interpreter.gemspec
98
+ homepage: https://github.com/shime/uby_interpreter
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.0.3
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Simple Ruby interpreter
122
+ test_files:
123
+ - test/uby_interpreter_test.rb
124
+ has_rdoc: