Переглянути джерело

Allow recursive functions & closures

master
Dylan Baker 5 роки тому
джерело
коміт
1954d89211

+ 1
- 1
lib/chervil/ast/application.rb Переглянути файл

19
         if function.nil?
19
         if function.nil?
20
           ::Chervil::Error.new("Unbound variable #{@expr.name}")
20
           ::Chervil::Error.new("Unbound variable #{@expr.name}")
21
         else
21
         else
22
-          function.call(@arguments.map { |arg| arg.evaluate(env) })
22
+          function.call(@arguments.map { |arg| arg.evaluate(env) }, env)
23
         end
23
         end
24
       end
24
       end
25
     end
25
     end

+ 1
- 2
lib/chervil/ast/function.rb Переглянути файл

18
       self
18
       self
19
     end
19
     end
20
 
20
 
21
-    def call(args)
21
+    def call(args, env)
22
       unless @params.size == args.size
22
       unless @params.size == args.size
23
         raise "Expected #{params.size} arguments but received #{args.size}"
23
         raise "Expected #{params.size} arguments but received #{args.size}"
24
       end
24
       end
25
 
25
 
26
-      env = ::Chervil::Env.new
27
       @params.zip(args).each do |key, value|
26
       @params.zip(args).each do |key, value|
28
         env.set(key.name, value)
27
         env.set(key.name, value)
29
       end
28
       end

+ 2
- 1
spec/ast/function_spec.rb Переглянути файл

17
             )
17
             )
18
           ],
18
           ],
19
         ).call(
19
         ).call(
20
-          [AST::Number.new(5.0)]
20
+          [AST::Number.new(5.0)],
21
+          Env.new
21
         )
22
         )
22
       ).to eq(25.0)
23
       ).to eq(25.0)
23
     end
24
     end

+ 1
- 1
spec/env_spec.rb Переглянути файл

2
   RSpec.describe Env do
2
   RSpec.describe Env do
3
     it 'has arithmetic from core' do
3
     it 'has arithmetic from core' do
4
       env = Env.new
4
       env = Env.new
5
-      expect(env.get("+").call([1, 2])).to eq(3)
5
+      expect(env.get("+").call([1, 2], env)).to eq(3)
6
     end
6
     end
7
 
7
 
8
     it 'inherits from parent env' do
8
     it 'inherits from parent env' do

+ 13
- 0
spec/interpreter_spec.rb Переглянути файл

12
       expect(env.get("x")).to eq(AST::Number.new(5.0))
12
       expect(env.get("x")).to eq(AST::Number.new(5.0))
13
       expect(interpret('x', env).first).to eq(5.0)
13
       expect(interpret('x', env).first).to eq(5.0)
14
     end
14
     end
15
+
16
+    it 'interprets a recursive function' do
17
+      env = Env.new
18
+      interpret('(define (fact x) (if (= x 0) 1 (* x (fact (- x 1)))))', env)
19
+      expect(interpret('(fact 5)', env).first).to eq(120.0)
20
+    end
21
+
22
+    it 'supports closures' do
23
+      env = Env.new
24
+      interpret('(define one 1)', env)
25
+      interpret('(define (plus-one x) (+ x one))', env)
26
+      expect(interpret('(plus-one 2)', env).first).to eq(3.0)
27
+    end
15
   end
28
   end
16
 end
29
 end

Завантаження…
Відмінити
Зберегти