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 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: