skeem 0.2.14 → 0.2.15

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
2
  SHA256:
3
- metadata.gz: 4e35fb6742873b7c49a13e95be6143ae1a5cad7826f20aec0a02ba8dd98fa723
4
- data.tar.gz: 7427071d91fa6578d37122bd953822e263f6eeba314d3d52bc5afd279052f08f
3
+ metadata.gz: 182cf920c536bb07dd813c34eae74af24181813a9d96fdd39c786cc28043f135
4
+ data.tar.gz: ba4cf5ce2df8d1708f3504e57a14b62734146f3c8a47043cf2d5ffdf591e35d6
5
5
  SHA512:
6
- metadata.gz: 6f7229bba2d1cdffd83830124711b024452f82e4f3ba57219c476a4a6b07a67f3c84c13b7de2a22442f65ad82e7b414fcb429d3997047135f6e2105b2c42dece
7
- data.tar.gz: 712805a13cff2128f340a0f75288ee81528e80114cac2815630e839c2e3c87c78efd5298a40bd47345edced3c597979a6be69b033db19478787da9f34a48af28
6
+ metadata.gz: bd03dfab05470ee167464113844c3a8b0b3174f58cd4607034f417218b91ec024e26aff941ac78e750be30ff216d18be97171b030c3f3055803443f421ad6c19
7
+ data.tar.gz: 2cd279dca2e9202e6a924373a01c1a49e493ea2379131284639b07977714c72df751574a8252231d15182dc6b23d55206aaa11be062502b4840a5d9a27143199
@@ -1,5 +1,22 @@
1
+ ## [0.2.15] - 2019-07-02
2
+ - Added a basic command-line and console interface for Skeem interpreter.
3
+ - Added procedures: `display!`, `newline`, `make-list`
4
+
5
+ ### Added
6
+ - `bin/skeem` The CLI and REPL console implementation for Skeem
7
+ - `bin/cubic.skm`: A sample defining a procedure that computes the cube of a number.
8
+ - `bin/hello-world.skm`: The initiatic programming example
9
+
10
+ ### Changed
11
+ - File `primitive_builder.rb` Implementation of primitive procedures `newline`, `make-list`
12
+ - File `base.skm` Added implementation of `newline` procedure.
13
+ - File `README.md` vastly reorganized and introducing the new command line.
14
+
15
+ ### Removed
16
+ - Bundler-generated files `bin/console`, `bin/setup`
17
+
1
18
  ## [0.2.14] - 2019-06-29
2
- - Added derived expression ´do´ as an imperative iteration form.
19
+ - Added derived expression `do` as an imperative iteration form.
3
20
  - Added procedures: `vector-set!`
4
21
 
5
22
  ### Added
data/README.md CHANGED
@@ -26,23 +26,73 @@ Or install it yourself as:
26
26
  $ gem install skeem
27
27
 
28
28
 
29
- The __Skeem__ project has started recently and at this stage, the gem supports a small Scheme subset.
29
+ The __Skeem__ project is WIP and currently the gem supports a subset of the __Scheme__ language.
30
+ If you're not familiar to Scheme, the section [About Scheme](#about-scheme) contains a number of interesting pointers.
30
31
 
31
- ## About Scheme
32
32
 
33
- The Scheme programming language is a Lisp dialect that supports multiple paradigms, including functional programming and imperative programming.
33
+ ## Usage
34
+ Once the gem is installed, the `skeem` executable can be used.
35
+ It allows to run the interpreter from the command line.
34
36
 
35
- ### Resources on Scheme
36
- Here are a few pointers for the Scheme programming language:
37
- - Wikipedia article on [Scheme](https://en.m.wikipedia.org/wiki/Scheme_\(programming_language\))
38
- - Latest official Scheme standard: [R7RS](https://bitbucket.org/cowan/r7rs-wg1-infra/src/default/R7RSHomePage.md)
39
- #### Online tutorials and books:
40
- - [The Scheme Programming Language, 4th Edition](https://www.scheme.com/tspl4/) by Kent Dybvig. A complete, introductory textbook on Scheme based on the older R5RS standard.
41
- - [Teach Yourself Scheme in Fixnum Days](http://ds26gte.github.io/tyscheme/index.html) by Dorai Sitaram
42
- - [Yet Another Scheme Tutorial](http://www.shido.info/lisp/idx_scm_e.html) by Shido Takafumi
43
- - [An Introduction to Scheme and its Implementation](http://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v14/schintro_toc.html) by Paul R. Wilson
37
+ ### Launching a REPL session
38
+ To start a REPL (Read-Eval-Print-Loop) session, just type:
39
+ ```
40
+ skeem
41
+ ```
44
42
 
45
- ## Usage
43
+ Skeem displays a greeting, a prompt and then waits for your input:
44
+ ```
45
+ Welcome to Skeem 0.2.15.
46
+ >
47
+ ```
48
+
49
+ Now that we know that `Skeem` is well alive, let's kick it...
50
+ We begin with the ritual 'Hello world' example, by typing after the __>__ prompt:
51
+ ```
52
+ (display "Hello, world")
53
+ ```
54
+
55
+ Skeem then replies:
56
+ ```
57
+ Hello, world
58
+ Skeem::SkmUndefined
59
+ ```
60
+
61
+ This works as expected except, maybe, for the last line. It can be easily explained if one knows
62
+ that the return value of the `display` procedure is undefined in standard Scheme.
63
+ Internally Skeem, implements such undefined result as a `Skeem::Undefined`instance.
64
+
65
+ To give some taste of things, here is an excerpt from a REPL session:
66
+ ```
67
+ > (+ 4 (* 5 6))
68
+ 34
69
+ > (define x 6)
70
+ 6
71
+ > (+ (* 5 x x) (* 4 x) 3)
72
+ 207
73
+ > (/ 21 5)
74
+ 21/5
75
+ > (/ 21.0 5)
76
+ 21/5
77
+ ```
78
+
79
+ #### Terminating a REPL session
80
+ To exit a REPL session, call the `exit` procedure as follows:
81
+ ```
82
+ (exit)
83
+ ```
84
+
85
+ ### Running a Skeem file
86
+ To run a Scheme file:
87
+
88
+ ```
89
+ skeem path/to/some-file.skm
90
+ ```
91
+
92
+ By the way, the `/bin` folder of the `skeem` gem contains a couple of Skeem sample files.
93
+
94
+ ## Embed Skeem in your Ruby app
95
+ This is the third way for Rubyists to interact with Skeem by integrating it directly in their Ruby code.
46
96
 
47
97
  ### Example 1 (Variable definition)
48
98
 
@@ -195,6 +245,51 @@ Here are a few pointers for the Scheme programming language:
195
245
  - Iteration (`do`)
196
246
  - Control procedures
197
247
 
248
+ ### Standard library
249
+ This section lists the procedures following closely the official [Revised7 Report on the Algorithmic Language](https://bitbucket.org/cowan/r7rs/src/draft-10/rnrs/r7rs.pdf) standard.
250
+
251
+ #### Equivalence predicates
252
+ * `eqv?`, `equal?`
253
+
254
+ #### Boolean procedures
255
+ * `boolean?`, `boolean=?`, `and`, `or`, `not`
256
+
257
+ #### Character procedures
258
+ * `char?` `char->integer`, `char=?`, `char<?`, `char>?`,`char<=?`, `char>=?`
259
+
260
+ #### Numerical operations
261
+ * Number-level: `number?`, `complex?`, `real?`, `rational?`, `integer?`, `zero?`,
262
+ `exact?`, `inexact?`, `exact-integer?` , `+`, `-`, `*`, `/`, `=`, `square`, `number->string`
263
+ * Real-level: `positive?`, `negative?`, `<`, `>`, `<=`, `>=`, `abs`, `max`, `min`,
264
+ `floor/`, `floor-quotient`, `floor-remainder`, `truncate/`, `truncate-quotient`,
265
+ `truncate-remainder`, `quotient`, `remainder`, `modulo`, `gcd`, `lcm`, `numerator`,
266
+ `denominator`, `floor`, `ceiling`, `truncate`, `round`
267
+ * Integer-level: `even?`, `odd?`, `integer->char`
268
+
269
+ #### List procedures
270
+ * `list?`, `null?`, `pair?`, `append`, `car`, `cdr`, `caar`, `cadr`, `cdar`, `cddr`,
271
+ `cons`, `make-list`, `length`, `list`, `list-copy`, `list->vector`, `reverse`,
272
+ `set-car!`, `set-cdr!`, `assq`, `assv`
273
+
274
+ #### String procedures
275
+ * `string?`, `string=?`, `string`, `make-string`, `string-append`, `string-length`, `string->symbol`
276
+
277
+ #### Symbol procedures
278
+ * `symbol?`, `symbol=?`, `symbol->string`
279
+
280
+ #### Vector procedures
281
+ * `vector?`, `make-vector`, `vector`, `vector-length`, `vector-set!`, `vector->list`
282
+
283
+ #### Control procedures
284
+ * `procedure?`, `apply`, `map`
285
+
286
+ #### Input/output procedures
287
+ * `display`, `newline`
288
+
289
+ #### Non-standard procedures
290
+ * `assert`
291
+
292
+
198
293
  ### Standard syntactic forms
199
294
  #### define
200
295
  __Purpose:__ Create a new variable and bind an expression/value to it.
@@ -254,56 +349,29 @@ __Purpose:__ Define one or more variable local to the block.
254
349
  __Syntax:__
255
350
  * (let* (<binding_spec\*\>) <body\>)
256
351
 
257
- ### Standard library
258
- This section lists the implemented standard procedures
259
-
260
- #### Equivalence predicates
261
- * `eqv?`, `equal?`
262
-
263
- #### Boolean procedures
264
- * `boolean?`, `boolean=?`, `and`, `or`, `not`
265
-
266
- #### Character procedures
267
- * `char?` `char->integer`, `char=?`, `char<?`, `char>?`,`char<=?`, `char>=?`
268
-
269
- #### Numerical operations
270
- * Number-level: `number?`, `complex?`, `real?`, `rational?`, `integer?`, `zero?`, `exact?`, `inexact?`, `exact-integer?` , `+`, `-`, `*`, `/`,
271
- `=`, `square`, `number->string`
272
- * Real-level: `positive?`, `negative?`, `<`, `>`, `<=`, `>=`, `abs`, `max`, `min`, `floor/`, `floor-quotient`, `floor-remainder`, `truncate/`, `truncate-quotient`,
273
- `truncate-remainder`, `quotient`, `remainder`, `modulo`, `gcd`, `lcm`, `numerator`, `denominator`, `floor`, `ceiling`, `truncate`, `round`
274
- * Integer-level: `even?`, `odd?`, `integer->char`
275
-
276
- #### List procedures
277
- * `list?`, `null?`, `pair?`, `append`, `car`, `cdr`, `caar`, `cadr`, `cdar`, `cddr`, `cons`, `length`, `list`, `list-copy`, `list->vector`, `reverse`, `set-car!`, `set-cdr!`
278
- , `assq`, `assv`
279
-
280
- #### String procedures
281
- * `string?`, `string=?`, `string`, `make-string`, `string-append`, `string-length`, `string->symbol`
282
352
 
283
- #### Symbol procedures
284
- * `symbol?`, `symbol=?`, `symbol->string`
285
-
286
- #### Vector procedures
287
- * `vector?`, `make-vector`, `vector`, `vector-length`, `vector-set!`, `vector->list`
288
-
289
- #### Control procedures
290
- * `procedure?`, `apply`, `map`
291
-
292
- #### Input/output procedures
293
- * `newline`
294
-
295
- #### Special procedures
296
- * `assert`
297
-
298
- Roadmap:
299
- - Extend language support
300
- - Implement REPL
353
+ ## Roadmap
301
354
  - Implement an equivalent of [lis.py](http://www.norvig.com/lispy.html)
302
355
  - Implement an equivalent of [lispy](http://norvig.com/lispy2.html)
303
356
  - Make it pass the test suite
304
357
  - Extend the language in order to support [Minikanren](https://github.com/TheReasonedSchemer2ndEd/CodeFromTheReasonedSchemer2ndEd)
305
358
  - Make it pass all examples from the [Reasoned Schemer](https://mitpress.mit.edu/books/reasoned-schemer-second-edition) book.
306
359
 
360
+ ## About Scheme
361
+
362
+ The Scheme programming language is a Lisp dialect that supports multiple paradigms, including functional programming and imperative programming.
363
+
364
+ ### Resources on Scheme
365
+ Here are a few pointers for the Scheme programming language:
366
+ - Wikipedia article on [Scheme](https://en.m.wikipedia.org/wiki/Scheme_\(programming_language\))
367
+ - Latest official Scheme standard: [R7RS](https://bitbucket.org/cowan/r7rs-wg1-infra/src/default/R7RSHomePage.md)
368
+ #### Online tutorials and books:
369
+ - [The Scheme Programming Language, 4th Edition](https://www.scheme.com/tspl4/) by Kent Dybvig. A complete, introductory textbook on Scheme based on the older R5RS standard.
370
+ - [Teach Yourself Scheme in Fixnum Days](http://ds26gte.github.io/tyscheme/index.html) by Dorai Sitaram
371
+ - [Yet Another Scheme Tutorial](http://www.shido.info/lisp/idx_scm_e.html) by Shido Takafumi
372
+ - [An Introduction to Scheme and its Implementation](http://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v14/schintro_toc.html) by Paul R. Wilson
373
+
374
+
307
375
  ## Other Scheme implementations in Ruby
308
376
  __Skeem__ isn't the sole implementation of the Scheme language in Ruby.
309
377
  Here are a few other ones:
@@ -0,0 +1,4 @@
1
+ (define cubic
2
+ (lambda (x)
3
+ (* x x x)))
4
+ (cubic 3) ; => 27
@@ -0,0 +1 @@
1
+ (display "Hello, world")
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'skeem'
4
+
5
+ class SkeemREPL
6
+ attr_reader :interpreter
7
+
8
+ def initialize()
9
+ @interpreter = Skeem::Interpreter.new
10
+ end
11
+
12
+ def run_session
13
+ puts "Welcome to Skeem #{Skeem::VERSION}."
14
+ loop do
15
+ print '> '
16
+ input = gets.chomp.strip
17
+ break if input == '(quit)' || input == '(exit)'
18
+ process_input(input)
19
+ end
20
+ end
21
+
22
+ def run_file(aFilename)
23
+ if File.exist?(aFilename)
24
+ valid_fname = aFilename
25
+ else # Retry by adding extension...
26
+ if File.extname(aFilename).empty?
27
+ if File.exist?(aFilename + '.skm')
28
+ valid_fname = aFilename + '.skm'
29
+ elsif File.exist?(aFilename + '.scm')
30
+ valid_fname = aFilename + '.scm'
31
+ else
32
+ valid_fname = nil
33
+ end
34
+ end
35
+ end
36
+
37
+ raise ScriptError, "No such file -- #{aFilename}" unless valid_fname
38
+
39
+ source_code = File.read(valid_fname)
40
+ process_input(source_code)
41
+ end
42
+
43
+ def process_input(input)
44
+ begin
45
+ ptree = interpreter.parse(input)
46
+ rescue StandardError => exc
47
+ $stderr.puts exc.message
48
+ return
49
+ end
50
+
51
+ raw_result = ptree.root.evaluate(interpreter.runtime)
52
+ result = raw_result.kind_of?(Skeem::SkmPair) ? raw_result.last : raw_result
53
+ if result.kind_of?(Skeem::SkmUndefined)
54
+ puts "\n#{result.class}"
55
+ elsif result.respond_to?(:value)
56
+ puts result.value
57
+ else
58
+ puts result.inspect
59
+ end
60
+ end
61
+ end # class
62
+
63
+ ########################################
64
+ # Entry point
65
+ ########################################
66
+ djinn = SkeemREPL.new
67
+
68
+ if ARGV.empty?
69
+ djinn.run_session
70
+ else
71
+ djinn.run_file(ARGV[0])
72
+ end
@@ -130,6 +130,7 @@ module Skeem
130
130
  create_cons(aRuntime)
131
131
  create_car(aRuntime)
132
132
  create_cdr(aRuntime)
133
+ create_make_list(aRuntime)
133
134
  create_length(aRuntime)
134
135
  create_list2vector(aRuntime)
135
136
  create_append(aRuntime)
@@ -158,7 +159,7 @@ module Skeem
158
159
  end
159
160
 
160
161
  def add_io_procedures(aRuntime)(aRuntime)
161
- create_newline(aRuntime)
162
+ create_display(aRuntime)
162
163
  end
163
164
 
164
165
  def add_special_procedures(aRuntime)
@@ -670,12 +671,12 @@ module Skeem
670
671
  def create_make_string(aRuntime)
671
672
  primitive = ->(runtime, count_arg, arglist) do
672
673
  count = count_arg
673
- check_argtype(count, SkmInteger, 'integer', 'make_string')
674
+ check_argtype(count, SkmInteger, 'integer', 'make-string')
674
675
  if arglist.empty?
675
676
  filler = SkmChar.create(rand(0xff).chr)
676
677
  else
677
678
  filler = arglist.first
678
- check_argtype(filler, SkmChar, 'char', 'make_string')
679
+ check_argtype(filler, SkmChar, 'char', 'make-string')
679
680
  end
680
681
  string(filler.value.to_s * count.value)
681
682
  end
@@ -774,6 +775,22 @@ module Skeem
774
775
 
775
776
  define_primitive_proc(aRuntime, 'cons', binary, primitive)
776
777
  end
778
+
779
+ def create_make_list(aRuntime)
780
+ primitive = ->(runtime, count_arg, arglist) do
781
+ count = count_arg
782
+ check_argtype(count, SkmInteger, 'integer', 'make-list')
783
+ if arglist.empty?
784
+ filler = SkmUndefined.instance
785
+ else
786
+ filler = arglist.first
787
+ end
788
+ arr = Array.new(count.value, filler)
789
+ SkmPair.create_from_a(arr)
790
+ end
791
+
792
+ define_primitive_proc(aRuntime, 'make-list', one_or_two, primitive)
793
+ end
777
794
 
778
795
  def create_length(aRuntime)
779
796
  primitive = ->(_runtime, arg_evaluated) do
@@ -1093,14 +1110,15 @@ module Skeem
1093
1110
 
1094
1111
  define_primitive_proc(aRuntime, 'map', one_or_more, primitive)
1095
1112
  end
1096
-
1097
- def create_newline(aRuntime)
1098
- primitive = ->(runtime) do
1113
+
1114
+ def create_display(aRuntime)
1115
+ primitive = ->(runtime, arg_evaluated) do
1099
1116
  # @TODO: make output stream configurable
1100
- print "\n"
1117
+ print arg_evaluated.value.to_s
1118
+ SkmUndefined.instance
1101
1119
  end
1102
-
1103
- define_primitive_proc(aRuntime, 'newline', nullary, primitive)
1120
+
1121
+ define_primitive_proc(aRuntime, 'display', unary, primitive)
1104
1122
  end
1105
1123
 
1106
1124
  def create_test_assert(aRuntime)
@@ -140,6 +140,10 @@
140
140
 
141
141
  (define symbol=? string=?)
142
142
 
143
+ (define newline
144
+ (lambda ()
145
+ (display #\newline)))
146
+
143
147
  ;; Test the equivalence (with eqv? predicate) between an expected value and
144
148
  ;; an expression
145
149
  ;; (test-eqv expected test-expr)
@@ -1,3 +1,3 @@
1
1
  module Skeem
2
- VERSION = '0.2.14'.freeze
2
+ VERSION = '0.2.15'.freeze
3
3
  end
@@ -16,7 +16,7 @@ module PkgExtending
16
16
  'LICENSE.txt',
17
17
  'README.md',
18
18
  'skeem.gemspec',
19
- 'bin/*.rb',
19
+ 'bin/*.*',
20
20
  'lib/*.*',
21
21
  'lib/**/*.rb',
22
22
  'lib/**/*.skm',
@@ -51,6 +51,7 @@ SUMMARY
51
51
  spec.license = 'MIT'
52
52
 
53
53
  spec.bindir = 'bin'
54
+ spec.executables << 'skeem'
54
55
  spec.require_paths = ['lib']
55
56
  PkgExtending.pkg_files(spec)
56
57
  PkgExtending.pkg_documentation(spec)
@@ -836,6 +836,16 @@ SKEEM
836
836
  compare_to_predicted(checks)
837
837
  end
838
838
  end # context
839
+
840
+ context 'Input/output:' do
841
+ it 'should implement the newline procedure' do
842
+ default_stdout = $stdout
843
+ $stdout = StringIO.new()
844
+ subject.run('(newline) (newline) (newline)')
845
+ expect($stdout.string).to match(/\n\n\n$/)
846
+ $stdout = default_stdout
847
+ end
848
+ end # context
839
849
 
840
850
  context 'Second-order functions' do
841
851
  it 'should implement lambda that calls second-order function' do
@@ -623,6 +623,14 @@ SKEEM
623
623
  example = "(cdr '())" # => error
624
624
  expect { subject.run(example) }.to raise_error(StandardError)
625
625
  end
626
+
627
+ it 'should implement the length procedure' do
628
+ example = '(make-list 2 3)'
629
+ result = subject.run(example)
630
+ expect(result).to be_list
631
+ expect(result.length).to eq(2)
632
+ expect(result.to_a).to eq([3, 3])
633
+ end
626
634
 
627
635
  it 'should implement the length procedure' do
628
636
  checks = [
@@ -908,7 +916,7 @@ SKEEM
908
916
  #(0 ("Sue" "Sue") "Anna")
909
917
  result = subject.run(source)
910
918
  expect(result).to be_kind_of(SkmVector)
911
- expectation = [SkmInteger.create(0),
919
+ expectation = [SkmInteger.create(0),
912
920
  SkmPair.new(SkmString.create("Sue"), SkmPair.new(SkmString.create("Sue"), SkmEmptyList.instance)),
913
921
  SkmString.create("Anna") ]
914
922
  expect(result).to eq(expectation)
@@ -965,11 +973,11 @@ SKEEM
965
973
  end # context
966
974
 
967
975
  context 'IO procedures:' do
968
- it 'should implement the newline procedure' do
976
+ it 'should implement the display procedure' do
969
977
  default_stdout = $stdout
970
978
  $stdout = StringIO.new()
971
- subject.run('(newline) (newline) (newline)')
972
- expect($stdout.string).to match(/\n\n\n$/)
979
+ subject.run('(display "Hello")')
980
+ expect($stdout.string).to eq('Hello')
973
981
  $stdout = default_stdout
974
982
  end
975
983
  end # context
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skeem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.14
4
+ version: 0.2.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-29 00:00:00.000000000 Z
11
+ date: 2019-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -69,7 +69,8 @@ dependencies:
69
69
  description: " Skeem is a Scheme language interpreter implemented in Ruby.\n"
70
70
  email:
71
71
  - famished.tiger@yahoo.com
72
- executables: []
72
+ executables:
73
+ - skeem
73
74
  extensions: []
74
75
  extra_rdoc_files:
75
76
  - README.md
@@ -83,6 +84,9 @@ files:
83
84
  - README.md
84
85
  - Rakefile
85
86
  - appveyor.yml
87
+ - bin/cubic.skm
88
+ - bin/hello-world.skm
89
+ - bin/skeem
86
90
  - lib/skeem.rb
87
91
  - lib/skeem/datum_dsl.rb
88
92
  - lib/skeem/element_visitor.rb