theta 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +20 -20
- data/README.rdoc +3 -2
- data/VERSION +1 -1
- data/lib/theta/environment.rb +3 -0
- data/lib/theta/interpreter.rb +19 -7
- data/lib/theta/library/add.scm +3 -3
- data/lib/theta/library/divide.scm +3 -3
- data/lib/theta/library/lambda.scm +39 -0
- data/lib/theta/library/multiply.scm +3 -3
- data/lib/theta/library/subtract.scm +3 -3
- data/lib/theta/parser.rb +46 -8
- data/theta.gemspec +3 -2
- metadata +12 -11
data/Gemfile.lock
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
git (1.2.5)
|
5
|
-
jeweler (1.5.2)
|
6
|
-
bundler (~> 1.0.0)
|
7
|
-
git (>= 1.2.5)
|
8
|
-
rake
|
9
|
-
rake (0.8.7)
|
10
|
-
rcov (0.9.9)
|
11
|
-
shoulda (2.11.3)
|
12
|
-
|
13
|
-
PLATFORMS
|
14
|
-
x86-mingw32
|
15
|
-
|
16
|
-
DEPENDENCIES
|
17
|
-
bundler (~> 1.0.0)
|
18
|
-
jeweler (~> 1.5.2)
|
19
|
-
rcov
|
20
|
-
shoulda
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
git (1.2.5)
|
5
|
+
jeweler (1.5.2)
|
6
|
+
bundler (~> 1.0.0)
|
7
|
+
git (>= 1.2.5)
|
8
|
+
rake
|
9
|
+
rake (0.8.7)
|
10
|
+
rcov (0.9.9)
|
11
|
+
shoulda (2.11.3)
|
12
|
+
|
13
|
+
PLATFORMS
|
14
|
+
x86-mingw32
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
bundler (~> 1.0.0)
|
18
|
+
jeweler (~> 1.5.2)
|
19
|
+
rcov
|
20
|
+
shoulda
|
data/README.rdoc
CHANGED
@@ -15,8 +15,9 @@ After installation, simply type theta to get to the interactive interpreter prom
|
|
15
15
|
2
|
16
16
|
theta> (+ a 3)
|
17
17
|
5
|
18
|
-
theta> (
|
19
|
-
|
18
|
+
theta> (define square (lambda (x) (* x x)))
|
19
|
+
theta> (square 3)
|
20
|
+
9
|
20
21
|
|
21
22
|
To exit, simply press enter on a blank line.
|
22
23
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/lib/theta/environment.rb
CHANGED
data/lib/theta/interpreter.rb
CHANGED
@@ -2,9 +2,11 @@ module Theta
|
|
2
2
|
# interpret scheme code
|
3
3
|
class Interpreter
|
4
4
|
|
5
|
+
attr_accessor :current_environment
|
6
|
+
|
5
7
|
#initialize the environment and the parser
|
6
8
|
def initialize
|
7
|
-
@global_environment = Environment.new
|
9
|
+
@global_environment = @current_environment = Environment.new
|
8
10
|
@parser = Parser.new
|
9
11
|
load_library
|
10
12
|
end
|
@@ -37,23 +39,33 @@ module Theta
|
|
37
39
|
end
|
38
40
|
|
39
41
|
# evaluate the scheme expression
|
40
|
-
def evaluate(expression
|
42
|
+
def evaluate(expression)
|
41
43
|
if expression.is_a? Symbol
|
42
|
-
return
|
44
|
+
return @current_environment.find(expression)
|
43
45
|
elsif not expression.is_a? Array
|
44
46
|
return expression
|
45
47
|
end
|
48
|
+
|
49
|
+
if expression.count == 1
|
50
|
+
if expression.is_a? Symbol
|
51
|
+
return @current_environment.find(expression[0])
|
52
|
+
else
|
53
|
+
return expression[0]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
46
57
|
case expression[0]
|
47
58
|
when :define
|
48
|
-
return
|
59
|
+
return @current_environment.define(expression [1], evaluate(expression[2]))
|
49
60
|
when :ruby_func
|
50
61
|
return eval expression[1]
|
51
62
|
else
|
52
|
-
function = evaluate(expression[0]
|
53
|
-
if function.
|
63
|
+
function = evaluate(expression[0])
|
64
|
+
if function.is_a? Proc
|
54
65
|
arguments = expression[1, expression.length]
|
55
|
-
function.call(arguments, self)
|
66
|
+
return function.call(arguments, self)
|
56
67
|
else
|
68
|
+
raise RuntimeError, "#{expression[0]} is not a function"
|
57
69
|
end
|
58
70
|
end
|
59
71
|
end
|
data/lib/theta/library/add.scm
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
(
|
1
|
+
(define +
|
2
2
|
(ruby_func "
|
3
3
|
lambda { |arguments, interpreter|
|
4
|
-
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
-
temp.inject { |result, n| result + n}
|
4
|
+
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
+
temp.inject { |result, n| result + n}
|
6
6
|
}
|
7
7
|
")
|
8
8
|
)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
(define /
|
2
2
|
(ruby_func "
|
3
3
|
lambda { |arguments, interpreter|
|
4
|
-
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
-
temp.inject { |result, n| result / n}
|
4
|
+
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
+
temp.inject { |result, n| result / n}
|
6
6
|
}
|
7
7
|
")
|
8
|
-
)
|
8
|
+
)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
(define lambda
|
2
|
+
(ruby_func "
|
3
|
+
lambda { |arguments, interpreter|
|
4
|
+
parameters = arguments[0]
|
5
|
+
body = arguments[1, arguments.length]
|
6
|
+
if parameters.is_a? Array
|
7
|
+
if parameters.length != parameters.uniq.length
|
8
|
+
raise 'Parameters declared more than once'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
lambda_environment = Theta::Environment.new(interpreter.current_environment)
|
13
|
+
|
14
|
+
execute = lambda { |body, environment, interpreter|
|
15
|
+
interpreter.current_environment = environment
|
16
|
+
result = nil
|
17
|
+
body.each do |expression|
|
18
|
+
result = interpreter.evaluate(expression)
|
19
|
+
end
|
20
|
+
interpreter.current_environment = environment.parent
|
21
|
+
return result
|
22
|
+
}
|
23
|
+
if parameters.is_a? Array
|
24
|
+
lambda { |arguments, interpreter|
|
25
|
+
parameters.each_index do |x|
|
26
|
+
lambda_environment.define(parameters[x], interpreter.evaluate(arguments[x]))
|
27
|
+
end
|
28
|
+
execute.call(body, lambda_environment, interpreter)
|
29
|
+
}
|
30
|
+
elsif parameters.is_a? Symbol
|
31
|
+
lambda { |arguments, interpreter|
|
32
|
+
arguments.map! { |x| interpreter.evaluate(x) }
|
33
|
+
lambda_environment.define(parameters, arguments)
|
34
|
+
execute.call(body, lambda_environment, interpreter)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
}
|
38
|
+
")
|
39
|
+
)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
(define *
|
2
2
|
(ruby_func "
|
3
3
|
lambda { |arguments, interpreter|
|
4
|
-
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
-
temp.inject { |result, n| result * n}
|
4
|
+
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
+
temp.inject { |result, n| result * n}
|
6
6
|
}
|
7
7
|
")
|
8
|
-
)
|
8
|
+
)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
(define -
|
2
2
|
(ruby_func "
|
3
3
|
lambda { |arguments, interpreter|
|
4
|
-
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
-
temp.inject { |result, n| result - n}
|
4
|
+
temp = arguments.map { |item| interpreter.evaluate(item) }
|
5
|
+
temp.inject { |result, n| result - n}
|
6
6
|
}
|
7
7
|
")
|
8
|
-
)
|
8
|
+
)
|
data/lib/theta/parser.rb
CHANGED
@@ -9,7 +9,48 @@ module Theta
|
|
9
9
|
|
10
10
|
# converts a string into an array of tokens
|
11
11
|
def tokenize(string)
|
12
|
-
|
12
|
+
tokens = []
|
13
|
+
found_string = false
|
14
|
+
temp = ""
|
15
|
+
string.each_char do |char|
|
16
|
+
if found_string
|
17
|
+
if char == "\""
|
18
|
+
found_string = false
|
19
|
+
temp << char
|
20
|
+
if not temp.empty?
|
21
|
+
tokens << temp
|
22
|
+
end
|
23
|
+
temp = ""
|
24
|
+
else
|
25
|
+
temp << char
|
26
|
+
end
|
27
|
+
else
|
28
|
+
if char == "(" || char == ")"
|
29
|
+
if not temp.empty?
|
30
|
+
tokens << temp
|
31
|
+
temp = ""
|
32
|
+
end
|
33
|
+
tokens << char
|
34
|
+
next
|
35
|
+
elsif char == "\""
|
36
|
+
found_string = true
|
37
|
+
temp << char
|
38
|
+
elsif char == " "
|
39
|
+
if not temp.empty?
|
40
|
+
tokens << temp
|
41
|
+
end
|
42
|
+
temp = ""
|
43
|
+
elsif char == "\t" || char == "\n"
|
44
|
+
if not temp.empty?
|
45
|
+
tokens << temp
|
46
|
+
end
|
47
|
+
temp = ""
|
48
|
+
else
|
49
|
+
temp << char
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return tokens
|
13
54
|
end
|
14
55
|
|
15
56
|
# reads an expression from an array of tokens (created
|
@@ -18,6 +59,7 @@ module Theta
|
|
18
59
|
if tokens.length == 0
|
19
60
|
raise SyntaxError, "unexpected EOF while reading"
|
20
61
|
end
|
62
|
+
tokens.delete_if { |item| item.strip == "" || item == []}
|
21
63
|
token = tokens.shift
|
22
64
|
if "(" == token
|
23
65
|
l = []
|
@@ -28,13 +70,8 @@ module Theta
|
|
28
70
|
return l
|
29
71
|
elsif ")" == token
|
30
72
|
raise SyntaxError, "unexpected )"
|
31
|
-
elsif "\""
|
32
|
-
|
33
|
-
until tokens[0] == "\""
|
34
|
-
string += " " + tokens.shift
|
35
|
-
end
|
36
|
-
tokens.shift
|
37
|
-
return string.gsub(/\n/, "")
|
73
|
+
elsif token.start_with?("\"")
|
74
|
+
return token.gsub("\"", "")
|
38
75
|
else
|
39
76
|
return atom(token)
|
40
77
|
end
|
@@ -43,6 +80,7 @@ module Theta
|
|
43
80
|
# returns appropriate numeric object if a number,
|
44
81
|
# otherwise returns a symbol
|
45
82
|
def atom(token)
|
83
|
+
token.gsub!(/\n\t/, "")
|
46
84
|
begin
|
47
85
|
return Integer(token)
|
48
86
|
rescue ArgumentError
|
data/theta.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{theta}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Chris O'Neal"]
|
12
|
-
s.date = %q{2011-03-
|
12
|
+
s.date = %q{2011-03-29}
|
13
13
|
s.description = %q{Theta was created as a learning project based off of lis.py and flea}
|
14
14
|
s.email = %q{ctoneal@gmail.com}
|
15
15
|
s.executables = ["theta", "theta"]
|
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/theta/interpreter.rb",
|
32
32
|
"lib/theta/library/add.scm",
|
33
33
|
"lib/theta/library/divide.scm",
|
34
|
+
"lib/theta/library/lambda.scm",
|
34
35
|
"lib/theta/library/multiply.scm",
|
35
36
|
"lib/theta/library/subtract.scm",
|
36
37
|
"lib/theta/parser.rb",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: theta
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-03-
|
12
|
+
date: 2011-03-29 00:00:00.000000000 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: shoulda
|
17
|
-
requirement: &
|
17
|
+
requirement: &9486048 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *9486048
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: bundler
|
28
|
-
requirement: &
|
28
|
+
requirement: &9485316 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: 1.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *9485316
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: jeweler
|
39
|
-
requirement: &
|
39
|
+
requirement: &9484296 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 1.5.2
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *9484296
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: rcov
|
50
|
-
requirement: &
|
50
|
+
requirement: &9479136 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *9479136
|
59
59
|
description: Theta was created as a learning project based off of lis.py and flea
|
60
60
|
email: ctoneal@gmail.com
|
61
61
|
executables:
|
@@ -79,6 +79,7 @@ files:
|
|
79
79
|
- lib/theta/interpreter.rb
|
80
80
|
- lib/theta/library/add.scm
|
81
81
|
- lib/theta/library/divide.scm
|
82
|
+
- lib/theta/library/lambda.scm
|
82
83
|
- lib/theta/library/multiply.scm
|
83
84
|
- lib/theta/library/subtract.scm
|
84
85
|
- lib/theta/parser.rb
|
@@ -100,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
101
|
version: '0'
|
101
102
|
segments:
|
102
103
|
- 0
|
103
|
-
hash:
|
104
|
+
hash: 1029420371
|
104
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
106
|
none: false
|
106
107
|
requirements:
|