rubylisp 1.0.2 → 1.0.3

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
  SHA1:
3
- metadata.gz: bb5f9ceceb5366ea22a1684c23f1f891baff4ee9
4
- data.tar.gz: 4dcf3352fe2c53178012846dd428a55e25e6ff5e
3
+ metadata.gz: 766ad09a55015bc092208b72f53402b9d937449a
4
+ data.tar.gz: 3861fd772f1f62324bf636387c5cc8ba73ce89a6
5
5
  SHA512:
6
- metadata.gz: 8b6a30a4b7811e1c08bd49710de04c17ac2cce55a0bd9cd375e5f71c58c386c7c0a70c1335c79cb40d55fc558e06812568b48990b178f39fb0b0264451f5db30
7
- data.tar.gz: 8cd9f89766f14601094794fa31404629e5780ce5072ad95abfd346b4733152c7962fa68c17234e475247458e7d65a93985ab7a6fe4bd61ff769c1df60c9293c2
6
+ metadata.gz: ec857ef3a5c1c82446acf3dffd9a0a90c2b355bf528b2c50e8aeb879b6eeeffd14566fa28bdbcedd272da3de746da3da6f503fecaa831fa08169330ad07c634c
7
+ data.tar.gz: cebd6a7be2904d8f7390d5bd05162b5d92e7092fba83ee73e76945042c493674704af1f4aaad734fb215f78b2b72f7ad948e44d5cb12f9f8d31436ab5d4d7dea
@@ -1,8 +1,15 @@
1
1
  module Lisp
2
2
 
3
+
4
+ def self.named_let_stack
5
+ @@named_let_stack ||= Array.new
6
+ end
7
+
8
+
3
9
  class Initializer
4
10
 
5
11
  def self.initialize_global_environment
12
+ $named_let_stack = []
6
13
  Lisp::EnvironmentFrame.global.bind(Symbol.named("nil"), nil)
7
14
  end
8
15
 
@@ -248,6 +248,7 @@ module Lisp
248
248
  def evaluate(env)
249
249
  return self if empty?
250
250
  sexpr = if @car.symbol?
251
+ throw :named_let_application, @cdr.to_a.map {|a| a.evaluate(env)} if @car.eq?(Lisp.named_let_stack[-1])
251
252
  key = @car
252
253
  frame = nth(1)
253
254
  value = nth(2)
@@ -348,9 +348,9 @@ module Lisp
348
348
  end
349
349
 
350
350
 
351
- def self.let_impl(args, env)
351
+ def self.common_let_impl(args, env)
352
352
  bindings = args.car || Lisp::ConsCell.new
353
- return Lisp::Debug.process_error("let requires a list of bindings as it's firest argument", env) unless bindings.list?
353
+ return Lisp::Debug.process_error("let requires a list of bindings as it's first argument", env) unless bindings.list?
354
354
  local_frame = EnvironmentFrame.extending(env, "let")
355
355
  local_frame.previous = env
356
356
  do_let_bindings(bindings, env, local_frame)
@@ -358,6 +358,39 @@ module Lisp
358
358
  end
359
359
 
360
360
 
361
+ def self.named_let_impl(args, env)
362
+ name = args.car
363
+ bindings = args.cadr || Lisp::ConsCell.new
364
+ binding_names = bindings.to_a.map {|b| b.car}
365
+ return Lisp::Debug.process_error("named let requires a list of bindings as it's second argument", env) unless bindings.list?
366
+ body = args.cddr
367
+ local_frame = EnvironmentFrame.extending(env, "let-#{name.to_s}")
368
+ local_frame.previous = env
369
+ do_let_bindings(bindings, env, local_frame)
370
+ Lisp.named_let_stack.push(name)
371
+ while true
372
+ new_values = catch :named_let_application do
373
+ result = body.evaluate_each(local_frame)
374
+ Lisp.named_let_stack.pop
375
+ return result
376
+ end
377
+ return Lisp::Debug.process_error("named let call requires the same number of values as bindings", env) unless binding_names.length == new_values.length
378
+ binding_names.zip(new_values) do |binding_pair|
379
+ local_frame.bind_locally(binding_pair[0], binding_pair[1])
380
+ end
381
+ end
382
+ end
383
+
384
+
385
+ def self.let_impl(args, env)
386
+ if args.car.symbol?
387
+ named_let_impl(args, env)
388
+ else
389
+ common_let_impl(args, env)
390
+ end
391
+ end
392
+
393
+
361
394
  def self.letstar_impl(args, env)
362
395
  bindings = args.car || Lisp::ConsCell.new
363
396
  return Lisp::Debug.process_error("let requires a list of bindings as it's firest argument", env) unless bindings.list?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubylisp
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Astels