skeem 0.2.14 → 0.2.15

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