lisp 1.3.0 → 1.5.2

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 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