Skip to content

Commit 3c547c1

Browse files
committed
Make some style changes and rename variable to tokens
1 parent 73a8f7d commit 3c547c1

File tree

1 file changed

+73
-72
lines changed

1 file changed

+73
-72
lines changed

ports-rb/scheme.rb

Lines changed: 73 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def initialize(params, args, outer_environment = nil)
1111
@env = {params => args}
1212
else
1313
raise "expected #{params.length} arguments, got #{args.length}" unless params.length == args.length
14+
1415
@env = params.zip(args).to_h
1516
end
1617
end
@@ -68,80 +69,78 @@ def call(*args)
6869
:length => :length.to_proc,
6970
:not => proc { |a| !a },
7071
:null? => proc { |a| a.nil? || a.empty? },
71-
:pair? => proc { |x| x.is_a?(Array) && !x.empty? },
72+
:pair? => proc { |tokens| tokens.is_a?(Array) && !tokens.empty? },
7273
:sqrt => proc { |a| Math.sqrt(a) }
7374
}.entries.transpose
7475
GLOBAL_ENV = Environment.new(GLOBAL_DICT[0], GLOBAL_DICT[1])
7576

7677
# Helper methods for expand
77-
def is_pair(x)
78-
x.is_a?(Array) && !x.empty?
78+
def pair?(tokens)
79+
tokens.is_a?(Array) && !tokens.empty?
7980
end
8081

81-
def to_string(x)
82-
case x
82+
def to_string(tokens)
83+
case tokens
8384
when true then "#t"
8485
when false then "#f"
85-
when Symbol then x.to_s
86-
when String then "\"#{x.gsub('"', '\"')}\""
87-
when Array then "(#{x.map { |e| to_string(e) }.join(" ")})"
88-
else x.to_s
86+
when Symbol then tokens.to_s
87+
when String then "\"#{tokens.gsub('"', '\"')}\""
88+
when Array then "(#{tokens.map { |e| to_string(e) }.join(" ")})"
89+
else tokens.to_s
8990
end
9091
end
9192

92-
def require_syntax(x, predicate, msg = "wrong length")
93-
raise "#{to_string(x)}: #{msg}" unless predicate
93+
def require_syntax(tokens, predicate, msg = "wrong length")
94+
raise "#{to_string(tokens)}: #{msg}" unless predicate
9495
end
9596

9697
# Main expand function
97-
def expand(x, toplevel = false)
98+
def expand(tokens, toplevel: false)
9899
# Check for empty list
99-
require_syntax(x, !(x.is_a?(Array) && x.empty?))
100+
require_syntax(tokens, !(tokens.is_a?(Array) && tokens.empty?))
100101

101102
# Constant/non-list => unchanged
102-
return x unless x.is_a?(Array)
103+
return tokens unless tokens.is_a?(Array)
103104

104-
case x.first
105+
case tokens.first
105106
when :include
106107
# (include string1 string2 ...)
107-
require_syntax(x, x.length > 1)
108-
expand_include(x)
108+
require_syntax(tokens, tokens.length > 1)
109+
expand_include(tokens)
109110
when :quote
110111
# (quote exp)
111-
require_syntax(x, x.length == 2)
112-
x
112+
require_syntax(tokens, tokens.length == 2)
113+
tokens
113114
when :if
114115
# (if test conseq) => (if test conseq nil)
115-
if x.length == 3
116-
x += [nil]
117-
end
118-
require_syntax(x, x.length == 4)
119-
x.map { |xi| expand(xi) }
116+
tokens += [nil] if tokens.length == 3
117+
require_syntax(tokens, tokens.length == 4)
118+
tokens.map { |token| expand(token) }
120119
when :set
121120
# (set! var exp)
122-
require_syntax(x, x.length == 3)
123-
var = x[1]
124-
require_syntax(x, var.is_a?(Symbol), "can set! only a symbol")
125-
[:set!, var, expand(x[2])]
121+
require_syntax(tokens, tokens.length == 3)
122+
var = tokens[1]
123+
require_syntax(tokens, var.is_a?(Symbol), "can set! only a symbol")
124+
[:set!, var, expand(tokens[2])]
126125
when :define, :"define-macro"
127126
# Check correct length
128-
require_syntax(x, x.length >= 3)
127+
require_syntax(tokens, tokens.length >= 3)
129128

130-
token, v, body = x[0], x[1], x[2..]
129+
token, v, body = tokens[0], tokens[1], tokens[2..]
131130

132131
if v.is_a?(Array) && !v.empty?
133132
# (define (f args) body) => (define f (lambda (args) body))
134133
f, *args = v
135134
expand([token, f, [:lambda, args] + body])
136135
else
137-
require_syntax(x, x.length == 3, "wrong length in definition")
138-
require_syntax(x, v.is_a?(Symbol), "can define only a symbol")
139-
exp = expand(x[2])
136+
require_syntax(tokens, tokens.length == 3, "wrong length in definition")
137+
require_syntax(tokens, v.is_a?(Symbol), "can define only a symbol")
138+
exp = expand(tokens[2])
140139

141140
if token == :"define-macro"
142-
require_syntax(x, toplevel, "define-macro only allowed at top level")
141+
require_syntax(tokens, toplevel, "define-macro only allowed at top level")
143142
proc = evaluate(exp)
144-
require_syntax(x, proc.respond_to?(:call), "macro must be a procedure")
143+
require_syntax(tokens, proc.respond_to?(:call), "macro must be a procedure")
145144
MACRO_TABLE[v] = proc
146145
return nil
147146
end
@@ -150,84 +149,80 @@ def expand(x, toplevel = false)
150149
end
151150
when :begin
152151
# (begin exp*)
153-
return nil if x.length == 1
154-
x.map { |xi| expand(xi, toplevel) }
152+
return nil if tokens.length == 1
153+
154+
tokens.map { |token| expand(token, toplevel: toplevel) }
155155
when :lambda
156156
# (lambda (vars) exp1 exp2...)
157-
require_syntax(x, x.length >= 3)
157+
require_syntax(tokens, tokens.length >= 3)
158158

159-
vars, *body = x[1..]
159+
vars, *body = tokens[1..]
160160

161161
# Check that vars is a symbol or list of symbols
162162
is_valid_vars = vars.is_a?(Symbol) ||
163163
(vars.is_a?(Array) && vars.all? { |v| v.is_a?(Symbol) })
164-
require_syntax(x, is_valid_vars, "illegal lambda argument list")
164+
require_syntax(tokens, is_valid_vars, "illegal lambda argument list")
165165

166166
# Wrap multiple expressions in begin
167167
exp = (body.length == 1) ? body[0] : [:begin] + body
168168
[:lambda, vars, expand(exp)]
169169
when :quasiquote
170170
# `x => expand_quasiquote(x)
171-
require_syntax(x, x.length == 2)
172-
expand_quasiquote(x[1])
171+
require_syntax(tokens, tokens.length == 2)
172+
expand_quasiquote(tokens[1])
173173
when :cond
174174
# (cond (test exp) ...)
175-
expanded_clauses = x[1..].map do |clause|
176-
require_syntax(x, clause.is_a?(Array) && clause.length == 2,
175+
expanded_clauses = tokens[1..].map do |clause|
176+
require_syntax(tokens, clause.is_a?(Array) && clause.length == 2,
177177
"Invalid cond clause format")
178178
[expand(clause[0]), expand(clause[1])]
179179
end
180180
[:cond] + expanded_clauses
181181
else
182182
# Check for macro expansion
183-
if x.first.is_a?(Symbol) && MACRO_TABLE.key?(x.first)
183+
if tokens.first.is_a?(Symbol) && MACRO_TABLE.key?(tokens.first)
184184
# (m arg...) => macroexpand if m is a macro
185-
expand(MACRO_TABLE[x.first].call(*x[1..]), toplevel)
185+
expand(MACRO_TABLE[tokens.first].call(*tokens[1..]), toplevel: toplevel)
186186
else
187187
# (f arg...) => expand each
188-
x.map { |xi| expand(xi) }
188+
tokens.map { |token| expand(token) }
189189
end
190190
end
191191
end
192192

193193
# Expand quasiquote expression
194-
def expand_quasiquote(x)
194+
def expand_quasiquote(tokens)
195195
# 'x => 'x
196-
unless is_pair(x)
197-
return [:quote, x]
198-
end
196+
return [:quote, tokens] unless pair?(tokens)
199197

200198
# Check for invalid splicing
201-
require_syntax(x, x[0] != :"unquote-splicing", "can't splice here")
199+
require_syntax(tokens, tokens[0] != :"unquote-splicing", "can't splice here")
202200

203-
if x[0] == :unquote
201+
if tokens[0] == :unquote
204202
# ,x => x
205-
require_syntax(x, x.length == 2)
206-
x[1]
207-
elsif is_pair(x[0]) && x[0][0] == :"unquote-splicing"
203+
require_syntax(tokens, tokens.length == 2)
204+
tokens[1]
205+
elsif pair?(tokens[0]) && tokens[0][0] == :"unquote-splicing"
208206
# (,@x y) => (append x y)
209-
require_syntax(x[0], x[0].length == 2)
210-
[:append, x[0][1], expand_quasiquote(x[1..])]
207+
require_syntax(tokens[0], tokens[0].length == 2)
208+
[:append, tokens[0][1], expand_quasiquote(tokens[1..])]
211209
else
212210
# `(x . y) => (cons `x `y)
213-
[:cons, expand_quasiquote(x[0]), expand_quasiquote(x[1..])]
211+
[:cons, expand_quasiquote(tokens[0]), expand_quasiquote(tokens[1..])]
214212
end
215213
end
216214

217215
# Expand include directive
218-
def expand_include(x)
216+
def expand_include(tokens)
219217
result = [:begin]
220218

221-
x[1..].each do |file_name|
219+
tokens[1..].each do |file_name|
222220
File.open(file_name, "r") do |include_file|
223221
content = include_file.read
224222
include_result = Parser.parse_string(content)
223+
raise "Could not include content of #{file_name}" unless include_result
225224

226-
if include_result
227-
result << expand(include_result, true)
228-
else
229-
raise SchemeException, "Could not include content of #{file_name}"
230-
end
225+
result << expand(include_result, true)
231226
end
232227
end
233228

@@ -270,6 +265,7 @@ def evaluate(tokens, environment = GLOBAL_ENV)
270265
case tokens.first
271266
when :if
272267
raise "`if` expected 3 arguments, got #{tokens.length - 1}" unless tokens.length == 4
268+
273269
condition = evaluate(tokens[1], environment)
274270
tokens = condition ? tokens[2] : tokens[3]
275271

@@ -283,11 +279,15 @@ def evaluate(tokens, environment = GLOBAL_ENV)
283279

284280
when :quote
285281
raise "`quote` expected 1 argument, got #{tokens.length - 1}" unless tokens.length == 2
282+
286283
return tokens[1]
287284

288285
when :lambda
289286
raise "`lambda` expected 2 argument, got #{tokens.length - 1}" unless tokens.length == 3
290-
raise "invalid argument list (expected symbol or list of symbols)" if !tokens[1].is_a?(Symbol) && !(tokens[1].is_a?(Array) && tokens[1].all? { |t| t.is_a?(Symbol) })
287+
if !tokens[1].is_a?(Symbol) && !(tokens[1].is_a?(Array) && tokens[1].all? { |t| t.is_a?(Symbol) })
288+
raise "invalid argument list (expected symbol or list of symbols)"
289+
end
290+
291291
return Procedure.new(tokens[1], tokens[2], environment)
292292

293293
when :begin
@@ -303,7 +303,7 @@ def evaluate(tokens, environment = GLOBAL_ENV)
303303
return
304304

305305
when :cond
306-
branch = tokens[1..].find do |(test, expression)|
306+
branch = tokens[1..].find do |(test, _)|
307307
test == :else || evaluate(test, environment)
308308
end
309309
return if branch.nil?
@@ -329,10 +329,10 @@ def evaluate(tokens, environment = GLOBAL_ENV)
329329
end
330330

331331
def evaluate_string(source)
332-
Scheme.evaluate(Scheme.expand(Parser.parse_string(source), true))
332+
Scheme.evaluate(Scheme.expand(Parser.parse_string(source), toplevel: true))
333333
end
334334

335-
module_function :evaluate_string, :evaluate, :expand, :is_pair, :require_syntax,
335+
module_function :evaluate_string, :evaluate, :expand, :pair?, :require_syntax,
336336
:expand_quasiquote, :expand_include, :let_macro, :to_string
337337

338338
# Get current directory
@@ -341,8 +341,9 @@ def evaluate_string(source)
341341
begin
342342
stdlib = File.join(dirname, "../ports/stdlib.scm")
343343
evaluate_string(File.read(stdlib))
344-
rescue => error
345-
puts "Error loading standard library: #{error.message}"
344+
rescue => e
345+
puts e.backtrace
346+
puts "Error loading standard library: #{e.message}"
346347
exit(1)
347348
end
348349
end

0 commit comments

Comments
 (0)