lisp 1.5.0 → 1.5.1

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: 42a5f2b1b6e96db9ab76de11598d650aa99a4f4c
4
- data.tar.gz: 258c6c47e9dca2afd7ab5e7e9c265caadfe7fa8a
2
+ SHA256:
3
+ metadata.gz: 3140fcbe7a7a85548c0efa3d612b29cc3fdd0cb152f90c913c6c3814c8425b36
4
+ data.tar.gz: 2c48b33ebed20827bd71168ff5c3a54ee064682d3dc1abfaaf3a5679f7f92777
5
5
  SHA512:
6
- metadata.gz: a80b1fdda67cffb7e3a8ca1369a27b418b1d591efc460422a60dcc2196f24bd7919be6f40e068453d6c949c059f3d37a485cc04e74018f4d11e9b8b99d7e1a9f
7
- data.tar.gz: cd35640693b386066596e6dfc26433f088650170e817715a174ddaf018cdec9f421a2373f8a72a332da7b74412e57af8c300d8a94c271711cf278a0d39d226b8
6
+ metadata.gz: e642ce75f5b2aea99869cf57049c722dedb51afaff16d49d9108ef665bc500564589c848a64bdb9ca3822866a2e7c0ce74cfa59723d675608c9862600d3c2262
7
+ data.tar.gz: 0511e2a95f6bf7851f29ab4e46ce33f2a927deb9efd9e463ad819b836113b3d3953781adb1301e86d35a3634a7b8e04bd141cbe4839a0ac7bf182da03f524b15
@@ -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
@@ -2,3 +2,5 @@ Gemfile.lock
2
2
  env
3
3
  pkg
4
4
  coverage
5
+ doc
6
+ .yardoc
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- group :test do
4
- gem "simplecov"
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,9 +1,9 @@
1
1
  lisp
2
2
  ====
3
3
 
4
- ![Gem][1] ![Build Status][2]
4
+ ![Gem Version][3] ![Gem][1] ![Build Status][2]
5
5
 
6
- Lisp Interpreter in the Ruby Programming Language - 70 LOC. 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
8
  ```clojure
9
9
  $ lisp-repl
@@ -20,12 +20,36 @@ ctrl-c to exit
20
20
 
21
21
  Install
22
22
  -------
23
- ![Gem Version][3]
24
23
 
25
24
  ```
26
25
  gem install lisp
27
26
  ```
28
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
+
29
53
  Features
30
54
  --------
31
55
 
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
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
- atom token
29
- end
30
- end
31
-
32
- def self.atom token
33
- case token
34
- when /\d/
35
- token.to_f % 1 > 0 ? token.to_f : token.to_i
36
- else
37
- token.to_sym
38
- end
39
- end
40
-
41
- def self.execute expression, scope = global
42
- return scope.fetch(expression) { |var| raise "#{var} is undefined" } if expression.is_a? Symbol
43
- return expression unless expression.is_a? Array
44
-
45
- case expression[0]
46
- when :define
47
- _, var, expression = expression
48
- scope[var] = execute expression, scope
49
- when :lambda
50
- _, params, expression = expression
51
- lambda { |*args| execute expression, scope.merge(Hash[params.zip(args)]) }
52
- when :if
53
- _, test, consequent, alternative = expression
54
- expression = if execute test, scope then consequent else alternative end
55
- execute expression, scope
56
- when :set!
57
- _, var, expression = expression
58
- if scope.has_key?(var) then scope[var] = execute expression, scope else raise "#{var} is undefined" end
59
- when :begin
60
- _, *expression = expression
61
- expression.map { |expression| execute expression, scope }.last
62
- else
63
- function, *args = expression.map { |expression| execute expression, scope }
64
- function.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,5 +1,3 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  require "coolline"
4
2
  require "coderay"
5
3
 
data/lib/lisp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lisp
2
- VERSION = '1.5.0'.freeze
2
+ VERSION = '1.5.1'.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'
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require "bundler/setup"
3
3
 
4
- Dir[File.expand_path(File.join(File.dirname(__FILE__),'support', '*.rb'))].each { |file| require file }
4
+ Dir[File.expand_path(File.join(File.dirname(__FILE__), 'support', '*.rb'))].each { |file| require file }
5
5
 
6
6
  require "lisp"
7
7
  require "minitest/autorun"
@@ -29,7 +29,8 @@ class TestLisp < MiniTest::Unit::TestCase
29
29
  end
30
30
 
31
31
  def test_ast_call
32
- assert_equal [:lambda, [:r], [:*, 3.141592653, [:*, :r, :r]]], Lisp.parse(Lisp.tokenize("(lambda (r) (* 3.141592653 (* r r)))"))
32
+ assert_equal [:lambda, [:r], [:*, 3.141592653, [:*, :r, :r]]],
33
+ Lisp.parse(Lisp.tokenize("(lambda (r) (* 3.141592653 (* r r)))"))
33
34
  end
34
35
 
35
36
  # execution
@@ -126,6 +127,8 @@ class TestLisp < MiniTest::Unit::TestCase
126
127
  end
127
128
 
128
129
  def test_repl
130
+ skip if ENV['CI']
131
+
129
132
  pid = Process.pid
130
133
  subject = Lisp::REPL.new
131
134
  thread = Thread.new do
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.5.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Moriarty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-18 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
@@ -88,19 +88,20 @@ executables:
88
88
  extensions: []
89
89
  extra_rdoc_files: []
90
90
  files:
91
+ - ".github/workflows/ci.yaml"
91
92
  - ".gitignore"
92
- - ".travis.yml"
93
93
  - Gemfile
94
94
  - LICENSE.txt
95
95
  - README.md
96
96
  - Rakefile
97
97
  - bin/lisp-repl
98
98
  - lib/lisp.rb
99
+ - lib/lisp/interpreter.rb
99
100
  - lib/lisp/repl.rb
100
101
  - lib/lisp/version.rb
101
102
  - lisp.gemspec
103
+ - test/lisp_test.rb
102
104
  - test/support/simplecov.rb
103
- - test/test_lisp.rb
104
105
  homepage: ''
105
106
  licenses:
106
107
  - MIT
@@ -120,11 +121,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
121
  - !ruby/object:Gem::Version
121
122
  version: '0'
122
123
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.5.2.3
124
+ rubygems_version: 3.0.3
125
125
  signing_key:
126
126
  specification_version: 4
127
127
  summary: Lisp Interpreter in Ruby.
128
128
  test_files:
129
+ - test/lisp_test.rb
129
130
  - test/support/simplecov.rb
130
- - test/test_lisp.rb
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- sudo: false
2
-
3
- language: ruby
4
-
5
- rvm:
6
- - 2.3.8
7
-
8
- env:
9
- global:
10
- - CC_TEST_REPORTER_ID=0a4c13b71635c00cee43aba776853ade9404cc745c42977e25a5877a3e148527
11
-
12
- before_script:
13
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
14
- - chmod +x ./cc-test-reporter
15
- - ./cc-test-reporter before-build
16
- - gem install bundler -v 2.0.2
17
-
18
- after_script:
19
- - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT