Skip to content

Commit cc9e587

Browse files
author
sathish
committed
Added another sample
1 parent 68e29ab commit cc9e587

File tree

1 file changed

+150
-113
lines changed

1 file changed

+150
-113
lines changed

lisp.rb

+150-113
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,177 @@
1-
21
class Lisp
32

4-
@definitions = {}
5-
@variables={}
6-
7-
def self.evaluate(operation, operands, scopes)
8-
9-
operands = operands.map{|operand| fetchVariableValue(operand, scopes)}
10-
result = 0
11-
if operation == '+'
12-
result = operands.reduce{|a,b| a.to_i+b.to_i}
13-
elsif operation == '-'
14-
result = operands.reduce{|a,b| a.to_i-b.to_i}
15-
elsif operation == '*'
16-
result = operands.reduce{|a,b| a.to_i*b.to_i}
17-
elsif operation == '/'
18-
result = operands.reduce{|a,b| a.to_i/b.to_i}
19-
else
20-
result = evaluateByDefinition(operation, operands)
3+
def self.parse(input)
4+
tokens = input.split
5+
i = 0
6+
@definitions = {"" => {}}
7+
@variables = {"" => {}}
8+
while i < tokens.size do
9+
token = tokens[i]
10+
if token == 'define' and tokens[i+1] == '('
11+
i,name = parseDefinitions(tokens,i,"")
12+
elsif token == 'define'
13+
@variables[""].update(tokens[i+1] => tokens[i+2])
14+
i = i + 2
15+
elsif token != '(' and token != ')'
16+
result, i = executeStmt(tokens,i,[""],{})
17+
end
18+
i = i + 1
2119
end
22-
return result
20+
result
2321
end
2422

25-
def self.fetchVariableValue(var,scopes)
26-
value = nil
27-
scopes.each{|scope| value = variables[scope][var] if( variables[scope][var] != nil}
23+
def self.parseDefinitions(tokens, i, scope_name)
24+
method_name = tokens[i+2]
25+
current_scope = scope_name+"."+method_name
26+
@definitions = @definitions.merge({current_scope => {}})
27+
private_definitions = {}
28+
params = []
29+
i = i + 3
30+
token = tokens[i]
2831

29-
if(value != nil)
30-
return value
31-
else
32-
return var
33-
end
32+
while true do
33+
token = tokens[i]
34+
if token == ')'
35+
break
36+
end
37+
params.push(token)
38+
i = i + 1
3439
end
3540

36-
def self.evaluateByDefinition(operation, operands)
37-
if @definitions.include? operation
38-
param = @definitions[operation][0]
39-
stmt = @definitions[operation][1]
40-
i = 0
41-
while i < param.size do
42-
stmt = stmt.sub(param[i],operands[i])
43-
i = i + 1
44-
end
45-
46-
return execute(stmt)
41+
i = i + 1
42+
token = tokens[i]
43+
stmts = []
44+
45+
count = -1
46+
while true do
47+
token = tokens[i]
48+
if token == 'define' and tokens[i+1] == '('
49+
i,name = parseDefinitions(tokens,i, current_scope)
50+
private_definitions.update(name => current_scope)
51+
@definitions[current_scope][name][2] = @definitions[current_scope][name][2].merge(private_definitions)
52+
elsif token == ')' and count == 0
53+
break
54+
elsif token == '('
55+
count = count + 1
56+
stmts.push(token)
57+
elsif token == ')'
58+
count = count - 1
59+
stmts.push(token)
4760
else
48-
puts "Unexpected operation"
49-
return 0
61+
stmts.push(token)
5062
end
63+
i = i + 1
5164
end
65+
i = i + 1
66+
stmts.push(token)
67+
@definitions[scope_name] = @definitions[scope_name].merge({method_name => [params, stmts, private_definitions]})
68+
return i,method_name
69+
end
5270

53-
def self.execute(input)
54-
tokens = input.split
55-
56-
operands = []
57-
operation = tokens[1]
58-
i = 2
59-
while i < tokens.size do
60-
token = tokens[i]
61-
62-
if token == '('
63-
temp_tokens = []
64-
temp_tokens.push(token)
65-
while token != ')'
66-
i = i +1
67-
token = tokens[i]
68-
temp_tokens.push(token)
69-
end
70-
operands.push(execute(temp_tokens.join(' ')))
71-
elsif token != ')'
72-
operands.push(token);
73-
end
74-
prevToken = token
75-
i = i + 1
76-
end
77-
return evaluate(operation,operands)
78-
end
71+
def self.executeStmt(tokens,i, scopes, private_definitions)
7972

80-
def self.parse(scope_name, input)
81-
tokens = input.split
82-
i = 0
83-
@definitions = {"" => {}}
84-
while i < tokens.size do
85-
token = tokens[i]
86-
if token == 'define'
87-
i = parseDefinitions(tokens,i,"")
88-
end
89-
i = i + 1
73+
while true
74+
if tokens[i] == "("
75+
i = i +1
76+
else
77+
break
9078
end
91-
@definitions
9279
end
9380

94-
def self.parseDefinitions(tokens, i, scope_name)
95-
method_name = tokens[i+2]
96-
@definitions.merge({scope_name+"."+method_name => {}})
97-
params = []
98-
i = i + 3
81+
puts "executing stmt = " + tokens[i]
82+
83+
operands = []
84+
operation = tokens[i]
85+
i = i + 1
86+
while true do
9987
token = tokens[i]
10088

101-
while true do
102-
token = tokens[i]
103-
if token == ')'
104-
break
105-
end
106-
params.push(token)
107-
i = i + 1
89+
if token == '('
90+
operand,i=executeStmt(tokens,i + 1, scopes, private_definitions)
91+
operands.push(operand)
92+
elsif token != ')'
93+
operands.push(token)
94+
elsif token == ')'
95+
break
10896
end
109-
11097
i = i + 1
111-
token = tokens[i]
112-
stmts = []
113-
114-
count = 0
115-
while true do
116-
token = tokens[i]
117-
if token == 'define'
118-
i = parseDefinitions(tokens,i,scope_name+"."+method_name)
119-
elsif token == ')' and count == 0
120-
break
121-
elsif token == '('
122-
count = count + 1
123-
elsif token == ')'
124-
count = count - 1
125-
end
126-
stmts.push(token)
127-
i = i + 1
98+
end
99+
return evaluate(operation,operands,scopes, private_definitions),i
100+
end
101+
102+
def self.evaluate(operation, operands, scopes, private_definition)
103+
104+
if operation == 'define'
105+
@variables[scopes.last].update(operands[0] => operands[1])
106+
result = 0
107+
else
108+
109+
operands = operands.map{|operand| fetchVariableValue(operand, scopes)}
110+
if operation == '+'
111+
result = operands.reduce{|a,b| a.to_i + b.to_i}
112+
elsif operation == '-'
113+
result = operands.reduce{|a,b| a.to_i - b.to_i}
114+
elsif operation == '*'
115+
result = operands.reduce{|a,b| a.to_i * b.to_i}
116+
elsif operation == '/'
117+
result = operands.reduce{|a,b| a.to_i / b.to_i}
118+
else
119+
result = evaluateByDefinition(operation, operands, scopes, private_definition)
128120
end
129-
stmts.push(token)
130-
@definitions[scope_name] = @definitions[scope_name].merge({method_name => [params, stmts.join(' ')]})
131-
return i
132121
end
133122

134-
def self.definitions
135-
@definitions
123+
puts "scopes " + scopes.join(',').to_s
124+
puts "operation " + operation.to_s
125+
puts "operands " + operands.join(',').to_s
126+
puts "result " + result.to_s
127+
128+
return result
129+
end
130+
131+
def self.evaluateByDefinition(operation, operands, scopes, private_definitions)
132+
function_scope = ""
133+
if private_definitions.include? operation
134+
function_scope = private_definitions[operation]
135+
end
136+
if @definitions[function_scope].include? operation
137+
params = @definitions[function_scope][operation][0]
138+
stmt = @definitions[function_scope][operation][1]
139+
private_definitions = @definitions[function_scope][operation][2]
140+
@variables.update({operation => {}})
141+
params.each_with_index{|param,i| @variables[operation].update({param => operands[i]})}
142+
scopes.push(operation)
143+
result,i = executeStmt(stmt,1, scopes, private_definitions)
144+
while(i < stmt.size - 2) do
145+
result,i = executeStmt(stmt,i + 1, scopes, private_definitions)
146+
end
147+
scopes.delete(operation)
148+
return result
149+
else
150+
puts "Unexpected operation" + operation
151+
return 0
136152
end
153+
end
137154

155+
def self.fetchVariableValue(var,scopes)
156+
result = nil
157+
scopes.each{|scope| result = @variables[scope][var] if @variables[scope][var] != nil}
158+
if(result != nil)
159+
return result
160+
else
161+
return var
138162
end
163+
end
164+
165+
def self.definitions
166+
@definitions
167+
end
168+
169+
def self.variables
170+
@variables
171+
end
172+
173+
174+
end
139175

140-
Lisp.parse("( define ( add a b ) ( + a b ) )")
176+
Lisp.parse("( define ( fun1 a b c ) ( define ( fun2 a f ) ( * a f ) ) ( define x 1 ) ( + a b ( - b c ) ( fun2 c b ) a x ) ) ( define x 11 ) ( + x ( fun1 1 2 3 ) )")
177+
Lisp.parse("( define ( sum-of-square x y ) ( + ( square x ) ( square y ) ) ( define ( square x ) ( * x x ) ) ( sum-of-square 3 4 )")

0 commit comments

Comments
 (0)