theta 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|