skeem 0.2.14 → 0.2.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +451 -195
  3. data/.travis.yml +27 -0
  4. data/CHANGELOG.md +35 -1
  5. data/Gemfile +2 -0
  6. data/README.md +125 -56
  7. data/Rakefile +2 -0
  8. data/appveyor.yml +3 -4
  9. data/bin/cubic.skm +4 -0
  10. data/bin/hello-world.skm +1 -0
  11. data/bin/skeem +72 -0
  12. data/lib/skeem/datum_dsl.rb +40 -30
  13. data/lib/skeem/element_visitor.rb +5 -2
  14. data/lib/skeem/grammar.rb +88 -26
  15. data/lib/skeem/interpreter.rb +9 -7
  16. data/lib/skeem/parser.rb +6 -4
  17. data/lib/skeem/primitive/primitive_builder.rb +148 -122
  18. data/lib/skeem/primitive/primitive_procedure.rb +23 -25
  19. data/lib/skeem/runtime.rb +17 -15
  20. data/lib/skeem/s_expr_builder.rb +49 -117
  21. data/lib/skeem/s_expr_nodes.rb +147 -132
  22. data/lib/skeem/skeem_exception.rb +1 -0
  23. data/lib/skeem/skm_binding.rb +9 -11
  24. data/lib/skeem/skm_compound_datum.rb +9 -6
  25. data/lib/skeem/skm_element.rb +15 -13
  26. data/lib/skeem/skm_empty_list.rb +6 -4
  27. data/lib/skeem/skm_exception.rb +9 -0
  28. data/lib/skeem/skm_expression.rb +3 -1
  29. data/lib/skeem/skm_frame.rb +3 -2
  30. data/lib/skeem/skm_pair.rb +26 -18
  31. data/lib/skeem/skm_procedure_exec.rb +11 -6
  32. data/lib/skeem/skm_simple_datum.rb +23 -20
  33. data/lib/skeem/skm_unary_expression.rb +34 -37
  34. data/lib/skeem/standard/base.skm +4 -0
  35. data/lib/skeem/tokenizer.rb +38 -28
  36. data/lib/skeem/version.rb +3 -1
  37. data/lib/skeem.rb +2 -0
  38. data/skeem.gemspec +9 -6
  39. data/spec/skeem/add4.skm +4 -0
  40. data/spec/skeem/datum_dsl_spec.rb +13 -12
  41. data/spec/skeem/element_visitor_spec.rb +14 -10
  42. data/spec/skeem/interpreter_spec.rb +84 -44
  43. data/spec/skeem/lambda_spec.rb +13 -11
  44. data/spec/skeem/parser_spec.rb +23 -19
  45. data/spec/skeem/primitive/primitive_builder_spec.rb +65 -48
  46. data/spec/skeem/primitive/primitive_procedure_spec.rb +14 -12
  47. data/spec/skeem/runtime_spec.rb +20 -18
  48. data/spec/skeem/s_expr_nodes_spec.rb +8 -6
  49. data/spec/skeem/skm_compound_datum_spec.rb +12 -10
  50. data/spec/skeem/skm_element_spec.rb +7 -5
  51. data/spec/skeem/skm_empty_list_spec.rb +7 -5
  52. data/spec/skeem/skm_frame_spec.rb +5 -4
  53. data/spec/skeem/skm_pair_spec.rb +9 -8
  54. data/spec/skeem/skm_procedure_exec_spec.rb +2 -0
  55. data/spec/skeem/skm_simple_datum_spec.rb +24 -22
  56. data/spec/skeem/skm_unary_expression_spec.rb +11 -9
  57. data/spec/skeem/tokenizer_spec.rb +54 -43
  58. data/spec/skeem_spec.rb +2 -0
  59. data/spec/spec_helper.rb +15 -10
  60. metadata +18 -10
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skeem
2
4
  class SkmElementVisitor
3
5
  # Link to the root element to visit
@@ -12,6 +14,7 @@ module Skeem
12
14
  # @param aRoot [SkmElement] the parse tree to visit.
13
15
  def initialize(aRoot)
14
16
  raise StandardError if aRoot.nil?
17
+
15
18
  @root = aRoot
16
19
  @subscribers = []
17
20
  end
@@ -57,7 +60,6 @@ module Skeem
57
60
  broadcast(:after_empty_list, anEmptyList)
58
61
  end
59
62
 
60
-
61
63
  def visit_pair(aPair)
62
64
  broadcast(:before_pair, aPair)
63
65
  traverse_car_cdr(aPair)
@@ -110,8 +112,9 @@ module Skeem
110
112
  def broadcast(msg, *args)
111
113
  subscribers.each do |subscr|
112
114
  next unless subscr.respond_to?(msg) || subscr.respond_to?(:accept_all)
115
+
113
116
  subscr.send(msg, runtime, *args)
114
117
  end
115
118
  end
116
119
  end # class
117
- end # module
120
+ end # module
data/lib/skeem/grammar.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Grammar for Skeem (a subset of Scheme language)
2
4
  require 'rley' # Load the gem
3
5
 
@@ -7,11 +9,11 @@ module Skeem
7
9
  # Official Small Scheme grammar is available at:
8
10
  # https://bitbucket.org/cowan/r7rs/src/draft-10/rnrs/r7rs.pdf
9
11
  # Names of grammar elements are based on the R7RS documentation
10
- builder = Rley::Syntax::GrammarBuilder.new do
12
+ builder = Rley::grammar_builder do
11
13
  # Delimiters, separators...
12
14
  add_terminals('APOSTROPHE', 'COMMA', 'COMMA_AT_SIGN')
13
15
  add_terminals('GRAVE_ACCENT', 'LPAREN', 'RPAREN')
14
- add_terminals('PERIOD', 'ARROW')
16
+ add_terminals('PERIOD', 'UNDERSCORE', 'ARROW', 'ELLIPSIS')
15
17
  add_terminals('VECTOR_BEGIN')
16
18
 
17
19
  # Literal values...
@@ -19,9 +21,9 @@ module Skeem
19
21
  add_terminals('CHAR', 'STRING_LIT', 'IDENTIFIER')
20
22
 
21
23
  # Keywords...
22
- add_terminals('BEGIN', 'COND', 'DEFINE', 'DO', 'ELSE')
23
- add_terminals('IF', 'LAMBDA', 'LET', 'LET*')
24
- add_terminals('QUOTE', 'QUASIQUOTE', 'SET!')
24
+ add_terminals('BEGIN', 'COND', 'DEFINE', 'DEFINE-SYNTAX', 'DO')
25
+ add_terminals('ELSE', 'IF', 'INCLUDE', 'LAMBDA', 'LET', 'LET_STAR')
26
+ add_terminals('QUOTE', 'QUASIQUOTE', 'SET!', 'SYNTAX-RULES')
25
27
  add_terminals('UNQUOTE', 'UNQUOTE-SPLICING')
26
28
 
27
29
  rule('program' => 'cmd_or_def_plus').as 'main'
@@ -33,6 +35,7 @@ module Skeem
33
35
  rule 'command' => 'expression'
34
36
  rule('definition' => 'LPAREN DEFINE IDENTIFIER expression RPAREN').as 'definition'
35
37
  rule('definition' => 'LPAREN DEFINE LPAREN IDENTIFIER def_formals RPAREN body RPAREN').as 'alt_definition'
38
+ rule('definition' => 'syntax_definition')
36
39
  rule('definition' => 'LPAREN BEGIN definition_star RPAREN').as 'definitions_within_begin'
37
40
  rule('expression' => 'IDENTIFIER').as 'variable_reference'
38
41
  rule 'expression' => 'literal'
@@ -41,8 +44,9 @@ module Skeem
41
44
  rule 'expression' => 'conditional'
42
45
  rule 'expression' => 'assignment'
43
46
  rule 'expression' => 'derived_expression'
47
+ rule 'expression' => 'includer'
44
48
  rule 'literal' => 'quotation'
45
- rule 'literal' => 'self-evaluating'
49
+ rule 'literal' => 'self-evaluating'
46
50
  rule('quotation' => 'APOSTROPHE datum').as 'quotation_short'
47
51
  rule('quotation' => 'LPAREN QUOTE datum RPAREN').as 'quotation'
48
52
  rule 'self-evaluating' => 'BOOLEAN'
@@ -64,8 +68,8 @@ module Skeem
64
68
  rule('vector' => 'VECTOR_BEGIN datum_star RPAREN').as 'vector'
65
69
  rule('datum_plus' => 'datum_plus datum').as 'multiple_datums'
66
70
  rule('datum_plus' => 'datum').as 'last_datum'
67
- rule('datum_star' => 'datum_star datum').as 'datum_star'
68
- rule('datum_star' => []).as 'no_datum_yet'
71
+ rule('datum_star' => 'datum_star datum').as 'star_default'
72
+ rule('datum_star' => []).as 'star_base' ## 'no_datum_yet'
69
73
  rule 'symbol' => 'IDENTIFIER'
70
74
  rule('procedure_call' => 'LPAREN operator RPAREN').as 'proc_call_nullary'
71
75
  rule('procedure_call' => 'LPAREN operator operand_plus RPAREN').as 'proc_call_args'
@@ -79,16 +83,17 @@ module Skeem
79
83
  rule('formals' => 'LPAREN identifier_star RPAREN').as 'fixed_arity_formals'
80
84
  rule('formals' => 'IDENTIFIER').as 'variadic_formals'
81
85
  rule('formals' => 'LPAREN identifier_plus PERIOD IDENTIFIER RPAREN').as 'dotted_formals'
82
- rule('identifier_star' => 'identifier_star IDENTIFIER').as 'identifier_star'
83
- rule('identifier_star' => []).as 'no_identifier_yet'
86
+ rule('syntax_definition' => 'LPAREN DEFINE-SYNTAX keyword transformer_spec RPAREN').as 'syntax_definition'
87
+ rule('identifier_star' => 'identifier_star IDENTIFIER').as 'star_default'
88
+ rule('identifier_star' => []).as 'star_base' ## 'no_identifier_yet'
84
89
  rule('identifier_plus' => 'identifier_plus IDENTIFIER').as 'multiple_identifiers'
85
90
  rule('identifier_plus' => 'IDENTIFIER').as 'last_identifier'
86
91
  rule('body' => 'definition_star sequence').as 'body'
87
- rule('definition_star' => 'definition_star definition').as 'definition_star'
88
- rule('definition_star' => []).as 'no_definition_yet'
92
+ rule('definition_star' => 'definition_star definition').as 'star_default'
93
+ rule('definition_star' => []).as 'star_base' ## 'no_definition_yet'
89
94
  rule('sequence' => 'command_star expression').as 'sequence'
90
- rule('command_star' => 'command_star command').as 'multiple_commands'
91
- rule('command_star' => []).as 'no_command_yet'
95
+ rule('command_star' => 'command_star command').as 'star_default'
96
+ rule('command_star' => []).as 'star_base' ## 'no_command_yet'
92
97
  rule('conditional' => 'LPAREN IF test consequent alternate RPAREN').as 'conditional'
93
98
  rule 'test' => 'expression'
94
99
  rule 'consequent' => 'expression'
@@ -101,13 +106,15 @@ module Skeem
101
106
  rule('derived_expression' => 'LPAREN COND cond_clause_plus RPAREN').as 'cond_form'
102
107
  rule('derived_expression' => 'LPAREN COND cond_clause_star LPAREN ELSE sequence RPAREN RPAREN').as 'cond_else_form'
103
108
  rule('derived_expression' => 'LPAREN LET LPAREN binding_spec_star RPAREN body RPAREN').as 'short_let_form'
104
- rule('derived_expression' => 'LPAREN LET* LPAREN binding_spec_star RPAREN body RPAREN').as 'let_star_form'
109
+ # TODO: implement "named let"
110
+ rule('derived_expression' => 'LPAREN LET IDENTIFIER LPAREN binding_spec_star RPAREN body RPAREN') # .as 'named_form'
111
+ rule('derived_expression' => 'LPAREN LET_STAR LPAREN binding_spec_star RPAREN body RPAREN').as 'let_star_form'
105
112
 
106
- # As the R7RS grammar is too restrictive,
113
+ # As the R7RS grammar is too restrictive,
107
114
  # the next rule was made more general than its standard counterpart
108
115
  rule('derived_expression' => 'LPAREN BEGIN body RPAREN').as 'begin_expression'
109
116
  do_syntax = <<-END_SYNTAX
110
- LPAREN DO LPAREN iteration_spec_star RPAREN
117
+ LPAREN DO LPAREN iteration_spec_star RPAREN
111
118
  LPAREN test do_result RPAREN
112
119
  command_star RPAREN
113
120
  END_SYNTAX
@@ -115,25 +122,29 @@ END_SYNTAX
115
122
  rule 'derived_expression' => 'quasiquotation'
116
123
  rule('cond_clause_plus' => 'cond_clause_plus cond_clause').as 'multiple_cond_clauses'
117
124
  rule('cond_clause_plus' => 'cond_clause').as 'last_cond_clauses'
118
- rule('cond_clause_star' => 'cond_clause_star cond_clause').as 'cond_clauses_star'
119
- rule('cond_clause_star' => []).as 'last_cond_clauses_star'
125
+ rule('cond_clause_star' => 'cond_clause_star cond_clause').as 'star_default'
126
+ rule('cond_clause_star' => []).as 'star_base' ## 'last_cond_clauses_star'
120
127
  rule('cond_clause' => 'LPAREN test sequence RPAREN').as 'cond_clause'
121
128
  rule('cond_clause' => 'LPAREN test RPAREN')
122
129
  rule('cond_clause' => 'LPAREN test ARROW recipient RPAREN').as 'cond_arrow_clause'
123
130
  rule('recipient' => 'expression')
124
131
  rule('quasiquotation' => 'LPAREN QUASIQUOTE qq_template RPAREN').as 'quasiquotation'
125
132
  rule('quasiquotation' => 'GRAVE_ACCENT qq_template').as 'quasiquotation_short'
126
- rule('binding_spec_star' => 'binding_spec_star binding_spec').as 'multiple_binding_specs'
127
- rule('binding_spec_star' => []).as 'no_binding_spec_yet'
133
+ rule('binding_spec_star' => 'binding_spec_star binding_spec').as 'star_default'
134
+ rule('binding_spec_star' => []).as 'star_base' ## 'no_binding_spec_yet'
128
135
  rule('binding_spec' => 'LPAREN IDENTIFIER expression RPAREN').as 'binding_spec'
129
- rule('iteration_spec_star' => 'iteration_spec_star iteration_spec').as 'multiple_iter_specs'
130
- rule('iteration_spec_star' => []).as 'no_iter_spec_yet'
136
+ rule('iteration_spec_star' => 'iteration_spec_star iteration_spec').as 'star_default'
137
+ rule('iteration_spec_star' => []).as 'star_base' ## 'no_iter_spec_yet'
131
138
  rule('iteration_spec' => 'LPAREN IDENTIFIER init step RPAREN').as 'iteration_spec_long'
132
139
  rule('iteration_spec' => 'LPAREN IDENTIFIER init RPAREN').as 'iteration_spec_short'
133
140
  rule('init' => 'expression')
134
141
  rule('step' => 'expression')
135
142
  rule 'do_result' => 'sequence'
136
- rule('do_result' => []).as 'empty_do_result'
143
+ rule('do_result' => []).as 'star_base' ## 'empty_do_result'
144
+ rule('keyword' => 'IDENTIFIER')
145
+ rule('includer' => 'LPAREN INCLUDE string_plus RPAREN').as 'include'
146
+ rule('string_plus' => 'string_plus STRING_LIT').as 'multiple_string'
147
+ rule('string_plus' => 'STRING_LIT').as 'last_single_string'
137
148
  rule 'qq_template' => 'simple_datum'
138
149
  rule 'qq_template' => 'list_qq_template'
139
150
  rule 'qq_template' => 'vector_qq_template'
@@ -144,14 +155,65 @@ END_SYNTAX
144
155
  rule('vector_qq_template' => 'VECTOR_BEGIN qq_template_or_splice_star RPAREN').as 'vector_qq'
145
156
  rule('unquotation' => 'COMMA qq_template').as 'unquotation_short'
146
157
  rule 'unquotation' => 'LPAREN UNQUOTE qq_template RPAREN'
147
- rule('qq_template_or_splice_star' => 'qq_template_or_splice_star qq_template_or_splice').as 'multiple_template_splice'
148
- rule('qq_template_or_splice_star' => []).as 'no_template_splice_yet'
158
+ rule('qq_template_or_splice_star' => 'qq_template_or_splice_star qq_template_or_splice').as 'star_default'
159
+ rule('qq_template_or_splice_star' => []).as 'star_base' ## 'no_template_splice_yet'
149
160
  rule 'qq_template_or_splice_plus' => 'qq_template_or_splice_plus qq_template_or_splice'
150
161
  rule 'qq_template_or_splice_plus' => 'qq_template_or_splice'
151
162
  rule 'qq_template_or_splice' => 'qq_template'
152
163
  rule 'qq_template_or_splice' => 'splicing_unquotation'
153
164
  rule 'splicing_unquotation' => 'COMMA_AT_SIGN qq_template'
154
165
  rule 'splicing_unquotation' => 'LPAREN UNQUOTE-SPLICING qq_template RPAREN'
166
+ rule('transformer_spec' => 'LPAREN SYNTAX-RULES LPAREN identifier_star RPAREN syntax_rule_star RPAREN').as 'transformer_syntax'
167
+ rule('transformer_spec' => 'LPAREN SYNTAX-RULES IDENTIFIER LPAREN identifier_star RPAREN syntax_rule_star RPAREN')
168
+ rule('syntax_rule_star' => 'syntax_rule_star syntax_rule').as 'star_default'
169
+ rule('syntax_rule_star' => []).as 'star_base'
170
+ rule('syntax_rule' => 'LPAREN pattern template RPAREN').as 'syntax_rule'
171
+ rule('pattern' => 'pattern_identifier')
172
+ rule('pattern' => 'UNDERSCORE')
173
+ rule('pattern' => 'LPAREN pattern_star RPAREN')
174
+ rule('pattern' => 'LPAREN pattern_plus PERIOD pattern RPAREN')
175
+ rule('pattern' => 'LPAREN pattern_plus ELLIPSIS pattern_star RPAREN')
176
+ rule('pattern' => 'LPAREN pattern_plus ELLIPSIS pattern_star PERIOD pattern RPAREN')
177
+ rule('pattern' => 'VECTOR_BEGIN pattern_star RPAREN')
178
+ rule('pattern' => 'VECTOR_BEGIN pattern_plus ELLIPSIS pattern_star RPAREN')
179
+ rule('pattern' => 'pattern_datum')
180
+ rule('pattern_star' => 'pattern_star pattern').as 'star_default'
181
+ rule('pattern_star' => []).as 'star_base'
182
+ rule('pattern_plus' => 'pattern_plus pattern')
183
+ rule('pattern_plus' => 'pattern')
184
+ rule('pattern_datum' => 'STRING_LIT')
185
+ rule('pattern_datum' => 'CHAR')
186
+ rule('pattern_datum' => 'BOOLEAN')
187
+ rule('pattern_datum' => 'number')
188
+ # rule('pattern_datum' => 'bytevector')
189
+ rule('template' => 'pattern_identifier')
190
+ rule('template' => 'LPAREN template_element_star RPAREN')
191
+ rule('template' => 'LPAREN template_element_plus PERIOD template RPAREN')
192
+ rule('template' => 'VECTOR_BEGIN template_element_star RPAREN')
193
+ rule('template' => 'template_datum')
194
+ rule('template_element_star' => 'template_element_star template_element').as 'star_default'
195
+ rule('template_element_star' => []).as 'star_base'
196
+ rule('template_element_plus' => 'template_element_plus template_element')
197
+ rule('template_element_plus' => 'template_element')
198
+ rule('template_element' => 'template')
199
+ rule('template_element' => 'template ELLIPSIS')
200
+ rule('template_datum' => 'pattern_datum')
201
+ rule('pattern_identifier' => 'IDENTIFIER')
202
+ # Ugly: specailized production rule per keyword...
203
+ rule('pattern_identifier' => 'BEGIN')
204
+ rule('pattern_identifier' => 'COND')
205
+ rule('pattern_identifier' => 'DEFINE')
206
+ rule('pattern_identifier' => 'ELSE')
207
+ rule('pattern_identifier' => 'IF')
208
+ rule('pattern_identifier' => 'INCLUDE')
209
+ rule('pattern_identifier' => 'LAMBDA')
210
+ rule('pattern_identifier' => 'LET')
211
+ rule('pattern_identifier' => 'LET*')
212
+ rule('pattern_identifier' => 'QUOTE')
213
+ rule('pattern_identifier' => 'QUASIQUOTE')
214
+ rule('pattern_identifier' => 'SET!')
215
+ rule('pattern_identifier' => 'UNQUOTE')
216
+ rule('pattern_identifier' => 'UNQUOTE-SPLICING')
155
217
  end
156
218
 
157
219
  # And now build the grammar and make it accessible via a global constant
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'parser'
2
4
  require_relative 'skm_frame'
3
5
  require_relative 'runtime'
@@ -9,7 +11,7 @@ module Skeem
9
11
  attr_reader(:parser)
10
12
  attr_reader(:runtime)
11
13
 
12
- def initialize(&aBlock)
14
+ def initialize
13
15
  @runtime = Runtime.new(SkmFrame.new)
14
16
  @parser = Parser.new
15
17
 
@@ -20,16 +22,16 @@ module Skeem
20
22
  end
21
23
  end
22
24
 
23
- def add_default_procedures()
25
+ def add_default_procedures
24
26
  add_primitives(runtime)
25
27
  add_standard(runtime)
26
28
  end
27
29
 
28
- def parse(source, mode = nil)
30
+ def parse(source, _mode = nil)
29
31
  @parser ||= Parser.new
30
32
  @ptree = parser.parse(source)
31
- # $stderr.puts @ptree.root.inspect if mode.nil?
32
- # require 'debug' unless mode.nil?
33
+ # $stderr.puts @ptree.root.inspect if _mode.nil?
34
+ # require 'debug' unless _mode.nil?
33
35
  end
34
36
 
35
37
  def run(source, mode = nil)
@@ -43,7 +45,7 @@ module Skeem
43
45
  end
44
46
 
45
47
  def add_standard(_runtime)
46
- std_pathname = File.dirname(__FILE__) + '/standard/base.skm'
48
+ std_pathname = "#{File.dirname(__FILE__)}/standard/base.skm"
47
49
  load_lib(std_pathname)
48
50
  end
49
51
 
@@ -57,4 +59,4 @@ module Skeem
57
59
  end
58
60
  end
59
61
  end # class
60
- end # module
62
+ end # module
data/lib/skeem/parser.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'tokenizer'
2
4
  require_relative 'grammar'
3
5
  require_relative 's_expr_builder'
@@ -5,10 +7,10 @@ require_relative 's_expr_builder'
5
7
  module Skeem
6
8
  class Parser
7
9
  attr_reader(:engine)
8
-
9
- def initialize()
10
+
11
+ def initialize
10
12
  # Create a Rley facade object
11
- @engine = Rley::Engine.new do |cfg|
13
+ @engine = Rley::Engine.new do |cfg|
12
14
  cfg.diagnose = true
13
15
  cfg.repr_builder = SkmBuilder
14
16
  end
@@ -16,7 +18,7 @@ module Skeem
16
18
  # Step 1. Load Skeem grammar
17
19
  @engine.use_grammar(Skeem::Grammar)
18
20
  end
19
-
21
+
20
22
  # Parse the given Skeem expression into a parse tree.
21
23
  # @param source [String] Skeem expression to parse
22
24
  # @return [ParseTree] A regexp object equivalent to the Skeem expression.
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'primitive_procedure'
2
4
  require_relative '../datum_dsl'
5
+ require_relative '../skm_exception'
3
6
  require_relative '../skm_pair'
4
7
 
5
8
  module Skeem
@@ -34,7 +37,7 @@ module Skeem
34
37
  def binary
35
38
  SkmArity.new(2, 2)
36
39
  end
37
-
40
+
38
41
  def ternary
39
42
  SkmArity.new(3, 3)
40
43
  end
@@ -130,6 +133,7 @@ module Skeem
130
133
  create_cons(aRuntime)
131
134
  create_car(aRuntime)
132
135
  create_cdr(aRuntime)
136
+ create_make_list(aRuntime)
133
137
  create_length(aRuntime)
134
138
  create_list2vector(aRuntime)
135
139
  create_append(aRuntime)
@@ -157,11 +161,12 @@ module Skeem
157
161
  create_map(aRuntime)
158
162
  end
159
163
 
160
- def add_io_procedures(aRuntime)(aRuntime)
161
- create_newline(aRuntime)
164
+ def add_io_procedures(aRuntime)
165
+ create_display(aRuntime)
162
166
  end
163
167
 
164
168
  def add_special_procedures(aRuntime)
169
+ create_error(aRuntime)
165
170
  create_test_assert(aRuntime)
166
171
  create_debug(aRuntime)
167
172
  create_inspect(aRuntime)
@@ -169,7 +174,7 @@ module Skeem
169
174
 
170
175
  def create_plus(aRuntime)
171
176
  # arglist should be a Ruby Array
172
- primitive = ->(_runtime, arglist) do
177
+ primitive = lambda do |_runtime, arglist|
173
178
  if arglist.empty?
174
179
  integer(0)
175
180
  else
@@ -183,7 +188,7 @@ module Skeem
183
188
  end
184
189
 
185
190
  def create_minus(aRuntime)
186
- primitive = ->(_runtime, first_operand, arglist) do
191
+ primitive = lambda do |_runtime, first_operand, arglist|
187
192
  raw_result = first_operand.value
188
193
  if arglist.empty?
189
194
  raw_result = -raw_result
@@ -197,7 +202,7 @@ module Skeem
197
202
  end
198
203
 
199
204
  def create_multiply(aRuntime)
200
- primitive = ->(_runtime, arglist) do
205
+ primitive = lambda do |_runtime, arglist|
201
206
  if arglist.empty?
202
207
  integer(1)
203
208
  else
@@ -211,7 +216,6 @@ module Skeem
211
216
  end
212
217
 
213
218
  def reciprocal(aLiteral)
214
-
215
219
  case aLiteral
216
220
  when Integer
217
221
  result = Rational(1, aLiteral)
@@ -225,29 +229,26 @@ module Skeem
225
229
  end
226
230
 
227
231
  def create_divide(aRuntime)
228
- primitive = ->(_runtime, first_operand, arglist) do
232
+ primitive = lambda do |_runtime, first_operand, arglist|
229
233
  raw_result = first_operand.value
230
234
  if arglist.empty?
231
235
  raw_result = reciprocal(raw_result)
232
236
  else
233
- # Ugly: Ruby version dependency: Rubies older than 2.4 have class Fixnum instead of Integer
234
- int_class = (RUBY_VERSION[0..2] < "2.4") ? Fixnum : Integer
235
-
236
237
  arglist.each do |elem|
237
238
  elem_value = elem.value
238
239
  case [raw_result.class, elem_value.class]
239
- when [int_class, int_class]
240
+ when [Integer, Integer]
240
241
  if raw_result.modulo(elem_value).zero?
241
- raw_result = raw_result / elem_value
242
+ raw_result /= elem_value
242
243
  else
243
244
  raw_result = Rational(raw_result, elem_value)
244
245
  end
245
246
 
246
- when [int_class, Rational]
247
- raw_result = raw_result * reciprocal(elem_value)
247
+ when [Integer, Rational]
248
+ raw_result *= reciprocal(elem_value)
248
249
 
249
250
  when [Rational, Rational]
250
- raw_result = raw_result * reciprocal(elem_value)
251
+ raw_result *= reciprocal(elem_value)
251
252
  else
252
253
  raw_result = raw_result.to_f
253
254
  raw_result /= elem_value
@@ -261,8 +262,8 @@ module Skeem
261
262
  end
262
263
 
263
264
  def create_floor_slash(aRuntime)
264
- primitive = ->(_runtime, operand_1, operand_2) do
265
- (quotient, modulus) = operand_1.value.divmod(operand_2.value)
265
+ primitive = lambda do |_runtime, operand1, operand2|
266
+ (quotient, modulus) = operand1.value.divmod(operand2.value)
266
267
  SkmPair.new(to_datum(quotient), to_datum(modulus)) # improper list!
267
268
  end
268
269
 
@@ -270,10 +271,10 @@ module Skeem
270
271
  end
271
272
 
272
273
  def create_truncate_slash(aRuntime)
273
- primitive = ->(_runtime, operand_1, operand_2) do
274
- modulo_ = operand_1.value / operand_2.value
275
- modulo_ += 1 if modulo_ < 0
276
- remainder_ = operand_1.value.remainder(operand_2.value)
274
+ primitive = lambda do |_runtime, operand1, operand2|
275
+ modulo_ = operand1.value / operand2.value
276
+ modulo_ += 1 if modulo_.negative?
277
+ remainder_ = operand1.value.remainder(operand2.value)
277
278
  SkmPair.new(to_datum(modulo_), to_datum(remainder_)) # improper list!
278
279
  end
279
280
 
@@ -281,7 +282,7 @@ module Skeem
281
282
  end
282
283
 
283
284
  def create_gcd(aRuntime)
284
- primitive = ->(_runtime, arglist) do
285
+ primitive = lambda do |_runtime, arglist|
285
286
  if arglist.empty?
286
287
  integer(0)
287
288
  else
@@ -300,7 +301,7 @@ module Skeem
300
301
  end
301
302
 
302
303
  def create_lcm(aRuntime)
303
- primitive = ->(_runtime, arglist) do
304
+ primitive = lambda do |_runtime, arglist|
304
305
  if arglist.empty?
305
306
  integer(1)
306
307
  else
@@ -314,7 +315,7 @@ module Skeem
314
315
  end
315
316
 
316
317
  def create_numerator(aRuntime)
317
- primitive = ->(_runtime, arg_evaluated) do
318
+ primitive = lambda do |_runtime, arg_evaluated|
318
319
  case arg_evaluated
319
320
  when SkmInteger
320
321
  result = arg_evaluated
@@ -328,7 +329,7 @@ module Skeem
328
329
  end
329
330
 
330
331
  def create_denominator(aRuntime)
331
- primitive = ->(_runtime, arg_evaluated) do
332
+ primitive = lambda do |_runtime, arg_evaluated|
332
333
  case arg_evaluated
333
334
  when SkmInteger
334
335
  result = 1
@@ -342,7 +343,7 @@ module Skeem
342
343
  end
343
344
 
344
345
  def create_floor(aRuntime)
345
- primitive = ->(_runtime, arg_evaluated) do
346
+ primitive = lambda do |_runtime, arg_evaluated|
346
347
  result = arg_evaluated.value.floor
347
348
  integer(result)
348
349
  end
@@ -351,7 +352,7 @@ module Skeem
351
352
  end
352
353
 
353
354
  def create_ceiling(aRuntime)
354
- primitive = ->(_runtime, arg_evaluated) do
355
+ primitive = lambda do |_runtime, arg_evaluated|
355
356
  result = arg_evaluated.value.ceil
356
357
  integer(result)
357
358
  end
@@ -360,7 +361,7 @@ module Skeem
360
361
  end
361
362
 
362
363
  def create_round(aRuntime)
363
- primitive = ->(_runtime, arg_evaluated) do
364
+ primitive = lambda do |_runtime, arg_evaluated|
364
365
  result = arg_evaluated.value.round
365
366
  integer(result)
366
367
  end
@@ -374,8 +375,8 @@ module Skeem
374
375
  end
375
376
 
376
377
  def create_eqv?(aRuntime)
377
- primitive = ->(runtime, operand_1, operand_2) do
378
- core_eqv?(operand_1, operand_2)
378
+ primitive = lambda do |_runtime, operand1, operand2|
379
+ core_eqv?(operand1, operand2)
379
380
  end
380
381
 
381
382
  define_primitive_proc(aRuntime, 'eqv?', binary, primitive)
@@ -387,7 +388,7 @@ module Skeem
387
388
  end
388
389
 
389
390
  def create_eq?(aRuntime)
390
- primitive = ->(_runtime, operand_1, operand_2) do
391
+ primitive = lambda do |_runtime, operand1, operand2|
391
392
  core_eq?(operand1, operand2)
392
393
  end
393
394
 
@@ -395,8 +396,8 @@ module Skeem
395
396
  end
396
397
 
397
398
  def create_equal?(aRuntime)
398
- primitive = ->(_runtime, operand_1, operand_2) do
399
- raw_result = operand_1.skm_equal?(operand_2)
399
+ primitive = lambda do |_runtime, operand1, operand2|
400
+ raw_result = operand1.skm_equal?(operand2)
400
401
  boolean(raw_result)
401
402
  end
402
403
 
@@ -404,7 +405,7 @@ module Skeem
404
405
  end
405
406
 
406
407
  def create_equal(aRuntime)
407
- primitive = ->(_runtime, first_operand, arglist) do
408
+ primitive = lambda do |_runtime, first_operand, arglist|
408
409
  if arglist.empty?
409
410
  boolean(true)
410
411
  else
@@ -418,11 +419,11 @@ module Skeem
418
419
  end
419
420
 
420
421
  def create_lt(aRuntime)
421
- primitive = ->(_runtime, first_operand, arglist) do
422
+ primitive = lambda do |runtime, first_operand, arglist|
422
423
  if arglist.empty?
423
424
  result = false
424
425
  else
425
- result = primitive_comparison(:<, _runtime, first_operand, arglist)
426
+ result = primitive_comparison(:<, runtime, first_operand, arglist)
426
427
  end
427
428
  boolean(result)
428
429
  end
@@ -431,11 +432,11 @@ module Skeem
431
432
  end
432
433
 
433
434
  def create_gt(aRuntime)
434
- primitive = ->(_runtime, first_operand, arglist) do
435
+ primitive = lambda do |runtime, first_operand, arglist|
435
436
  if arglist.empty?
436
437
  result = false
437
438
  else
438
- result = primitive_comparison(:>, _runtime, first_operand, arglist)
439
+ result = primitive_comparison(:>, runtime, first_operand, arglist)
439
440
  end
440
441
  boolean(result)
441
442
  end
@@ -444,11 +445,11 @@ module Skeem
444
445
  end
445
446
 
446
447
  def create_lte(aRuntime)
447
- primitive = ->(_runtime, first_operand, arglist) do
448
+ primitive = lambda do |runtime, first_operand, arglist|
448
449
  if arglist.empty?
449
450
  result = true
450
451
  else
451
- result = primitive_comparison(:<=, _runtime, first_operand, arglist)
452
+ result = primitive_comparison(:<=, runtime, first_operand, arglist)
452
453
  end
453
454
  boolean(result)
454
455
  end
@@ -457,11 +458,11 @@ module Skeem
457
458
  end
458
459
 
459
460
  def create_gte(aRuntime)
460
- primitive = ->(_runtime, first_operand, arglist) do
461
+ primitive = lambda do |runtime, first_operand, arglist|
461
462
  if arglist.empty?
462
463
  result = true
463
464
  else
464
- result = primitive_comparison(:>=, _runtime, first_operand, arglist)
465
+ result = primitive_comparison(:>=, runtime, first_operand, arglist)
465
466
  end
466
467
  boolean(result)
467
468
  end
@@ -480,7 +481,7 @@ module Skeem
480
481
  end
481
482
 
482
483
  def create_max(aRuntime)
483
- primitive = ->(_runtime, first_operand, arglist) do
484
+ primitive = lambda do |_runtime, first_operand, arglist|
484
485
  if arglist.empty?
485
486
  result = first_operand
486
487
  else
@@ -498,7 +499,7 @@ module Skeem
498
499
  end
499
500
 
500
501
  def create_min(aRuntime)
501
- primitive = ->(_runtime, first_operand, arglist) do
502
+ primitive = lambda do |_runtime, first_operand, arglist|
502
503
  if arglist.empty?
503
504
  result = first_operand
504
505
  else
@@ -517,7 +518,7 @@ module Skeem
517
518
 
518
519
  def create_number2string(aRuntime)
519
520
  # TODO: add support for radix argument
520
- primitive = ->(_runtime, arg_evaluated) do
521
+ primitive = lambda do |_runtime, arg_evaluated|
521
522
  check_argtype(arg_evaluated, SkmNumber, 'number', 'number->string')
522
523
  string(arg_evaluated.value)
523
524
  end
@@ -528,7 +529,7 @@ module Skeem
528
529
  def create_and(aRuntime)
529
530
  # arglist should be a Ruby Array
530
531
  # Arguments aren't evaluated yet!...
531
- primitive = ->(runtime, arglist) do
532
+ primitive = lambda do |runtime, arglist|
532
533
  if arglist.empty?
533
534
  boolean(true) # in conformance with 4.2.1
534
535
  else
@@ -536,7 +537,7 @@ module Skeem
536
537
  last_result = nil
537
538
  # $stderr.puts arglist.inspect
538
539
  arglist.each do |raw_arg|
539
- argument = raw_arg.evaluate(aRuntime)
540
+ argument = raw_arg.evaluate(runtime)
540
541
  last_result = argument
541
542
  raw_result &&= !(argument.boolean? && !argument.value)
542
543
  break unless raw_result # stop here, a false was found...
@@ -554,14 +555,14 @@ module Skeem
554
555
  def create_or(aRuntime)
555
556
  # arglist should be a Ruby Array
556
557
  # Arguments aren't evaluated yet!...
557
- primitive = ->(runtime, arglist) do
558
+ primitive = lambda do |runtime, arglist|
558
559
  if arglist.empty?
559
560
  boolean(false) # in conformance with 4.2.1
560
561
  else
561
562
  raw_result = false
562
563
  last_result = nil
563
564
  arglist.each do |raw_arg|
564
- argument = raw_arg.evaluate(aRuntime)
565
+ argument = raw_arg.evaluate(runtime)
565
566
  last_result = argument
566
567
  raw_result ||= (!argument.boolean? || argument.value)
567
568
  break if raw_result # stop here, a true was found...
@@ -601,7 +602,7 @@ module Skeem
601
602
  end
602
603
 
603
604
  def create_boolean_equal(aRuntime)
604
- primitive = ->(_runtime, first_operand, arglist) do
605
+ primitive = lambda do |_runtime, first_operand, arglist|
605
606
  compare_all(first_operand, arglist, :==)
606
607
  end
607
608
 
@@ -609,7 +610,7 @@ module Skeem
609
610
  end
610
611
 
611
612
  def create_char2int(aRuntime)
612
- primitive = ->(runtime, arg_evaluated) do
613
+ primitive = lambda do |_runtime, arg_evaluated|
613
614
  check_argtype(arg_evaluated, SkmChar, 'character', 'char->integer')
614
615
  integer(arg_evaluated.value.ord)
615
616
  end
@@ -618,7 +619,7 @@ module Skeem
618
619
  end
619
620
 
620
621
  def create_int2char(aRuntime)
621
- primitive = ->(runtime, arg_evaluated) do
622
+ primitive = lambda do |_runtime, arg_evaluated|
622
623
  check_argtype(arg_evaluated, SkmInteger, 'integer', 'integer->char')
623
624
  char(arg_evaluated.value.ord)
624
625
  end
@@ -627,7 +628,7 @@ module Skeem
627
628
  end
628
629
 
629
630
  def create_char_equal(aRuntime)
630
- primitive = ->(_runtime, first_operand, arglist) do
631
+ primitive = lambda do |_runtime, first_operand, arglist|
631
632
  compare_all(first_operand, arglist, :==)
632
633
  end
633
634
 
@@ -635,7 +636,7 @@ module Skeem
635
636
  end
636
637
 
637
638
  def create_char_lt(aRuntime)
638
- primitive = ->(_runtime, first_operand, arglist) do
639
+ primitive = lambda do |_runtime, first_operand, arglist|
639
640
  compare_all(first_operand, arglist, :<)
640
641
  end
641
642
 
@@ -643,7 +644,7 @@ module Skeem
643
644
  end
644
645
 
645
646
  def create_char_gt(aRuntime)
646
- primitive = ->(_runtime, first_operand, arglist) do
647
+ primitive = lambda do |_runtime, first_operand, arglist|
647
648
  compare_all(first_operand, arglist, :>)
648
649
  end
649
650
 
@@ -651,7 +652,7 @@ module Skeem
651
652
  end
652
653
 
653
654
  def create_char_lte(aRuntime)
654
- primitive = ->(_runtime, first_operand, arglist) do
655
+ primitive = lambda do |_runtime, first_operand, arglist|
655
656
  compare_all(first_operand, arglist, :<=)
656
657
  end
657
658
 
@@ -659,23 +660,22 @@ module Skeem
659
660
  end
660
661
 
661
662
  def create_char_gte(aRuntime)
662
- primitive = ->(_runtime, first_operand, arglist) do
663
+ primitive = lambda do |_runtime, first_operand, arglist|
663
664
  compare_all(first_operand, arglist, :>=)
664
665
  end
665
666
 
666
667
  define_primitive_proc(aRuntime, 'char>=?', one_or_more, primitive)
667
668
  end
668
669
 
669
-
670
670
  def create_make_string(aRuntime)
671
- primitive = ->(runtime, count_arg, arglist) do
671
+ primitive = lambda do |_runtime, count_arg, arglist|
672
672
  count = count_arg
673
- check_argtype(count, SkmInteger, 'integer', 'make_string')
673
+ check_argtype(count, SkmInteger, 'integer', 'make-string')
674
674
  if arglist.empty?
675
675
  filler = SkmChar.create(rand(0xff).chr)
676
676
  else
677
677
  filler = arglist.first
678
- check_argtype(filler, SkmChar, 'char', 'make_string')
678
+ check_argtype(filler, SkmChar, 'char', 'make-string')
679
679
  end
680
680
  string(filler.value.to_s * count.value)
681
681
  end
@@ -684,11 +684,11 @@ module Skeem
684
684
  end
685
685
 
686
686
  def create_string_string(aRuntime)
687
- primitive = ->(_runtime, arglist) do
687
+ primitive = lambda do |_runtime, arglist|
688
688
  if arglist.empty?
689
689
  value = ''
690
690
  else
691
- value = arglist.reduce('') do |interim, some_char|
691
+ value = arglist.reduce(+'') do |interim, some_char|
692
692
  check_argtype(some_char, SkmChar, 'character', 'string')
693
693
  interim << some_char.value
694
694
  end
@@ -701,7 +701,7 @@ module Skeem
701
701
  end
702
702
 
703
703
  def create_string_equal(aRuntime)
704
- primitive = ->(_runtime, first_operand, arglist) do
704
+ primitive = lambda do |_runtime, first_operand, arglist|
705
705
  all_same?(first_operand, arglist)
706
706
  end
707
707
 
@@ -709,11 +709,11 @@ module Skeem
709
709
  end
710
710
 
711
711
  def create_string_append(aRuntime)
712
- primitive = ->(_runtime, arglist) do
712
+ primitive = lambda do |_runtime, arglist|
713
713
  if arglist.empty?
714
714
  value = ''
715
715
  else
716
- value = arglist.reduce('') { |interim, substr| interim << substr.value }
716
+ value = arglist.reduce(+'') { |interim, substr| interim << substr.value }
717
717
  end
718
718
 
719
719
  string(value)
@@ -723,7 +723,7 @@ module Skeem
723
723
  end
724
724
 
725
725
  def create_string_length(aRuntime)
726
- primitive = ->(runtime, arg_evaluated) do
726
+ primitive = lambda do |_runtime, arg_evaluated|
727
727
  check_argtype(arg_evaluated, SkmString, 'string', 'string-length')
728
728
  integer(arg_evaluated.length)
729
729
  end
@@ -732,7 +732,7 @@ module Skeem
732
732
  end
733
733
 
734
734
  def create_string2symbol(aRuntime)
735
- primitive = ->(runtime, arg_evaluated) do
735
+ primitive = lambda do |_runtime, arg_evaluated|
736
736
  check_argtype(arg_evaluated, SkmString, 'string', 'string->symbol')
737
737
  identifier(arg_evaluated)
738
738
  end
@@ -741,7 +741,7 @@ module Skeem
741
741
  end
742
742
 
743
743
  def create_symbol2string(aRuntime)
744
- primitive = ->(runtime, arg_evaluated) do
744
+ primitive = lambda do |_runtime, arg_evaluated|
745
745
  check_argtype(arg_evaluated, SkmIdentifier, 'symbol', 'symbol->string')
746
746
  string(arg_evaluated)
747
747
  end
@@ -750,7 +750,7 @@ module Skeem
750
750
  end
751
751
 
752
752
  def create_car(aRuntime)
753
- primitive = ->(runtime, arg_evaluated) do
753
+ primitive = lambda do |_runtime, arg_evaluated|
754
754
  check_argtype(arg_evaluated, SkmPair, 'pair', 'car')
755
755
  arg_evaluated.car
756
756
  end
@@ -759,7 +759,7 @@ module Skeem
759
759
  end
760
760
 
761
761
  def create_cdr(aRuntime)
762
- primitive = ->(_runtime, arg_evaluated) do
762
+ primitive = lambda do |_runtime, arg_evaluated|
763
763
  check_argtype(arg_evaluated, SkmPair, 'pair', 'cdr')
764
764
  arg_evaluated.cdr
765
765
  end
@@ -768,15 +768,31 @@ module Skeem
768
768
  end
769
769
 
770
770
  def create_cons(aRuntime)
771
- primitive = ->(_runtime, obj1, obj2) do
771
+ primitive = lambda do |_runtime, obj1, obj2|
772
772
  SkmPair.new(obj1, obj2)
773
773
  end
774
774
 
775
775
  define_primitive_proc(aRuntime, 'cons', binary, primitive)
776
776
  end
777
777
 
778
+ def create_make_list(aRuntime)
779
+ primitive = lambda do |_runtime, count_arg, arglist|
780
+ count = count_arg
781
+ check_argtype(count, SkmInteger, 'integer', 'make-list')
782
+ if arglist.empty?
783
+ filler = SkmUndefined.instance
784
+ else
785
+ filler = arglist.first
786
+ end
787
+ arr = Array.new(count.value, filler)
788
+ SkmPair.create_from_a(arr)
789
+ end
790
+
791
+ define_primitive_proc(aRuntime, 'make-list', one_or_two, primitive)
792
+ end
793
+
778
794
  def create_length(aRuntime)
779
- primitive = ->(_runtime, arg_evaluated) do
795
+ primitive = lambda do |_runtime, arg_evaluated|
780
796
  check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'length')
781
797
  integer(arg_evaluated.length)
782
798
  end
@@ -785,7 +801,7 @@ module Skeem
785
801
  end
786
802
 
787
803
  def create_list2vector(aRuntime)
788
- primitive = ->(_runtime, arg_evaluated) do
804
+ primitive = lambda do |_runtime, arg_evaluated|
789
805
  check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list->vector')
790
806
  vector(arg_evaluated.to_a)
791
807
  end
@@ -801,7 +817,7 @@ module Skeem
801
817
  else
802
818
  but_last = arglist.take(arglist.length - 1)
803
819
  check_arguments(but_last, [SkmPair, SkmEmptyList], 'list', 'append')
804
- result = arglist.shift.klone # First list is taken
820
+ result = arglist.shift.klone # First list is taken
805
821
  arglist.each do |arg|
806
822
  case arg
807
823
  when SkmPair
@@ -809,11 +825,7 @@ module Skeem
809
825
  if result.kind_of?(SkmEmptyList)
810
826
  result = cloned
811
827
  else
812
- if result.kind_of?(SkmEmptyList)
813
- result = SkmPair.new(arg, SkmEmptyList.instance)
814
- else
815
- result.append_list(cloned)
816
- end
828
+ result.append_list(cloned)
817
829
  end
818
830
  when SkmEmptyList
819
831
  # Do nothing
@@ -832,9 +844,9 @@ module Skeem
832
844
 
833
845
  def create_append(aRuntime)
834
846
  # Arguments aren't evaluated yet!...
835
- primitive = ->(runtime, arglist) do
847
+ primitive = lambda do |runtime, arglist|
836
848
  if arglist.size > 1
837
- arguments = evaluate_arguments(arglist, aRuntime)
849
+ arguments = evaluate_arguments(arglist, runtime)
838
850
  else
839
851
  arguments = arglist
840
852
  end
@@ -846,13 +858,14 @@ module Skeem
846
858
  end
847
859
 
848
860
  def create_reverse(aRuntime)
849
- primitive = ->(_runtime, arg_evaluated) do
861
+ primitive = lambda do |_runtime, arg_evaluated|
850
862
  check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'reverse')
851
863
  if arg_evaluated == SkmEmptyList.instance
852
864
  result = arg_evaluated
853
865
  else
854
866
  err_msg = 'reverse procedure requires a proper list as argument'
855
- raise StandardError, err_msg unless arg_evaluated.proper?
867
+ raise StandardError, err_msg unless arg_evaluated.proper?
868
+
856
869
  elems_reversed = arg_evaluated.to_a.reverse
857
870
  result = SkmPair.create_from_a(elems_reversed)
858
871
  end
@@ -864,7 +877,7 @@ module Skeem
864
877
 
865
878
  def create_setcar(aRuntime)
866
879
  # Arguments aren't evaluated yet!...
867
- primitive = ->(runtime, pair_arg, obj_arg) do
880
+ primitive = lambda do |runtime, pair_arg, obj_arg|
868
881
  case pair_arg
869
882
  when SkmPair
870
883
  pair = pair_arg
@@ -889,7 +902,7 @@ module Skeem
889
902
 
890
903
  def create_setcdr(aRuntime)
891
904
  # Arguments aren't evaluated yet!...
892
- primitive = ->(runtime, pair_arg, obj_arg) do
905
+ primitive = lambda do |runtime, pair_arg, obj_arg|
893
906
  case pair_arg
894
907
  when SkmPair
895
908
  pair = pair_arg
@@ -913,21 +926,22 @@ module Skeem
913
926
  end
914
927
 
915
928
  def create_assq(aRuntime)
916
- primitive = ->(runtime, obj_arg, alist_arg) do
929
+ primitive = lambda do |runtime, obj_arg, alist_arg|
917
930
  assoc_list = alist_arg.evaluate(runtime)
918
931
  check_assoc_list(assoc_list, 'assq')
919
932
  obj = obj_arg.evaluate(runtime)
920
933
  result = boolean(false)
921
934
  unless assoc_list.empty?
922
935
  pair = assoc_list
923
- begin
936
+ loop do
924
937
  are_equal = core_eq?(pair.car.car, obj)
925
938
  if are_equal.value
926
939
  result = pair.car
927
940
  break
928
941
  end
929
942
  pair = pair.cdr
930
- end while (pair && (pair.kind_of?(SkmPair)))
943
+ break unless pair.kind_of?(SkmPair)
944
+ end
931
945
  end
932
946
 
933
947
  result
@@ -936,19 +950,20 @@ module Skeem
936
950
  end
937
951
 
938
952
  def create_assv(aRuntime)
939
- primitive = ->(runtime, obj, assoc_list) do
953
+ primitive = lambda do |_runtime, obj, assoc_list|
940
954
  check_assoc_list(assoc_list, 'assq')
941
955
  result = boolean(false)
942
956
  unless assoc_list.empty?
943
957
  pair = assoc_list
944
- begin
958
+ loop do
945
959
  are_equal = core_eqv?(pair.car.car, obj)
946
960
  if are_equal.value
947
961
  result = pair.car
948
962
  break
949
963
  end
950
964
  pair = pair.cdr
951
- end while (pair && (pair.kind_of?(SkmPair)))
965
+ break unless pair.kind_of?(SkmPair)
966
+ end
952
967
  end
953
968
 
954
969
  result
@@ -961,15 +976,16 @@ module Skeem
961
976
 
962
977
  unless alist.empty?
963
978
  cell = SkmPair.new(integer(1), alist)
964
- begin
979
+ loop do
965
980
  cell = cell.cdr
966
981
  check_argtype(cell, SkmPair, 'association list', proc_name)
967
- end while cell.cdr.kind_of?(SkmPair)
982
+ break unless cell.cdr.kind_of?(SkmPair)
983
+ end
968
984
  end
969
985
  end
970
986
 
971
987
  def create_list_copy(aRuntime)
972
- primitive = ->(runtime, arg_evaluated) do
988
+ primitive = lambda do |_runtime, arg_evaluated|
973
989
  check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list-copy')
974
990
  arg_evaluated.klone # Previously: arg.klone
975
991
  end
@@ -978,7 +994,7 @@ module Skeem
978
994
  end
979
995
 
980
996
  def create_vector(aRuntime)
981
- primitive = ->(_runtime, elements) do
997
+ primitive = lambda do |_runtime, elements|
982
998
  vector(elements)
983
999
  end
984
1000
 
@@ -986,7 +1002,7 @@ module Skeem
986
1002
  end
987
1003
 
988
1004
  def create_vector_length(aRuntime)
989
- primitive = ->(_runtime, arg_evaluated) do
1005
+ primitive = lambda do |_runtime, arg_evaluated|
990
1006
  check_argtype(arg_evaluated, SkmVector, 'vector', 'vector-length')
991
1007
  integer(arg_evaluated.length)
992
1008
  end
@@ -995,7 +1011,7 @@ module Skeem
995
1011
  end
996
1012
 
997
1013
  def create_make_vector(aRuntime)
998
- primitive = ->(runtime, count_arg, arglist) do
1014
+ primitive = lambda do |runtime, count_arg, arglist|
999
1015
  count = count_arg.evaluate(runtime)
1000
1016
  check_argtype(count, SkmInteger, 'integer', 'make_vector')
1001
1017
  if arglist.empty?
@@ -1011,8 +1027,8 @@ module Skeem
1011
1027
  end
1012
1028
 
1013
1029
  def create_vector_ref(aRuntime)
1014
- # argument 1: a vector, argument 2: an index(integer)
1015
- primitive = ->(runtime, vector, index) do
1030
+ # argument 1: a vector, argument 2: an index(integer)
1031
+ primitive = lambda do |_runtime, vector, index|
1016
1032
  check_argtype(vector, SkmVector, 'vector', 'vector-ref')
1017
1033
  check_argtype(index, SkmInteger, 'integer', 'vector-ref')
1018
1034
  # TODO: index checking
@@ -1022,10 +1038,10 @@ module Skeem
1022
1038
 
1023
1039
  define_primitive_proc(aRuntime, 'vector-ref', binary, primitive)
1024
1040
  end
1025
-
1041
+
1026
1042
  def create_vector_set(aRuntime)
1027
- # Arguments aren't evaluated yet!...
1028
- primitive = ->(runtime, vector, k, object) do
1043
+ # Arguments aren't evaluated yet!...
1044
+ primitive = lambda do |runtime, vector, k, object|
1029
1045
  index = k.evaluate(runtime)
1030
1046
  check_argtype(vector, SkmVector, 'vector', 'vector-set!')
1031
1047
  check_argtype(index, SkmInteger, 'integer', 'vector-set!')
@@ -1033,12 +1049,12 @@ module Skeem
1033
1049
  vector.members[index.value] = object
1034
1050
  vector
1035
1051
  end
1036
-
1052
+
1037
1053
  define_primitive_proc(aRuntime, 'vector-set!', ternary, primitive)
1038
1054
  end
1039
1055
 
1040
1056
  def create_vector2list(aRuntime)
1041
- primitive = ->(runtime, arg_evaluated) do
1057
+ primitive = lambda do |_runtime, arg_evaluated|
1042
1058
  check_argtype(arg_evaluated, SkmVector, 'vector', 'vector->list')
1043
1059
  SkmPair.create_from_a(arg_evaluated.members)
1044
1060
  end
@@ -1047,7 +1063,7 @@ module Skeem
1047
1063
  end
1048
1064
 
1049
1065
  def create_apply(aRuntime)
1050
- primitive = ->(runtime, proc_arg, arglist) do
1066
+ primitive = lambda do |runtime, proc_arg, arglist|
1051
1067
  if arglist.empty?
1052
1068
  result = SkmEmptyList.instance
1053
1069
  else
@@ -1055,18 +1071,19 @@ module Skeem
1055
1071
  invoke = ProcedureCall.new(nil, proc_arg, single_list.to_a)
1056
1072
  result = invoke.evaluate(runtime)
1057
1073
  end
1074
+ result
1058
1075
  end
1059
1076
 
1060
1077
  define_primitive_proc(aRuntime, 'apply', one_or_more, primitive)
1061
1078
  end
1062
1079
 
1063
1080
  def create_map(aRuntime)
1064
- primitive = ->(runtime, proc_arg, arglist) do
1081
+ primitive = lambda do |runtime, proc_arg, arglist|
1065
1082
  if arglist.empty?
1066
1083
  result = SkmEmptyList.instance
1067
1084
  else
1068
1085
  curr_cells = arglist
1069
- arity = curr_cells.size
1086
+ # arity = curr_cells.size
1070
1087
  initial_result = nil
1071
1088
  curr_result = nil
1072
1089
  loop do
@@ -1082,7 +1099,7 @@ module Skeem
1082
1099
  curr_result = new_result
1083
1100
 
1084
1101
  curr_cells.map!(&:cdr)
1085
- break if curr_cells.find { |cdr_entry| ! cdr_entry.kind_of?(SkmPair) }
1102
+ break if curr_cells.find { |cdr_entry| !cdr_entry.kind_of?(SkmPair) }
1086
1103
  end
1087
1104
 
1088
1105
  result = initial_result
@@ -1094,24 +1111,33 @@ module Skeem
1094
1111
  define_primitive_proc(aRuntime, 'map', one_or_more, primitive)
1095
1112
  end
1096
1113
 
1097
- def create_newline(aRuntime)
1098
- primitive = ->(runtime) do
1114
+ def create_display(aRuntime)
1115
+ primitive = lambda do |_runtime, arg_evaluated|
1099
1116
  # @TODO: make output stream configurable
1100
- print "\n"
1117
+ print arg_evaluated.value.to_s
1118
+ SkmUndefined.instance
1119
+ end
1120
+
1121
+ define_primitive_proc(aRuntime, 'display', unary, primitive)
1122
+ end
1123
+
1124
+ def create_error(aRuntime)
1125
+ primitive = lambda do |_runtime, arg_evaluated|
1126
+ raise SkmError, arg_evaluated.value
1101
1127
  end
1102
1128
 
1103
- define_primitive_proc(aRuntime, 'newline', nullary, primitive)
1129
+ define_primitive_proc(aRuntime, 'error', unary, primitive)
1104
1130
  end
1105
1131
 
1106
1132
  def create_test_assert(aRuntime)
1107
- primitive = ->(runtime, arg_evaluated) do
1133
+ primitive = lambda do |_runtime, arg_evaluated|
1108
1134
  if arg_evaluated.boolean? && arg_evaluated.value == false
1109
1135
  assert_call = aRuntime.caller
1110
1136
  pos = assert_call.call_site
1111
1137
  # Error: assertion failed: (> 1 2)
1112
1138
  msg1 = "assertion failed on line #{pos.line}, column #{pos.column}"
1113
1139
  msg2 = ", with #{arg_evaluated.inspect}"
1114
- raise StandardError, 'Error: ' + msg1 + msg2
1140
+ raise StandardError, "Error: #{msg1}#{msg2}"
1115
1141
  else
1116
1142
  boolean(true)
1117
1143
  end
@@ -1123,7 +1149,7 @@ module Skeem
1123
1149
  # DON'T USE IT
1124
1150
  # Non-standard procedure reserved for internal testing/debugging purposes.
1125
1151
  def create_debug(aRuntime)
1126
- primitive = ->(runtime) do
1152
+ primitive = lambda do |_runtime|
1127
1153
  require 'debug'
1128
1154
  end
1129
1155
 
@@ -1133,8 +1159,8 @@ module Skeem
1133
1159
  # DON'T USE IT
1134
1160
  # Non-standard procedure reserved for internal testing/debugging purposes.
1135
1161
  def create_inspect(aRuntime)
1136
- primitive = ->(runtime, arg_evaluated) do
1137
- $stderr.puts 'INSPECT>' + arg_evaluated.inspect
1162
+ primitive = lambda do |_runtime, arg_evaluated|
1163
+ $stderr.puts "INSPECT>#{arg_evaluated.inspect}"
1138
1164
  Skeem::SkmUndefined.instance
1139
1165
  end
1140
1166
  define_primitive_proc(aRuntime, '_inspect', unary, primitive)
@@ -1142,7 +1168,7 @@ module Skeem
1142
1168
 
1143
1169
  def create_object_predicate(aRuntime, predicate_name, msg_name = nil)
1144
1170
  msg_name = predicate_name if msg_name.nil?
1145
- primitive = ->(runtime, arg_evaluated) do
1171
+ primitive = lambda do |_runtime, arg_evaluated|
1146
1172
  to_datum(arg_evaluated.send(msg_name))
1147
1173
  end
1148
1174
 
@@ -1202,7 +1228,7 @@ module Skeem
1202
1228
  else
1203
1229
  msg2 = "but got #{argument.class}"
1204
1230
  end
1205
- raise StandardError, msg1 + ' ' + msg2
1231
+ raise StandardError, "#{msg1} #{msg2}"
1206
1232
  end
1207
1233
 
1208
1234
  def remaining_args(arglist, aRuntime)
@@ -1216,4 +1242,4 @@ module Skeem
1216
1242
  end
1217
1243
  end # module
1218
1244
  end # module
1219
- end # module
1245
+ end # module