-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheval.rb
93 lines (81 loc) · 2.71 KB
/
eval.rb
1
2
3
4
5
6
7
8
9
10
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
require_relative 'lang/errors'
require_relative 'lang/builtinfunctions'
require_relative 'lang/environment'
module Eval
def self.eval(environment, userinput)
case userinput
when SchemeSymbol
symbol = environment.get(userinput)
raise UndefinedVariableError.new(userinput.value) unless symbol != nil
return symbol
when SchemeCons
return self.eval_cons(environment, userinput)
when SchemeNil
return nil
#else
# raise SchemeInternalError.new("Unimplemented eval: #{input.class}")
end
return userinput
end
def self.eval_cons(environment, cons)
function = self.eval(environment, cons.car)
function_arguments = cons.cdr
case function
when BuiltinFunction
return self.eval_builtin_function(environment, function, function_arguments)
when BuiltinSyntax
return self.eval_builtin_syntax(environment, function, function_arguments)
when UserdefinedFunction
return self.eval_user_function(environment, function, function_arguments)
else
raise SchemeSyntaxError.new("#{function} is not a function")
end
end
def self.eval_builtin_syntax(environment, function, function_arguments)
args = []
loop do
args << function_arguments.car
break if function_arguments.cdr.class == SchemeNil
function_arguments = function_arguments.cdr
end
return function.work(environment, args)
end
def self.eval_builtin_function(environment, function, function_arguments)
args = []
loop do
args << self.eval(environment, function_arguments.car)
break if function_arguments.cdr.class == SchemeNil
function_arguments = function_arguments.cdr
end
return function.work(environment, args)
end
def self.eval_user_syntax(environment, function, args)
raise Exception.new('Not yet implemented')
end
def self.eval_user_function(environment, function, function_arguments)
# Create argument List
args = []
loop do
args << self.eval(environment, function_arguments.car)
break if function_arguments.cdr.class == SchemeNil
function_arguments = function_arguments.cdr
end
if args.size != function.number_of_arguments
raise SchemeArgumentNumberError.new(function.name, function.number_of_arguments, args.size)
end
# Create a new environment for function and map parameters to arguments
local_env = Environment.new(environment)
i = 0
while i < args.size
local_env.put(function.parameter[i], args[i])
i+=1
end
result = nil
# Eval each function in UDF
function.function.each do |f|
result = self.eval(local_env, f)
end
# Return the last evaled result of the function
return result
end
end