rus3 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rus3
4
+ module Procedure
5
+
6
+ # This module holds comparison operation procedures of Scheme.
7
+
8
+ module Comparison
9
+
10
+ def lt?(*args)
11
+ c_calc(:<, *args)
12
+ end
13
+
14
+ def le?(*args)
15
+ c_calc(:<=, *args)
16
+ end
17
+
18
+ def gt?(*args)
19
+ c_calc(:>, *args)
20
+ end
21
+
22
+ def ge?(*args)
23
+ c_calc(:>=, *args)
24
+ end
25
+
26
+ def same_value?(*args)
27
+ c_calc(:==, *args)
28
+ end
29
+
30
+ private
31
+
32
+ def c_calc(op, *args)
33
+ case args.size
34
+ when 0, 1
35
+ raise ArgumentError, args.to_s
36
+ when 2
37
+ args[0].send(op, args[1]) ? true : false
38
+ else
39
+ args[0].send(op, args[1]) and c_calc(op, *args[1..-1]) ? true : false
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
data/lib/rus3/repl.rb CHANGED
@@ -21,13 +21,13 @@ module Rus3
21
21
  class Repl
22
22
 
23
23
  # Indicates the version of the Repl class.
24
- REPL_VERSION = "0.2.0"
24
+ REPL_VERSION = "0.2.1"
25
25
 
26
26
  class << self
27
27
 
28
28
  # Starts REPL.
29
- def start(parser: nil, evaluator: nil, verbose: false)
30
- repl = Repl.new(parser: parser, evaluator: evaluator, verbose: verbose)
29
+ def start(evaluator: nil, verbose: false)
30
+ repl = Repl.new(evaluator: evaluator, verbose: verbose)
31
31
  repl.loop
32
32
  end
33
33
 
@@ -35,9 +35,9 @@ module Rus3
35
35
 
36
36
  # Hods major component names of the REPL.
37
37
  COMPONENTS = {
38
- :parser => Parser::DEFAULT_PARSER,
38
+ :parser => Rubasteme::Parser,
39
39
  :evaluator => Evaluator::DEFAULT_EVALUATOR,
40
- :printer => nil,
40
+ :printer => Printer::ChainPrinter,
41
41
  }
42
42
 
43
43
  # Prompt for input.
@@ -51,18 +51,16 @@ module Rus3
51
51
  attr_accessor :verbose # :nodoc:
52
52
  attr_accessor :prompt # :nodoc:
53
53
 
54
- def initialize(parser: nil, evaluator: nil, verbose: false)
54
+ def initialize(evaluator: nil, verbose: false)
55
55
  comps = COMPONENTS.dup
56
56
 
57
- comps[:parser] = Parser.const_get("#{parser.capitalize}Parser") if parser
58
57
  comps[:evaluator] = Evaluator.const_get("#{evaluator.capitalize}Evaluator") if evaluator
59
58
 
60
59
  comps.each { |name, klass|
61
- instance_variable_set("@#{name}", klass.nil? ? self : klass.new)
60
+ instance_variable_set("@#{name}", klass.new)
62
61
  }
63
62
 
64
63
  @prompt = PROMPT
65
- @parser.prompt = PROMPT
66
64
 
67
65
  @verbose = verbose
68
66
  @evaluator.verbose = verbose
@@ -77,17 +75,18 @@ module Rus3
77
75
  end
78
76
 
79
77
  def loop
80
- msg = Kernel.loop { # LOOP
78
+ msg = Kernel.loop { # LOOP
81
79
  begin
82
- ast = @parser.read(STDIN) # READ
80
+ source = read(STDIN) # READ
81
+ break FAREWELL_MESSAGE if source.nil?
82
+ ast = @parser.parse(Rbscmlex::Lexer.new(source))
83
83
  rescue SchemeSyntaxError => e
84
84
  puts "ERROR" + (@verbose ? "(READ)" : "") + ": %s" % e
85
85
  next
86
86
  end
87
- break FAREWELL_MESSAGE if ast.nil?
88
87
 
89
88
  begin
90
- value = @evaluator.eval(ast) # EVAL
89
+ value = @evaluator.eval(ast) # EVAL
91
90
  rescue SyntaxError, StandardError => e
92
91
  puts "ERROR" + (@verbose ? "(EVAL)" : "") + ": %s" % e
93
92
  next
@@ -95,7 +94,7 @@ module Rus3
95
94
 
96
95
  history_push(value)
97
96
 
98
- @printer.print(value) # PRINT
97
+ @printer.print(value) # PRINT
99
98
  }
100
99
  puts "#{msg}" unless msg.nil?
101
100
  end
@@ -125,28 +124,23 @@ module Rus3
125
124
  require "readline"
126
125
 
127
126
  def read(io = STDIN)
128
- Readline::readline(@prompt, true)
129
- end
130
-
131
- def eval(ast)
132
- ast
133
- end
134
-
135
- def print(obj)
136
- prefix = "==> "
137
- prefix += "[#{obj.class}]: " if @verbose
138
- Kernel.print prefix
139
- pp obj
127
+ program_source = nil
128
+ if io == STDIN
129
+ program_source = Readline::readline(@prompt, true)
130
+ else
131
+ program_source = io.readlines(chomp: true).join(" ")
132
+ end
133
+ program_source
140
134
  end
141
135
 
142
136
  private
143
137
 
144
138
  def version_message(comp_name)
145
- vmsg = nil
139
+ vmsg = ""
146
140
  component = instance_variable_get("@#{comp_name}")
147
- if component.nil? or component == self
148
- vmsg = ":using :built-in :#{comp_name}"
149
- else
141
+ if component.class.respond_to?(:version)
142
+ vmsg = "#{component.class.version}"
143
+ elsif component.respond_to?(:version)
150
144
  vmsg = "#{component.version}"
151
145
  end
152
146
  vmsg
@@ -225,7 +219,8 @@ HELP
225
219
  scheme_source = File.readlines(path, chomp: true).join(" ")
226
220
  result = ast = nil
227
221
  if @scm_parser.respond_to?(:parse)
228
- ast = @scm_parser.parse(scheme_source)
222
+ lexer = Rbscmlex::Lexer.new(scheme_source)
223
+ ast = @scm_parser.parse(lexer)
229
224
  end
230
225
  if @scm_evaluator.respond_to?(:eval)
231
226
  result = @scm_evaluator.eval(ast)
data/lib/rus3/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rus3
4
- VERSION = "0.2.0"
5
- RELEASE = "2021-05-03"
4
+ VERSION = "0.2.1"
5
+ RELEASE = "2021-05-20"
6
6
  end
data/rus3.gemspec CHANGED
@@ -9,10 +9,10 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["mnbi@users.noreply.github.com"]
10
10
 
11
11
  spec.summary = "Ruby with Syntax Sugar of Scheme"
12
- spec.description = "Ruby with Syntax Sugar of Scheme"
12
+ spec.description = "Ruby with Syntax Sugar of Scheme, or Scheme to Ruby translator."
13
13
  spec.homepage = "https://github.com/mnbi/rus3"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = "https://github.com/mnbi/rus3"
@@ -27,9 +27,6 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- # Uncomment to register a new dependency of your gem
31
- # spec.add_dependency "example-gem", "~> 1.0"
32
-
33
- # For more information and examples about making a new gem, checkout our
34
- # guide at: https://bundler.io/guides/creating_gem.html
30
+ spec.add_dependency "rbscmlex", ">= 0.1.3"
31
+ spec.add_dependency "rubasteme", ">= 0.1.3"
35
32
  end
metadata CHANGED
@@ -1,16 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rus3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - mnbi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-03 00:00:00.000000000 Z
12
- dependencies: []
13
- description: Ruby with Syntax Sugar of Scheme
11
+ date: 2021-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rbscmlex
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubasteme
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.3
41
+ description: Ruby with Syntax Sugar of Scheme, or Scheme to Ruby translator.
14
42
  email:
15
43
  - mnbi@users.noreply.github.com
16
44
  executables:
@@ -33,23 +61,18 @@ files:
33
61
  - examples/iota.scm
34
62
  - exe/rus3
35
63
  - lib/rus3.rb
36
- - lib/rus3/ast.rb
37
- - lib/rus3/ast/branch_node.rb
38
- - lib/rus3/ast/error.rb
39
- - lib/rus3/ast/leaf_node.rb
40
64
  - lib/rus3/char.rb
41
65
  - lib/rus3/error.rb
42
66
  - lib/rus3/evaluator.rb
43
67
  - lib/rus3/evaluator/environment.rb
44
68
  - lib/rus3/evaluator/scheme_evaluator.rb
45
69
  - lib/rus3/evaluator/translator.rb
46
- - lib/rus3/lexer.rb
47
70
  - lib/rus3/pair.rb
48
- - lib/rus3/parser.rb
49
- - lib/rus3/parser/scheme_parser.rb
50
71
  - lib/rus3/port.rb
51
72
  - lib/rus3/printer.rb
73
+ - lib/rus3/procedure/arithmetic.rb
52
74
  - lib/rus3/procedure/char.rb
75
+ - lib/rus3/procedure/comparison.rb
53
76
  - lib/rus3/procedure/control.rb
54
77
  - lib/rus3/procedure/list.rb
55
78
  - lib/rus3/procedure/predicate.rb
@@ -57,7 +80,6 @@ files:
57
80
  - lib/rus3/procedure/vector.rb
58
81
  - lib/rus3/procedure/write.rb
59
82
  - lib/rus3/repl.rb
60
- - lib/rus3/token.rb
61
83
  - lib/rus3/vector.rb
62
84
  - lib/rus3/version.rb
63
85
  - rus3.gemspec
@@ -76,7 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
76
98
  requirements:
77
99
  - - ">="
78
100
  - !ruby/object:Gem::Version
79
- version: 2.3.0
101
+ version: 2.7.0
80
102
  required_rubygems_version: !ruby/object:Gem::Requirement
81
103
  requirements:
82
104
  - - ">="
data/lib/rus3/ast.rb DELETED
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rus3
4
-
5
- module AST
6
-
7
- require_relative "ast/error"
8
-
9
- module Utils
10
- class << self
11
- def camel_case(snake_case)
12
- snake_case.to_s.split("_").map(&:capitalize).join("")
13
- end
14
- end
15
- end
16
-
17
- class Node
18
- attr_reader :literal
19
-
20
- def initialize(literal = nil)
21
- @literal = literal
22
- end
23
-
24
- def leaf?; false; end
25
- def branch?; false; end
26
- def illegal?; false; end
27
-
28
- def type; nil; end
29
-
30
- def to_s
31
- @literal
32
- end
33
- end
34
-
35
- class IllegalNode < Node
36
- def initialize(ast_type, literal)
37
- super(literal)
38
- @given_type = ast_type
39
- end
40
-
41
- def illegal?
42
- true
43
- end
44
-
45
- def type
46
- @given_type
47
- end
48
-
49
- def to_s
50
- "type: #{@given_type}, literal: #{@literal}"
51
- end
52
- end
53
-
54
- require_relative "ast/leaf_node"
55
- require_relative "ast/branch_node"
56
-
57
- class << self
58
- def instantiate(ast_type, literal = nil)
59
- klass_name = Utils.camel_case(ast_type) + "Node"
60
- klass = AST.const_get(klass_name)
61
- if klass.nil? or klass == IllegalNode
62
- IllegalNode.new(ast_type, literal)
63
- else
64
- klass.new(literal)
65
- end
66
- end
67
-
68
- end
69
- end
70
- end
@@ -1,412 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rus3
4
- module AST
5
-
6
- class BranchNode < Node
7
- include Enumerable
8
-
9
- def initialize(size = nil)
10
- super(nil)
11
- @nodes = size.nil? ? [] : Array.new(size)
12
- end
13
-
14
- def branch?
15
- true
16
- end
17
-
18
- def <<(node)
19
- @nodes << node
20
- end
21
-
22
- def [](index)
23
- raise OutOfRangeError, index if index >= @nodes.size
24
- @nodes[index]
25
- end
26
-
27
- def each(&block)
28
- if block.nil?
29
- @nodes.each
30
- else
31
- @nodes.each(&block)
32
- self
33
- end
34
- end
35
-
36
- def to_s
37
- @nodes.map(&:to_s).join(" ")
38
- end
39
-
40
- end
41
-
42
- class ProgramNode < BranchNode
43
- def initialize(_ = nil)
44
- super(nil)
45
- end
46
-
47
- def type
48
- :program
49
- end
50
- end
51
-
52
- class VectorNode < BranchNode
53
- def initialize(_ = nil)
54
- super(nil)
55
- end
56
-
57
- def type
58
- :vector
59
- end
60
-
61
- def to_s
62
- "#(" + super + ")"
63
- end
64
- end
65
-
66
- class ListNode < BranchNode
67
- def initialize(first_literal = nil, initial_size = nil)
68
- super(initial_size)
69
- @nodes[0] = IdentifierNode.new(first_literal) if first_literal
70
- end
71
-
72
- def type
73
- :list
74
- end
75
-
76
- def car
77
- @nodes[0]
78
- end
79
-
80
- def cdr
81
- @nodes[1..-1]
82
- end
83
-
84
- def to_s
85
- "(" + super + ")"
86
- end
87
- end
88
-
89
- class QuotationNode < ListNode
90
- def initialize(_ = nil)
91
- super("quote")
92
- end
93
-
94
- def type
95
- :quotation
96
- end
97
- end
98
-
99
- class ProcedureCallNode < ListNode
100
- def initialize(_ = nil)
101
- # @nodes = [<operator>, <operand>*]
102
- super(nil, 1)
103
- end
104
-
105
- def type
106
- :procedure_call
107
- end
108
-
109
- def operator
110
- @nodes[0]
111
- end
112
-
113
- def operator=(node)
114
- @nodes[0] = node
115
- end
116
-
117
- def operands
118
- @nodes[1..-1]
119
- end
120
-
121
- def add_operand(node)
122
- @nodes << node
123
- end
124
- end
125
-
126
- class LambdaExpressionNode < ListNode
127
- def initialize(_ = nil)
128
- # @nodes = [<lambda>, <formals>, <body> ...]
129
- super("lambda", 2)
130
- end
131
-
132
- def type
133
- :lambda_expression
134
- end
135
-
136
- def formals
137
- @nodes[1]
138
- end
139
-
140
- def formals=(list_node)
141
- @nodes[1] = list_node
142
- end
143
-
144
- def body
145
- @nodes[2..-1]
146
- end
147
-
148
- def body=(nodes)
149
- nodes.each_with_index { |node, i|
150
- @nodes[i + 2] = node
151
- }
152
- end
153
- end
154
-
155
- class ConditionalNode < ListNode
156
- def initialize(_ = nil)
157
- # @nodes = [<if>, <test>, <consequent>] or
158
- # [<if>, <test>, <consequent>, <alternate>]
159
- super("if", 3)
160
- end
161
-
162
- def type
163
- :conditional
164
- end
165
-
166
- def test
167
- @nodes[1]
168
- end
169
-
170
- def consequent
171
- @nodes[2]
172
- end
173
-
174
- def alternate
175
- if @nodes.size > 3
176
- @nodes[3]
177
- else
178
- nil
179
- end
180
- end
181
-
182
- def test=(node)
183
- @nodes[1] = node
184
- end
185
-
186
- def consequent=(node)
187
- @nodes[2] = node
188
- end
189
-
190
- def alternate=(node)
191
- @nodes[3] = node
192
- end
193
- end
194
-
195
- class AssignmentNode < ListNode
196
- def initialize(_ = nil)
197
- super("set!", 3)
198
- end
199
-
200
- def type
201
- :assignment
202
- end
203
-
204
- def identifier
205
- @nodes[1]
206
- end
207
-
208
- def identifier=(node)
209
- @nodes[1] = node
210
- end
211
-
212
- def expression
213
- @nodes[2]
214
- end
215
-
216
- def expression=(node)
217
- @nodes[2] = node
218
- end
219
- end
220
-
221
- class IdentifierDefinitionNode < ListNode
222
- def initialize(_ = nil)
223
- super("define", 3)
224
- end
225
-
226
- def type
227
- :identifier_definition
228
- end
229
-
230
- def identifier
231
- @nodes[1]
232
- end
233
-
234
- def identifier=(node)
235
- @nodes[1] = node
236
- end
237
-
238
- def expression
239
- @nodes[2]
240
- end
241
-
242
- def expression=(node)
243
- @nodes[2] = node
244
- end
245
-
246
- def def_formals
247
- if lambda?
248
- expression.formals
249
- else
250
- nil
251
- end
252
- end
253
-
254
- def body
255
- if lambda?
256
- expression.body
257
- else
258
- nil
259
- end
260
- end
261
-
262
- private
263
-
264
- def lambda?
265
- expression.type == :lambda_expression
266
- end
267
-
268
- end
269
-
270
- class SyntaxDefinitionNode < ListNode
271
- def type
272
- :syntax_definition
273
- end
274
-
275
- end
276
-
277
- class ValuesDefinitionNode < ListNode
278
- def type
279
- :values_definition
280
- end
281
-
282
- end
283
-
284
- class RecordTypeDefinitionNode < ListNode
285
- def type
286
- :record_type_definition
287
- end
288
-
289
- end
290
-
291
- class MacroBlockNode < ListNode
292
- def initialize(literal)
293
- super(literal)
294
- end
295
-
296
- def type
297
- :macro_block
298
- end
299
-
300
- end
301
-
302
- class CondNode < ListNode
303
- def initialize(_ = nil)
304
- super("cond")
305
- end
306
-
307
- def type
308
- :cond
309
- end
310
-
311
- def cond_clauses
312
- @nodes[1..-1]
313
- end
314
-
315
- def add_clause(node)
316
- @nodes << node
317
- end
318
- end
319
-
320
- class CondClauseNode < ListNode
321
- def initialize(_ = nil)
322
- super(nil, 1)
323
- end
324
-
325
- def type
326
- :cond_clause
327
- end
328
-
329
- def test
330
- @nodes[0]
331
- end
332
-
333
- def test=(node)
334
- @nodes[0] = node
335
- end
336
-
337
- def sequence
338
- @nodes[1..-1]
339
- end
340
-
341
- def add_expression(node)
342
- @nodes << node
343
- end
344
- end
345
-
346
- class LetNode < ListNode
347
- def initialize(_ = nil)
348
- super("let", 2)
349
- end
350
-
351
- def type
352
- :let
353
- end
354
-
355
- def bind_specs
356
- @nodes[1]
357
- end
358
-
359
- def bind_specs=(node)
360
- @nodes[1] = node
361
- end
362
-
363
- def body
364
- @nodes[2..-1]
365
- end
366
-
367
- def body=(nodes)
368
- nodes.each_with_index { |node, i|
369
- @nodes[i + 2] = node
370
- }
371
- end
372
- end
373
-
374
- class BindSpecNode < ListNode
375
- def initialize(_ = nil)
376
- super(nil, 2)
377
- end
378
-
379
- def type
380
- :bind_spec
381
- end
382
-
383
- def identifier
384
- @nodes[1]
385
- end
386
-
387
- def identifier=(node)
388
- @nodes[1] = node
389
- end
390
-
391
- def expression
392
- @nodes[2]
393
- end
394
-
395
- def expression=(node)
396
- @nodes[2] = node
397
- end
398
- end
399
-
400
- class AndNode < ListNode
401
- def initialize(_ = nil)
402
- super("and")
403
- end
404
-
405
- def type
406
- :and
407
- end
408
-
409
- end
410
-
411
- end
412
- end