Skip to content

Commit cf711df

Browse files
committed
Add minimal interpreter implementation in Ruby
Also, convert the interpreter test cases to Ruby
1 parent 8b073c5 commit cf711df

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

ports-r/scheme.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
require_relative "parser"
2+
3+
module Scheme
4+
GLOBAL_ENV = {
5+
:+ => proc { |a, b| a + b },
6+
:* => proc { |a, b| a * b }
7+
}
8+
9+
def evaluate(tokens)
10+
if tokens.is_a?(String)
11+
tokens
12+
elsif tokens.is_a?(Numeric)
13+
tokens
14+
elsif tokens.is_a?(Array)
15+
token = tokens.shift
16+
procedure = evaluate(token)
17+
procedure.call(
18+
*(tokens.map { |t| evaluate(t) })
19+
)
20+
elsif tokens.is_a?(Symbol)
21+
GLOBAL_ENV[tokens]
22+
end
23+
end
24+
25+
def evaluate_string(source)
26+
Scheme.evaluate(Parser.parse_string(source))
27+
end
28+
29+
module_function :evaluate_string, :evaluate
30+
end

ports-r/semantic-tests.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
require "json"
2+
require "pathname"
3+
4+
# Helper function to check if result matches expected output
5+
def matches(result, target)
6+
if target.is_a?(Hash) && target.key?("type")
7+
return result.is_a?(StandardError)
8+
end
9+
10+
if target.is_a?(Array)
11+
return false unless result.is_a?(Array)
12+
return false unless result.length == target.length
13+
14+
match = true
15+
target.each_with_index do |t, i|
16+
match &&= matches(result[i], t)
17+
end
18+
return match
19+
end
20+
21+
if result.is_a?(Symbol)
22+
return result.to_s == target
23+
end
24+
25+
result == target
26+
end
27+
28+
# Get current directory
29+
dirname = File.dirname(__FILE__)
30+
31+
# Load test cases
32+
test_table = []
33+
begin
34+
tests_path1 = File.join(dirname, "../ports/lispy-tests.json")
35+
tests_path2 = File.join(dirname, "../ports/lispy-tests2.json")
36+
37+
tests1 = JSON.parse(File.read(tests_path1))
38+
test_table.concat(tests1)
39+
40+
tests2 = JSON.parse(File.read(tests_path2))
41+
test_table.concat(tests2)
42+
rescue => error
43+
puts "Error loading test files: #{error.message}"
44+
exit(1)
45+
end
46+
47+
# Import the scheme module - assuming it's defined in a Ruby file
48+
require_relative "scheme"
49+
50+
# Run tests
51+
test_table.each do |entry|
52+
input = entry["input"]
53+
54+
begin
55+
eval_result = Scheme.evaluate_string(input)
56+
rescue => error
57+
eval_result = error
58+
end
59+
60+
if matches(eval_result, entry["expected"])
61+
puts "✅: #{input}"
62+
else
63+
puts "❌: #{input} got #{eval_result}[#{eval_result.class}] instead of #{entry["expected"]}[#{entry["expected"].class}]"
64+
end
65+
end

0 commit comments

Comments
 (0)