rus3 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
- VERSION = "0.1.0"
24
+ REPL_VERSION = "0.2.0"
25
25
 
26
26
  class << self
27
27
 
28
28
  # Starts REPL.
29
- def start(verbose: false)
30
- repl = Repl.new(verbose: verbose)
29
+ def start(parser: nil, evaluator: nil, verbose: false)
30
+ repl = Repl.new(parser: parser, 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,
39
- :evaluator => Evaluator,
40
- :printer => nil,
38
+ :parser => Parser::DEFAULT_PARSER,
39
+ :evaluator => Evaluator::DEFAULT_EVALUATOR,
40
+ :printer => nil,
41
41
  }
42
42
 
43
43
  # Prompt for input.
@@ -49,14 +49,20 @@ module Rus3
49
49
  @@value_history = [] # :nodoc:
50
50
 
51
51
  attr_accessor :verbose # :nodoc:
52
+ attr_accessor :prompt # :nodoc:
52
53
 
53
- def initialize(verbose: false)
54
- COMPONENTS.each { |name, klass|
54
+ def initialize(parser: nil, evaluator: nil, verbose: false)
55
+ comps = COMPONENTS.dup
56
+
57
+ comps[:parser] = Parser.const_get("#{parser.capitalize}Parser") if parser
58
+ comps[:evaluator] = Evaluator.const_get("#{evaluator.capitalize}Evaluator") if evaluator
59
+
60
+ comps.each { |name, klass|
55
61
  instance_variable_set("@#{name}", klass.nil? ? self : klass.new)
56
62
  }
57
63
 
58
64
  @prompt = PROMPT
59
- @parser.prompt = PROMPT unless @parser.nil?
65
+ @parser.prompt = PROMPT
60
66
 
61
67
  @verbose = verbose
62
68
  @evaluator.verbose = verbose
@@ -73,15 +79,15 @@ module Rus3
73
79
  def loop
74
80
  msg = Kernel.loop { # LOOP
75
81
  begin
76
- exp = @parser.read(STDIN) # READ
82
+ ast = @parser.read(STDIN) # READ
77
83
  rescue SchemeSyntaxError => e
78
84
  puts "ERROR" + (@verbose ? "(READ)" : "") + ": %s" % e
79
85
  next
80
86
  end
81
- break FAREWELL_MESSAGE if exp.nil?
87
+ break FAREWELL_MESSAGE if ast.nil?
82
88
 
83
89
  begin
84
- value = @evaluator.eval(exp) # EVAL
90
+ value = @evaluator.eval(ast) # EVAL
85
91
  rescue SyntaxError, StandardError => e
86
92
  puts "ERROR" + (@verbose ? "(EVAL)" : "") + ": %s" % e
87
93
  next
@@ -96,15 +102,20 @@ module Rus3
96
102
 
97
103
  # Shows the greeting message.
98
104
  def greeting
99
- puts "A simple REPL for Rus3:"
100
- puts "- Rus3 version: #{Rus3::VERSION} (#{Rus3::RELEASE})"
105
+ puts "A simple REPL to run Rus3:"
101
106
  return unless @verbose
102
107
 
103
- puts " - REPL version: #{VERSION}"
108
+ vmsg = "(rus3 :version #{Rus3::VERSION} :release #{Rus3::RELEASE}\n"
109
+ vmsg += " (repl :version #{REPL_VERSION}\n"
110
+
111
+ comp_vmsgs = []
104
112
  COMPONENTS.keys.each { |comp_name|
105
- Kernel.print " - "
106
- print_version(comp_name)
113
+ comp_vmsgs << " (#{version_message(comp_name)})"
107
114
  }
115
+ vmsg += comp_vmsgs.join("\n")
116
+ vmsg += "))"
117
+
118
+ puts vmsg
108
119
  end
109
120
 
110
121
  # :stopdoc:
@@ -117,8 +128,8 @@ module Rus3
117
128
  Readline::readline(@prompt, true)
118
129
  end
119
130
 
120
- def eval(exp)
121
- exp
131
+ def eval(ast)
132
+ ast
122
133
  end
123
134
 
124
135
  def print(obj)
@@ -130,12 +141,21 @@ module Rus3
130
141
 
131
142
  private
132
143
 
144
+ def version_message(comp_name)
145
+ vmsg = nil
146
+ component = instance_variable_get("@#{comp_name}")
147
+ if component.nil? or component == self
148
+ vmsg = ":using :built-in :#{comp_name}"
149
+ else
150
+ vmsg = "#{component.version}"
151
+ end
152
+ vmsg
153
+ end
154
+
133
155
  def define_constants # :nodoc:
134
156
  return if @evaluator.nil?
135
157
 
136
- r = @evaluator.binding.receiver
137
-
138
- r.instance_eval {
158
+ @evaluator.instance_eval {
139
159
  self.class.const_set(:RUS3_VERSION, "#{VERSION}")
140
160
  }
141
161
  end
@@ -143,9 +163,7 @@ module Rus3
143
163
  def define_help_feature # :nodoc:
144
164
  return if @evaluator.nil?
145
165
 
146
- r = @evaluator.binding.receiver
147
-
148
- r.instance_eval {
166
+ @evaluator.instance_eval {
149
167
  def _help
150
168
  puts <<HELP
151
169
  A simple REPL for Rus3.
@@ -167,10 +185,8 @@ HELP
167
185
  def define_history_feature # :nodoc:
168
186
  return if @evaluator.nil?
169
187
 
170
- r = @evaluator.binding.receiver
171
-
172
- r.instance_variable_set(:@value_history, @@value_history)
173
- r.instance_eval {
188
+ @evaluator.instance_variable_set(:@value_history, @@value_history)
189
+ @evaluator.instance_eval {
174
190
 
175
191
  def _last_value
176
192
  @value_history[-1]
@@ -201,30 +217,24 @@ HELP
201
217
  def define_load_feature
202
218
  return if @evaluator.nil?
203
219
 
204
- r = @evaluator.binding.receiver
205
-
206
- r.instance_variable_set(:@scm_parser, Parser::SchemeParser.new)
207
- r.instance_eval {
220
+ @evaluator.instance_variable_set(:@scm_parser, @parser)
221
+ @evaluator.instance_variable_set(:@scm_evaluator, @evaluator)
222
+ @evaluator.instance_eval {
208
223
  def load_scm(path)
209
224
  raise Rus3::CannotFindFileError, path unless FileTest.exist?(path)
210
- scm_source = nil
211
- File.open(path, "r") {|f| scm_source = f.readlines(chomp: true)}
212
- s_exp = scm_source.join(" ")
213
- r_exp = @scm_parser.parse(s_exp)
214
- self.binding.eval(r_exp)
225
+ scheme_source = File.readlines(path, chomp: true).join(" ")
226
+ result = ast = nil
227
+ if @scm_parser.respond_to?(:parse)
228
+ ast = @scm_parser.parse(scheme_source)
229
+ end
230
+ if @scm_evaluator.respond_to?(:eval)
231
+ result = @scm_evaluator.eval(ast)
232
+ end
233
+ pp result
215
234
  end
216
235
  }
217
236
  end
218
237
 
219
- def print_version(comp_name)
220
- component = instance_variable_get("@#{comp_name}")
221
- if component.nil? or component == self
222
- puts "using built-in #{comp_name.upcase}"
223
- else
224
- puts "#{component.version}"
225
- end
226
- end
227
-
228
238
  def history_push(value)
229
239
  prev_value = @@value_history[-1]
230
240
  if prev_value != value and UNDEF != value
data/lib/rus3/token.rb ADDED
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rus3
4
+
5
+ TOKEN_TYPES = [ # :nodoc:
6
+ # delimiters
7
+ :lparen, # `(`
8
+ :rparen, # `)`
9
+ :vec_lparen, # `#(`
10
+ :bytevec_lparen, # `#u8(`
11
+ :quotation, # `'`
12
+ :backquote, # "`" (aka quasiquote)
13
+ :comma, # `,`
14
+ :comma_at, # `,@`
15
+ :dot, # `.`
16
+ :semicolon, # `;`
17
+ :comment_lparen, # `#|`
18
+ :comment_rparen, # `|#`
19
+ # value types
20
+ :identifier, # `foo`
21
+ :boolean, # `#f` or `#t` (`#false` or `#true`)
22
+ :number, # `123`, `456.789`, `1/2`, `3+4i`
23
+ :character, # `#\a`
24
+ :string, # `"hoge"`
25
+ # operators
26
+ :op_proc, # `+`, `-`, ...
27
+ # control
28
+ :illegal,
29
+ ]
30
+
31
+ Token = Struct.new(:type, :literal) {
32
+ alias :to_s :literal
33
+ }
34
+
35
+ end
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.1.2"
5
- RELEASE = "2021-04-23"
4
+ VERSION = "0.2.0"
5
+ RELEASE = "2021-05-03"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rus3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mnbi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-23 00:00:00.000000000 Z
11
+ date: 2021-05-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby with Syntax Sugar of Scheme
14
14
  email:
@@ -33,12 +33,19 @@ files:
33
33
  - examples/iota.scm
34
34
  - exe/rus3
35
35
  - 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
36
40
  - lib/rus3/char.rb
37
41
  - lib/rus3/error.rb
38
42
  - lib/rus3/evaluator.rb
43
+ - lib/rus3/evaluator/environment.rb
44
+ - lib/rus3/evaluator/scheme_evaluator.rb
45
+ - lib/rus3/evaluator/translator.rb
46
+ - lib/rus3/lexer.rb
39
47
  - lib/rus3/pair.rb
40
48
  - lib/rus3/parser.rb
41
- - lib/rus3/parser/lexer.rb
42
49
  - lib/rus3/parser/scheme_parser.rb
43
50
  - lib/rus3/port.rb
44
51
  - lib/rus3/printer.rb
@@ -50,6 +57,7 @@ files:
50
57
  - lib/rus3/procedure/vector.rb
51
58
  - lib/rus3/procedure/write.rb
52
59
  - lib/rus3/repl.rb
60
+ - lib/rus3/token.rb
53
61
  - lib/rus3/vector.rb
54
62
  - lib/rus3/version.rb
55
63
  - rus3.gemspec