lisp 1.3.0 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 728f826f5c7ad7f2b90d6861cdd6d0792c9af21f
4
- data.tar.gz: 21b608d9ee103ad308ab4a2b346f459609684120
2
+ SHA256:
3
+ metadata.gz: 600c4afdb71f1e0635249197b7d0eb7fa9c55a5dabf11bffa5e636f61858712e
4
+ data.tar.gz: c73dade15637b2226120e61b31d41ae23363fb25cc4ba462e302dc1c32822855
5
5
  SHA512:
6
- metadata.gz: 451e92aa8b46ea6b0ad3b6d7bab7b0118052f2ec43fdc3c9779ce93817e6a178e6cf99c11e92732e193b952d8f65375eac2338f0360bac181ad892270d14d999
7
- data.tar.gz: d297679c014dfa9f0c52be2e8e73baf9c9175e4b3a1038440da0cb20d2597139a526a68d90845d0ab6efdec0f2ef55ae567af36c0219a45ec333d02c31554b3e
6
+ metadata.gz: 88191d156aba236ac005556a8002a24ab12f54129cb3aac6e82502dfa0741f320cf9e535299a0716e8fd2f41ce1f6f005b11d0a88c746a516d0951ae3d0188b4
7
+ data.tar.gz: 919dc08c1f74c65b878e734443d868a2cd006c6bda3a24d4d6c5850aeff1428da591da8d45b392509d4c238f780e86dc4450e7490535d0f3287d6fcee4144d44
@@ -0,0 +1,19 @@
1
+ name: Continuous Integration
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+
9
+ strategy:
10
+ matrix:
11
+ ruby: [ '2.3', '2.7' ]
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - run: bundle exec rake
data/.gitignore CHANGED
@@ -1,3 +1,6 @@
1
1
  Gemfile.lock
2
2
  env
3
3
  pkg
4
+ coverage
5
+ doc
6
+ .yardoc
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- group :development do
4
- gem "codeclimate-test-reporter", require: nil
5
- end
3
+ gem "rake", "~> 12.0"
4
+ gem "yard", "~> 0.9"
5
+ gem "simplecov", "~> 0.17"
6
6
 
7
7
  gemspec
data/README.md CHANGED
@@ -1,35 +1,55 @@
1
- lisp-rb
2
- =======
1
+ lisp
2
+ ====
3
3
 
4
- [![Code Climate](https://codeclimate.com/github/jamesmoriarty/lisp-rb.png)](https://codeclimate.com/github/jamesmoriarty/lisp-rb) [![Code Climate](https://codeclimate.com/github/jamesmoriarty/lisp-rb/coverage.png)](https://codeclimate.com/github/jamesmoriarty/lisp-rb)
4
+ ![Gem Version][3] ![Gem][1] ![Build Status][2]
5
5
 
6
- Lisp Interpreter in Ruby. Inspired by [Lis.py](http://norvig.com/lispy.html).
6
+ Minimal Lisp interpreter using 75LOC and only standard libraries excluding the REPL. Inspired by [Lis.py](http://norvig.com/lispy.html).
7
7
 
8
- ```
9
- $ lisp-rb
8
+ ```clojure
9
+ $ lisp-repl
10
10
  ctrl-c to exit
11
- > (define pi 3.14)
12
- 3.14
13
- > (* pi 2)
14
- 6.28
15
- > (define area (lambda (r) (* 3.141592653 (* r r))))
16
- #<Proc:0x007f8af9c59ff0@./lisp.rb:44>
17
- > (area 3)
18
- 28.274333877
19
- > (define fact (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1))))))
20
- #<Proc:0x007f9a4cc4acf0@./lisp.rb:63 (lambda)>
21
- > (fact 10)
22
- 3628800.0
11
+ > (begin
12
+ (> (define incf
13
+ ((> (lambda (x)
14
+ (((> (set! x (+ x 1))))
15
+ (> (define one 1)
16
+ (> (incf one))
17
+ 2
18
+ >
23
19
  ```
24
20
 
25
21
  Install
26
22
  -------
27
- [![Gem Version](https://badge.fury.io/rb/lisp.svg)](http://badge.fury.io/rb/lisp)
28
23
 
29
24
  ```
30
25
  gem install lisp
31
26
  ```
32
27
 
28
+ Usage
29
+ -----
30
+
31
+ ```clojure
32
+ require "lisp"
33
+
34
+ Lisp.eval(<<-eos)
35
+ (begin
36
+ (define fact
37
+ (lambda (n)
38
+ (if (<= n 1)
39
+ 1
40
+ (* n (fact (- n 1))))))
41
+ (fact 10))
42
+ eos # => 3628800
43
+ ```
44
+
45
+ Commandline
46
+ -----------
47
+
48
+ ```
49
+ lisp-repl
50
+ ```
51
+
52
+
33
53
  Features
34
54
  --------
35
55
 
@@ -50,3 +70,7 @@ Features
50
70
  - [x] __assignment__ - (set! var exp) Evaluate exp and assign that value to var, which must have been previously defined (with a define or as a parameter to an enclosing procedure). _Example: (set! x2 (* x x))_
51
71
 
52
72
  - [x] __sequencing__ - (begin exp...) Evaluate each of the expressions in left-to-right order, and return the final value. _Example: (begin (set! x 1) (set! x (+ x 1)) (* x 2)) ⇒ 4_
73
+
74
+ [1]: https://img.shields.io/gem/dt/lisp
75
+ [2]: https://travis-ci.org/jamesmoriarty/lisp.svg?branch=master
76
+ [3]: https://img.shields.io/gem/v/lisp
data/Rakefile CHANGED
@@ -1,7 +1,29 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require 'yard'
2
4
 
3
- require 'rake/testtask'
5
+ YARD::Rake::YardocTask.new do |t|
6
+ t.files = ['lib/**/*.rb', 'README', 'CHANGELOG', 'CODE_OF_CONDUCT']
7
+ t.options = []
8
+ t.stats_options = ['--list-undoc']
9
+ end
10
+
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << "test"
13
+ t.libs << "lib"
14
+ t.test_files = FileList["test/**/*_test.rb"]
15
+ end
4
16
 
5
- task :default do
6
- Dir.glob('./test/*.rb').each { |file| require file}
17
+ namespace :gh do
18
+ desc "Deploy yard docs to github pages"
19
+ task :pages => :yard do
20
+ `git add -f doc`
21
+ `git commit -am "update: $(date)"`
22
+ `git subtree split --prefix doc -b gh-pages`
23
+ `git push -f origin gh-pages:gh-pages`
24
+ `git branch -D gh-pages`
25
+ `git reset head~1`
26
+ end
7
27
  end
28
+
29
+ task :default => :test
@@ -2,4 +2,4 @@
2
2
 
3
3
  require_relative "../lib/lisp"
4
4
 
5
- Lisp.repl
5
+ Lisp::REPL.new.run
data/lib/lisp.rb CHANGED
@@ -1,76 +1,8 @@
1
- $:.unshift File.dirname(__FILE__)
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
2
 
3
3
  require "lisp/version"
4
+ require "lisp/interpreter"
4
5
  require "lisp/repl"
5
6
 
6
7
  module Lisp
7
- def self.eval(string)
8
- execute(parse(tokenize(string)))
9
- end
10
-
11
- def self.tokenize(string)
12
- string.gsub("("," ( ").gsub(")"," ) ").split
13
- end
14
-
15
- def self.parse(tokens, tree = [])
16
- raise "unexpected: eof" if tokens.size.zero?
17
-
18
- case token = tokens.shift
19
- when "("
20
- while tokens[0] != ")" do
21
- tree.push parse(tokens)
22
- end
23
- tokens.shift
24
- tree
25
- when ")"
26
- raise "unexpected: )"
27
- else
28
- evaluator(token)
29
- end
30
- end
31
-
32
- def self.evaluator(token)
33
- case token
34
- when /\d/
35
- token.to_f
36
- else
37
- token.to_sym
38
- end
39
- end
40
-
41
- def self.execute(exp, scope = global)
42
- return scope[exp] if exp.is_a? Symbol
43
- return exp unless exp.is_a? Array
44
-
45
- case exp[0]
46
- when :define
47
- _, var, exp = exp
48
- scope[var] = execute(exp, scope)
49
- when :lambda
50
- _, params, exp = exp
51
- lambda { |*args| execute(exp, scope.merge(Hash[params.zip(args)])) }
52
- when :if
53
- _, test, conseq, alt = exp
54
- exp = execute(test, scope) ? conseq : alt
55
- execute(exp, scope)
56
- when :set!
57
- _, var, exp = exp
58
- if scope.has_key?(var) then scope[var] = execute(exp, scope) else raise "#{var} is undefined" end
59
- when :begin
60
- _, *exp = exp
61
- exp.map { |exp| execute(exp) }.last
62
- else
63
- func, *args = exp.map { |exp| execute(exp, scope) }
64
- func.call(*args)
65
- end
66
- end
67
-
68
- def self.global
69
- @scope ||= begin
70
- operators = [:==, :"!=", :"<", :"<=", :">", :">=", :+, :-, :*, :/]
71
- operators.inject({}) do |scope, operator|
72
- scope.merge(operator => lambda { |*args| args.inject(&operator) })
73
- end
74
- end
75
- end
76
8
  end
@@ -0,0 +1,74 @@
1
+ module Lisp
2
+ class << self
3
+ def eval string
4
+ execute parse tokenize string
5
+ end
6
+
7
+ def tokenize string
8
+ string.gsub("(", " ( ").gsub(")", " ) ").split
9
+ end
10
+
11
+ def parse tokens, tree = []
12
+ raise "unexpected: eof" if tokens.size.zero?
13
+
14
+ case token = tokens.shift
15
+ when "("
16
+ while tokens[0] != ")" do
17
+ tree.push parse tokens
18
+ end
19
+ tokens.shift
20
+ tree
21
+ when ")"
22
+ raise "unexpected: )"
23
+ else
24
+ atom token
25
+ end
26
+ end
27
+
28
+ def execute expression, scope = global
29
+ return scope.fetch(expression) { |var| raise "#{var} is undefined" } if expression.is_a? Symbol
30
+ return expression unless expression.is_a? Array
31
+
32
+ case expression[0]
33
+ when :define
34
+ _, var, expression = expression
35
+ scope[var] = execute expression, scope
36
+ when :lambda
37
+ _, params, expression = expression
38
+ lambda { |*args| execute expression, scope.merge(Hash[params.zip(args)]) }
39
+ when :if
40
+ _, test, consequent, alternative = expression
41
+ expression = if execute test, scope then consequent else alternative end
42
+ execute expression, scope
43
+ when :set!
44
+ _, var, expression = expression
45
+ if scope.has_key?(var) then scope[var] = execute expression, scope else raise "#{var} is undefined" end
46
+ when :begin
47
+ _, *expression = expression
48
+ expression.map { |expression| execute expression, scope }.last
49
+ else
50
+ function, *args = expression.map { |expression| execute expression, scope }
51
+ function.call *args
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def atom token
58
+ case token
59
+ when /^[\p{N}\.]+$/
60
+ token.to_f % 1 > 0 ? token.to_f : token.to_i
61
+ else
62
+ token.to_sym
63
+ end
64
+ end
65
+
66
+ def global
67
+ operators = [:==, :"!=", :"<", :"<=", :">", :">=", :+, :-, :*, :/]
68
+
69
+ operators.inject({}) do |scope, operator|
70
+ scope.merge operator => lambda { |*args| args.inject &operator }
71
+ end
72
+ end
73
+ end
74
+ end
data/lib/lisp/repl.rb CHANGED
@@ -1,22 +1,66 @@
1
- #!/usr/bin/env ruby
2
1
  require "coolline"
2
+ require "coderay"
3
3
 
4
4
  module Lisp
5
- def self.repl
6
- trap("SIGINT") { throw :exit }
7
- puts "ctrl-c to exit"
8
- catch(:exit) do
9
- loop do
10
- puts begin
11
- eval Coolline.new.readline
12
- rescue Exception => e
13
- e.message
5
+ class REPL
6
+ attr_reader :io, :input
7
+
8
+ def initialize
9
+ @io = Coolline.new do |config|
10
+ config.transform_proc = proc do
11
+ CodeRay.scan(config.line, :clojure).term
14
12
  end
15
13
  end
14
+
15
+ reset_input!
16
+ end
17
+
18
+ def run
19
+ trap("SIGINT") { throw :exit }
20
+
21
+ puts "ctrl-c to exit"
22
+
23
+ catch(:exit) do
24
+ loop do
25
+ begin
26
+ @input += io.readline prompt
27
+
28
+ if open_count == close_count
29
+ puts Lisp.eval input
30
+
31
+ reset_input!
32
+ end
33
+ rescue Exception => e
34
+ puts e.message
35
+
36
+ reset_input!
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def prompt
45
+ count = open_count - close_count
46
+ char = count > 0 ? ?( : ?)
47
+ "#{char * count}> "
48
+ end
49
+
50
+ def reset_input!
51
+ @input = String.new
16
52
  end
17
- end
18
- end
19
53
 
20
- if __FILE__ == $0
21
- Lisp.repl
54
+ def open_count
55
+ tokens.count(?()
56
+ end
57
+
58
+ def close_count
59
+ tokens.count(?))
60
+ end
61
+
62
+ def tokens
63
+ Lisp.tokenize input
64
+ end
65
+ end
22
66
  end
data/lib/lisp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lisp
2
- VERSION = "1.3.0"
2
+ VERSION = '1.5.2'.freeze
3
3
  end
data/lisp.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'lisp/version'
@@ -8,9 +9,9 @@ Gem::Specification.new do |spec|
8
9
  spec.version = Lisp::VERSION
9
10
  spec.authors = ["James Moriarty"]
10
11
  spec.email = ["jamespaulmoriarty@gmail.com"]
11
- spec.summary = %q{Lisp Interpreter in Ruby.}
12
- spec.description = ""
13
- spec.homepage = ""
12
+ spec.summary = %q{Lisp interpreter}
13
+ spec.description = "Minimal Lisp interpreter using 75LOC and only standard libraries excluding the REPL. Inspired by Lis.py."
14
+ spec.homepage = "https://github.com/jamesmoriarty/lisp"
14
15
  spec.license = "MIT"
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0")
@@ -19,7 +20,8 @@ Gem::Specification.new do |spec|
19
20
  spec.require_paths = ["lib"]
20
21
 
21
22
  spec.add_dependency "coolline"
22
- spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_dependency "coderay"
24
+ spec.add_development_dependency "bundler"
23
25
  spec.add_development_dependency "rake"
24
- spec.add_development_dependency "pry"
26
+ spec.add_development_dependency "minitest", "> 5"
25
27
  end
data/test/lisp_test.rb ADDED
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+
4
+ Dir[File.expand_path(File.join(File.dirname(__FILE__), 'support', '*.rb'))].each { |file| require file }
5
+
6
+ require "lisp"
7
+ require "minitest/autorun"
8
+
9
+ class TestLisp < MiniTest::Unit::TestCase
10
+
11
+ # parser
12
+
13
+ def test_tokenize
14
+ assert_equal ["(", "+", "1", "1", ")"], Lisp.tokenize("(+ 1 1)")
15
+ end
16
+
17
+ def test_parse_open
18
+ assert_raises(RuntimeError) { Lisp.parse(Lisp.tokenize("(")) }
19
+ end
20
+
21
+ def test_parse_close
22
+ assert_raises(RuntimeError) { Lisp.parse(Lisp.tokenize(")")) }
23
+ end
24
+
25
+ # ast
26
+
27
+ def test_ast_nested
28
+ assert_equal [:*, 2, [:+, 1, 0]], Lisp.parse(Lisp.tokenize("(* 2 (+ 1 0) )"))
29
+ end
30
+
31
+ def test_ast_call
32
+ assert_equal [:lambda, [:r], [:*, 3.141592653, [:*, :r, :r]]],
33
+ Lisp.parse(Lisp.tokenize("(lambda (r) (* 3.141592653 (* r r)))"))
34
+ end
35
+
36
+ # execution
37
+
38
+ def test_execution_return
39
+ assert_equal 1, Lisp.execute(1)
40
+ end
41
+
42
+ def test_execution_reduce
43
+ assert_equal 2, Lisp.execute([:*, 2, [:+, 1, 0]])
44
+ end
45
+
46
+ def test_eval
47
+ assert_equal 2, Lisp.eval("(* 2 (+ 1 0) )")
48
+ end
49
+
50
+ def test_define
51
+ assert_equal 6.283185306, Lisp.eval(<<-eos)
52
+ (begin
53
+ (define pi 3.141592653)
54
+ (* pi 2))
55
+ eos
56
+ end
57
+
58
+ def test_if_cont
59
+ assert_equal 2, Lisp.eval("(if(== 1 2) 1 2)")
60
+ end
61
+
62
+ def test_if_alt
63
+ assert_equal 1, Lisp.eval("(if(!= 1 2) 1 2)")
64
+ end
65
+
66
+ def test_set!
67
+ assert_raises(RuntimeError) { Lisp.eval("(set! foo 0)") }
68
+ end
69
+
70
+ def test_begin
71
+ assert_equal 4, Lisp.eval(<<-eos)
72
+ (begin
73
+ (define x 1)
74
+ (set! x (+ x 1)) (* x 2))
75
+ eos
76
+ end
77
+
78
+ def test_lambda
79
+ assert_equal 28.274333877, Lisp.eval(<<-eos)
80
+ (begin
81
+ (define area
82
+ (lambda (r)
83
+ (* 3.141592653 (* r r))))
84
+ (area 3))
85
+ eos
86
+ end
87
+
88
+ def test_lambda_no_args
89
+ assert_equal 42, Lisp.eval(<<-eos)
90
+ (begin
91
+ (define test
92
+ (lambda () 42))
93
+ (test))
94
+ eos
95
+ end
96
+
97
+ def test_lambda_call_self
98
+ assert_equal 3628800, Lisp.eval(<<-eos)
99
+ (begin
100
+ (define fact
101
+ (lambda (n)
102
+ (if (<= n 1)
103
+ 1
104
+ (* n (fact (- n 1))))))
105
+ (fact 10))
106
+ eos
107
+ end
108
+
109
+ def test_lambda_call_arg
110
+ assert_equal 40, Lisp.eval(<<-eos)
111
+ (begin
112
+ (define twice (lambda (x) (* 2 x)))
113
+ (define repeat (lambda (f) (lambda (x) (f (f x)))))
114
+ ((repeat twice) 10)))
115
+ eos
116
+ end
117
+
118
+ def test_program
119
+ assert_equal 2, Lisp.eval(<<-eos)
120
+ (begin
121
+ (define incf
122
+ (lambda (x)
123
+ (set! x (+ x 1))))
124
+ (define one 1)
125
+ (incf one))
126
+ eos
127
+ end
128
+
129
+ def test_repl
130
+ skip if ENV['CI']
131
+
132
+ pid = Process.pid
133
+ subject = Lisp::REPL.new
134
+ thread = Thread.new do
135
+ sleep 1
136
+ Process.kill("INT", pid)
137
+ thread.join
138
+ end
139
+
140
+ assert_output("ctrl-c to exit\n") do
141
+ subject.run
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,5 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.add_filter 'vendor'
4
+ SimpleCov.add_filter 'test'
5
+ SimpleCov.start
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lisp
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Moriarty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-23 00:00:00.000000000 Z
11
+ date: 2021-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coolline
@@ -25,21 +25,21 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: coderay
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.6'
34
- type: :development
33
+ version: '0'
34
+ type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.6'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: pry
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -66,26 +66,44 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: ''
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">"
74
+ - !ruby/object:Gem::Version
75
+ version: '5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">"
81
+ - !ruby/object:Gem::Version
82
+ version: '5'
83
+ description: Minimal Lisp interpreter using 75LOC and only standard libraries excluding
84
+ the REPL. Inspired by Lis.py.
70
85
  email:
71
86
  - jamespaulmoriarty@gmail.com
72
87
  executables:
73
- - lisp-rb
88
+ - lisp-repl
74
89
  extensions: []
75
90
  extra_rdoc_files: []
76
91
  files:
92
+ - ".github/workflows/ci.yaml"
77
93
  - ".gitignore"
78
94
  - Gemfile
79
95
  - LICENSE.txt
80
96
  - README.md
81
97
  - Rakefile
82
- - bin/lisp-rb
98
+ - bin/lisp-repl
83
99
  - lib/lisp.rb
100
+ - lib/lisp/interpreter.rb
84
101
  - lib/lisp/repl.rb
85
102
  - lib/lisp/version.rb
86
103
  - lisp.gemspec
87
- - test/test_lisp.rb
88
- homepage: ''
104
+ - test/lisp_test.rb
105
+ - test/support/simplecov.rb
106
+ homepage: https://github.com/jamesmoriarty/lisp
89
107
  licenses:
90
108
  - MIT
91
109
  metadata: {}
@@ -104,10 +122,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
122
  - !ruby/object:Gem::Version
105
123
  version: '0'
106
124
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.2.2
125
+ rubygems_version: 3.0.3
109
126
  signing_key:
110
127
  specification_version: 4
111
- summary: Lisp Interpreter in Ruby.
128
+ summary: Lisp interpreter
112
129
  test_files:
113
- - test/test_lisp.rb
130
+ - test/lisp_test.rb
131
+ - test/support/simplecov.rb
data/test/test_lisp.rb DELETED
@@ -1,65 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require "bundler/setup"
3
- require "codeclimate-test-reporter"
4
- CodeClimate::TestReporter.start
5
- require "minitest/autorun"
6
- require "pry"
7
-
8
- require_relative "../lib/lisp"
9
-
10
- class TestLisp < MiniTest::Unit::TestCase
11
-
12
- # parser
13
-
14
- def test_tokenize
15
- assert_equal ["(", "+", "1", "1", ")"], Lisp.tokenize("(+ 1 1)")
16
- end
17
-
18
- def test_parse
19
- assert_raises(RuntimeError) { Lisp.parse(Lisp.tokenize("(")) }
20
- assert_raises(RuntimeError) { Lisp.parse(Lisp.tokenize(")")) }
21
- end
22
-
23
- # representation
24
-
25
- def test_representation
26
- assert_equal [:*, 2, [:+, 1, 0]], Lisp.parse(Lisp.tokenize("(* 2 (+ 1 0) )"))
27
- assert_equal [:lambda, [:r], [:*, 3.141592653, [:*, :r, :r]]], Lisp.parse(Lisp.tokenize("(lambda (r) (* 3.141592653 (* r r)))"))
28
- end
29
-
30
- # execution
31
-
32
- def test_execution
33
- assert_equal 1, Lisp.execute(1)
34
- assert_equal 2, Lisp.execute([:*, 2, [:+, 1, 0]])
35
- end
36
-
37
- def test_eval
38
- assert_equal 2, Lisp.eval("(* 2 (+ 1 0) )")
39
- end
40
-
41
- def test_define
42
- Lisp.eval("(define pi 3.141592653)")
43
- assert_equal 6.283185306, Lisp.eval("(* pi 2)")
44
- end
45
-
46
- def test_if
47
- assert_equal 2, Lisp.eval("(if(== 1 2) 1 2)")
48
- assert_equal 1, Lisp.eval("(if(!= 1 2) 1 2)")
49
- end
50
-
51
- def test_set!
52
- assert_raises(RuntimeError) { Lisp.eval("(set! foo 0)") }
53
- end
54
-
55
- def test_begin
56
- assert_equal 4, Lisp.eval("(begin (define x 1) (set! x (+ x 1)) (* x 2))")
57
- end
58
-
59
- def test_lambda
60
- Lisp.eval("(define area (lambda (r) (* 3.141592653 (* r r))))")
61
- assert_equal 28.274333877, Lisp.eval("(area 3)")
62
- Lisp.eval("(define fact (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1))))))")
63
- assert_equal 3628800, Lisp.eval("(fact 10)")
64
- end
65
- end