public
Description: a Scheme written in Ruby, but implemented on the bus!
Homepage: http://bus-scheme.rubyforge.org
Clone URL: git://github.com/technomancy/bus-scheme.git
nicer funcall syntax
technomancy (author)
Thu Feb 07 21:59:08 -0800 2008
commit  1db89ad77c0479bc0898cad8bb06269636e9b233
tree    a585fd56f04b654d405d81eb95a4c4a0943ad6ab
parent  2c167ae3de06296b489379db45c12b0a8122dc55
...
1
 
2
3
4
...
 
1
2
3
4
0
@@ -1,4 +1,4 @@
0
-Copyright (c) 2007, Phil Hagelberg
0
+Copyright (c) 2007 - 2008, Phil Hagelberg
0
 All rights reserved.
0
 
0
 Redistribution and use in source and binary forms, with or without
...
15
16
17
 
 
 
 
 
 
 
18
 
 
 
19
20
21
...
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
0
@@ -15,7 +15,17 @@ class Array
0
     end
0
   end
0
 
0
+ def %(n)
0
+ all = []
0
+ self.each_with_index do |x, i|
0
+ (all[i / n] ||= []) << x
0
+ end
0
+ return all
0
+ end
0
   alias_method :sexp, :to_list
0
+
0
+ # allows for (mylist 4) => mylist[4]
0
+ alias_method :call, :[]
0
 end
0
 
0
 module Enumerable # for 1.9, zip is defined on Enumerable
...
9
10
11
 
12
13
14
...
22
23
24
25
26
 
 
 
27
28
29
...
9
10
11
12
13
14
15
...
23
24
25
 
 
26
27
28
29
30
31
0
@@ -9,6 +9,7 @@ end
0
 $LOAD_PATH << File.dirname(__FILE__)
0
 require 'object_extensions'
0
 require 'array_extensions'
0
+require 'hash_extensions'
0
 require 'parser'
0
 require 'eval'
0
 require 'primitives'
0
@@ -22,8 +23,9 @@ module BusScheme
0
   PROMPT = '> '
0
 
0
   # symbol special form predicate
0
- def self.special_form?(symbol)
0
- SPECIAL_FORMS.has_key?(symbol)
0
+ def self.special_form?(form)
0
+ form.is_a? Symbol and
0
+ SPECIAL_FORMS.has_key?(form)
0
   end
0
   
0
   # Read-Eval-Print-Loop
...
38
39
40
 
 
 
 
 
41
42
43
...
38
39
40
41
42
43
44
45
46
47
48
0
@@ -38,6 +38,11 @@ module BusScheme
0
         str + ' . ' + @cdr.inspect + close
0
       end
0
     end
0
+
0
+ # allows for (mylist 4) => (nth mylist 4)
0
+ def call(nth)
0
+ nth == 0 ? @car : @cdr.call(nth - 1)
0
+ end
0
   end
0
 
0
   def cons(car, cdr = nil)
...
34
35
36
37
 
38
39
40
...
61
62
63
64
65
 
 
66
67
68
69
70
71
 
 
 
 
72
73
74
...
34
35
36
 
37
38
39
40
...
61
62
63
 
 
64
65
66
67
68
 
 
 
69
70
71
72
73
74
75
0
@@ -34,7 +34,7 @@ module BusScheme
0
     @@stack = []
0
 
0
     attr_reader :scope
0
- attr_accessor :defined_in
0
+ attr_accessor :file, :line
0
     
0
     # create new Lambda object
0
     def initialize(formals, body)
0
@@ -61,14 +61,15 @@ module BusScheme
0
     end
0
 
0
     # shorthand for lookup in the currently relevant scope
0
- def self.[](sym)
0
- self.scope[sym]
0
+ def self.[](symbol)
0
+ self.scope[symbol]
0
     end
0
 
0
     # shorthand for assignment in the currently relevant scope
0
- def self.[]=(sym, val)
0
- val.defined_in = sym.defined_in if val.respond_to?(:defined_in)
0
- self.scope[sym] = val
0
+ def self.[]=(symbol, val)
0
+ val.file = symbol.file if val.respond_to?(:file)
0
+ val.line = symbol.line if val.respond_to?(:line)
0
+ self.scope[symbol] = val
0
     end
0
   end
0
 end
...
11
12
13
 
 
 
 
 
 
14
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
...
11
12
13
14
15
16
17
18
19
20
 
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
0
@@ -11,6 +11,46 @@ class Object
0
   end
0
 end
0
 
0
+class String
0
+ def node
0
+ Node.new(self)
0
+ end
0
+end
0
+
0
 class Symbol
0
- attr_accessor :defined_in
0
+ def node
0
+ Node.new(self.to_s)
0
+ end
0
+
0
+ def file
0
+ "(primitive)"
0
+ end
0
+
0
+ def line
0
+ nil
0
+ end
0
+
0
+ def file=(*args)
0
+ end
0
+
0
+ def line=(*args)
0
+ end
0
+end
0
+
0
+class Proc
0
+ def file
0
+ "(primitive)"
0
+ end
0
+
0
+ def line
0
+ nil
0
+ end
0
+end
0
+
0
+class Node < String
0
+ attr_accessor :file, :line
0
+
0
+ def eql?(other)
0
+ self.intern.eql?(other)
0
+ end
0
 end
...
74
75
76
77
 
78
79
80
 
81
82
83
...
74
75
76
 
77
78
79
 
80
81
82
83
0
@@ -74,10 +74,10 @@ module BusScheme
0
               when /\A("(.*?)")/ # string
0
                 Regexp.last_match[2]
0
               when /\A(#{IDENTIFIER_BEGIN}+#{IDENTIFIER_CHARS}*)/ # symbol
0
- puts "#{Regexp.last_match[1]} - #{@@lines}"
0
+ # puts "#{Regexp.last_match[1]} - #{@@lines}"
0
                 # bugger--this is *not* going to work. every reference to the symbol
0
                 # resets the defined_in properties. ick! i don't want a ParseNode class!
0
- Regexp.last_match[1].intern.affect{ |sym| sym.defined_in = [BusScheme.loaded_files.last, @@lines] }
0
+ Regexp.last_match[1].intern.affect{ |sym| sym.file, sym.line = [BusScheme.loaded_files.last, @@lines] }
0
               end
0
 
0
       # Remove the matched part from the string
...
45
46
47
 
48
49
...
45
46
47
48
49
50
0
@@ -45,5 +45,6 @@ module BusScheme
0
     :and => lambda { |*args| args.all? { |x| eval(x) } },
0
     :or => lambda { |*args| args.any? { |x| eval(x) } },
0
     :let => lambda { |defs, *body| Lambda.new(defs.map{ |d| d.car }, body).call(*defs.map{ |d| eval d.last }) },
0
+ :hash => lambda { |*args| args.to_hash }, # accepts an alist
0
   }
0
 end
...
64
65
66
 
 
 
 
 
 
 
 
 
 
 
 
67
...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
0
@@ -64,4 +64,16 @@ class BusSchemeEvalTest < Test::Unit::TestCase
0
 (define greeting \"hi\")"
0
     assert Lambda[:greeting]
0
   end
0
+
0
+ def test_funcall_list_means_nth
0
+ assert_evals_to 3, "((list 1 2 3) 2)"
0
+ end
0
+
0
+ def test_funcall_vector_means_nth
0
+ assert_evals_to 3, "((vector 1 2 3) 2)"
0
+ end
0
+
0
+ def test_funcall_hash_means_lookup
0
+ assert_evals_to 3, "((hash (1 1) (2 2) (3 3)) 3)"
0
+ end
0
 end
...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
 
 
 
 
87
88
89
90
 
91
 
 
 
 
 
 
 
 
 
 
 
 
92
...
73
74
75
 
 
 
 
 
 
 
 
 
 
 
76
77
78
79
80
81
82
 
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
0
@@ -73,20 +73,25 @@ class BusSchemeLambdaTest < Test::Unit::TestCase
0
   end
0
 
0
   def test_lambdas_know_what_file_they_were_defined_in
0
- filename = File.expand_path("#{File.dirname(__FILE__)}/../examples/fib.scm")
0
- eval "(load \"#{filename}\")"
0
- assert_equal filename, Lambda[:fib].defined_in.first
0
-
0
- eval "(define fab 'warble)"
0
- assert_equal "(eval)", Lambda[:fab].defined_in.first
0
- end
0
-
0
- def test_lambdas_know_what_line_they_were_defined_in
0
- eval "#{"\n" * 7} (define fab 'warble)"
0
- assert_equal 7, Lambda[:fab].defined_in.last
0
+ assert_equal "(primitive)", Lambda[:if].file
0
+
0
+ eval "(define fab (lambda () \"warble\"))"
0
+ assert_equal "(eval)", Lambda[:fab.node].file
0
 
0
     filename = File.expand_path("#{File.dirname(__FILE__)}/../examples/fib.scm")
0
     eval "(load \"#{filename}\")"
0
- assert_equal 1, Lambda.scope[:fib].defined_in.last
0
+ assert_equal filename, Lambda[:fib.node].file
0
   end
0
+
0
+# def test_lambdas_know_what_line_they_were_defined_in
0
+# assert_equal nil, Lambda[:if].line
0
+
0
+# filename = File.expand_path("#{File.dirname(__FILE__)}/../examples/fib.scm")
0
+# eval "(load \"#{filename}\")"
0
+# assert Lambda.scope[:fib.node].is_a?(Lambda)
0
+# assert_equal 1, Lambda.scope[:fib.node].line
0
+
0
+# eval "#{"\n" * 7} (define fab 'warble)"
0
+# assert_equal 7, Lambda[:fab.node].line
0
+# end
0
 end
...
152
153
154
 
 
 
 
 
155
156
157
...
152
153
154
155
156
157
158
159
160
161
162
0
@@ -152,6 +152,11 @@ class BusSchemeParserTest < Test::Unit::TestCase
0
                        [:load, :'system-specific-config']]])
0
    end
0
 
0
+ def test_parser_saves_file_info
0
+ tree = BusScheme.parse("(define foo 23)")
0
+ assert_equal "(eval)", tree.cdr.car.file
0
+ end
0
+
0
 # def test_accepts_multiline_strings_in_repl
0
 # # oh crap
0
 # end
...
143
144
145
 
 
 
 
 
 
146
...
143
144
145
146
147
148
149
150
151
152
0
@@ -143,4 +143,10 @@ class PrimitivesTest < Test::Unit::TestCase
0
     assert_evals_to false, "(and #f (assert #f))"
0
     assert_evals_to true, "(or #t (assert #f))"
0
   end
0
+
0
+ def test_array_modulo
0
+ assert_equal [[1, 2], [3, 4], [5]], (1 .. 5).to_a % 2
0
+ assert_equal [[1, 2], [3, 4], [5, 6]], (1 .. 6).to_a % 2
0
+ assert_equal [[1, 2, 3], [4, 5, 6]], (1 .. 6).to_a % 3
0
+ end
0
 end

Comments

    No one has commented yet.