uby_interpreter 1.0.0

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