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 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> (- 6 a)
19
- 4
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.0
1
+ 0.1.1
@@ -2,6 +2,9 @@ module Theta
2
2
  # An environment, stores defined items for a
3
3
  # particular level
4
4
  class Environment
5
+
6
+ attr_accessor :parent
7
+
5
8
  def initialize(parent = nil)
6
9
  @parent = parent
7
10
  @table = {}
@@ -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, environment=@global_environment)
42
+ def evaluate(expression)
41
43
  if expression.is_a? Symbol
42
- return environment.find(expression)
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 environment.define(expression [1], evaluate(expression[2], environment))
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], environment)
53
- if function.lambda?
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
@@ -1,8 +1,8 @@
1
- ( define +
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
- return string.gsub("(", " ( ").gsub(")", " ) ").split
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 "\"" == token
32
- string = ""
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.0"
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-28}
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.0
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-28 00:00:00.000000000 -05:00
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: &7590828 !ruby/object:Gem::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: *7590828
25
+ version_requirements: *9486048
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: bundler
28
- requirement: &7589724 !ruby/object:Gem::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: *7589724
36
+ version_requirements: *9485316
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: jeweler
39
- requirement: &7588884 !ruby/object:Gem::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: *7588884
47
+ version_requirements: *9484296
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rcov
50
- requirement: &7588152 !ruby/object:Gem::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: *7588152
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: -350340689
104
+ hash: 1029420371
104
105
  required_rubygems_version: !ruby/object:Gem::Requirement
105
106
  none: false
106
107
  requirements: