lisp 1.5.0 → 1.5.1

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