flea 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/.gitignore +1 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +274 -0
  4. data/Rakefile +36 -0
  5. data/VERSION +1 -0
  6. data/bin/flea +39 -0
  7. data/examples/guess-the-number.scm +18 -0
  8. data/flea-language-spec/README.rdoc +3 -0
  9. data/flea-language-spec/flea-language-spec.yaml +2 -0
  10. data/flea-language-spec/test-cases/01-display-and-basic-literals/01-display-string-literal.scm +5 -0
  11. data/flea-language-spec/test-cases/01-display-and-basic-literals/02-display-integer-literal.scm +5 -0
  12. data/flea-language-spec/test-cases/01-display-and-basic-literals/03-display-boolean-true-literal.scm +5 -0
  13. data/flea-language-spec/test-cases/01-display-and-basic-literals/04-display-boolean-false-literal.scm +5 -0
  14. data/flea-language-spec/test-cases/01-display-and-basic-literals/05-display-list-literal-using-quote.scm +5 -0
  15. data/flea-language-spec/test-cases/01-display-and-basic-literals/06-display-identifier-quoted.scm +5 -0
  16. data/flea-language-spec/test-cases/02-variables/01-define-with-string.scm +6 -0
  17. data/flea-language-spec/test-cases/02-variables/02-define-with-integer.scm +6 -0
  18. data/flea-language-spec/test-cases/02-variables/03-define-with-boolean-true.scm +6 -0
  19. data/flea-language-spec/test-cases/02-variables/04-define-with-boolean-false.scm +6 -0
  20. data/flea-language-spec/test-cases/02-variables/05-define-with-list.scm +6 -0
  21. data/flea-language-spec/test-cases/03-basic-built-in-procedures/01-addition.scm +5 -0
  22. data/flea-language-spec/test-cases/03-basic-built-in-procedures/02-subtraction.scm +5 -0
  23. data/flea-language-spec/test-cases/03-basic-built-in-procedures/03-multiplication.scm +5 -0
  24. data/flea-language-spec/test-cases/03-basic-built-in-procedures/04-division.scm +5 -0
  25. data/flea-language-spec/test-cases/03-basic-built-in-procedures/05-equality-true-integer.scm +5 -0
  26. data/flea-language-spec/test-cases/03-basic-built-in-procedures/06-equality-false-integer.scm +5 -0
  27. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/01-equal?-true-integer.scm +5 -0
  28. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/02-equal?-false-integer.scm +5 -0
  29. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/03-equal?-true-string.scm +5 -0
  30. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/04-equal?-false-string.scm +5 -0
  31. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/05-equal?-true-boolean.scm +5 -0
  32. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/06-equal?-false-boolean.scm +5 -0
  33. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/07-equal?-true-list.scm +7 -0
  34. data/flea-language-spec/test-cases/03-basic-built-in-procedures/07-equal?/08-equal?-false-list.scm +7 -0
  35. data/flea-language-spec/test-cases/04-comma-quoting/01-comma-quoting.scm +5 -0
  36. data/flea-language-spec/test-cases/05-lambda/01-lambda.scm +5 -0
  37. data/flea-language-spec/test-cases/05-lambda/02-call-in-place-lambda.scm +5 -0
  38. data/flea-language-spec/test-cases/05-lambda/03-define-with-lambda.scm +6 -0
  39. data/flea-language-spec/test-cases/05-lambda/04-define-and-call-lambda.scm +8 -0
  40. data/flea-language-spec/test-cases/05-lambda/05-lambda-repeated-argument.scm +9 -0
  41. data/flea-language-spec/test-cases/05-lambda/06-lambda-list-argument.scm +8 -0
  42. data/flea-language-spec/test-cases/05-lambda/07-lambda-n-or-more-arguments.scm +12 -0
  43. data/flea-language-spec/test-cases/05-lambda/08-lambda-should-return-last-result.scm +16 -0
  44. data/flea-language-spec/test-cases/06-if/01-if-true-single-arg.scm +6 -0
  45. data/flea-language-spec/test-cases/06-if/02-if-false-single-arg.scm +6 -0
  46. data/flea-language-spec/test-cases/06-if/03-if-true-two-args.scm +7 -0
  47. data/flea-language-spec/test-cases/06-if/04-if-false-two-args.scm +7 -0
  48. data/flea-language-spec/test-cases/07-set/01-should-not-set-undefined-variable.scm +5 -0
  49. data/flea-language-spec/test-cases/07-set/02-set-previously-defined-variable.scm +8 -0
  50. data/flea-language-spec/test-cases/08-derived-expressions/01-begin/01-begin.scm +8 -0
  51. data/flea-language-spec/test-cases/09-list-manipulation/01-car.scm +7 -0
  52. data/flea-language-spec/test-cases/09-list-manipulation/02-cdr.scm +7 -0
  53. data/flea-language-spec/test-cases/09-list-manipulation/03-list-tail.scm +7 -0
  54. data/flea-language-spec/test-cases/09-list-manipulation/04-append.scm +10 -0
  55. data/flea-language-spec/test-cases/09-list-manipulation/05-list.scm +5 -0
  56. data/flea-language-spec/test-cases/10-functional-examples/countdown.scm +15 -0
  57. data/lib/flea.rb +5 -0
  58. data/lib/flea/environment.rb +38 -0
  59. data/lib/flea/interpreter.rb +67 -0
  60. data/lib/flea/standard_library/addition_operator.scm +7 -0
  61. data/lib/flea/standard_library/append.scm +7 -0
  62. data/lib/flea/standard_library/begin.scm +11 -0
  63. data/lib/flea/standard_library/car.scm +7 -0
  64. data/lib/flea/standard_library/cdr.scm +7 -0
  65. data/lib/flea/standard_library/cons.scm +13 -0
  66. data/lib/flea/standard_library/display.scm +8 -0
  67. data/lib/flea/standard_library/division_operator.scm +7 -0
  68. data/lib/flea/standard_library/equality_operator.scm +8 -0
  69. data/lib/flea/standard_library/gets.scm +6 -0
  70. data/lib/flea/standard_library/greater_than.scm +8 -0
  71. data/lib/flea/standard_library/if.scm +10 -0
  72. data/lib/flea/standard_library/lambda.scm +57 -0
  73. data/lib/flea/standard_library/less_than.scm +8 -0
  74. data/lib/flea/standard_library/list.scm +8 -0
  75. data/lib/flea/standard_library/list_predicate.scm +6 -0
  76. data/lib/flea/standard_library/list_tail.scm +5 -0
  77. data/lib/flea/standard_library/multiplication_operator.scm +7 -0
  78. data/lib/flea/standard_library/null.scm +3 -0
  79. data/lib/flea/standard_library/quote.scm +6 -0
  80. data/lib/flea/standard_library/rand.scm +6 -0
  81. data/lib/flea/standard_library/read.scm +6 -0
  82. data/lib/flea/standard_library/set.scm +9 -0
  83. data/lib/flea/standard_library/string_to_num.scm +6 -0
  84. data/lib/flea/standard_library/subtraction_operator.scm +7 -0
  85. data/spec/flea/environment_spec.rb +114 -0
  86. data/spec/flea/interpreter_spec.rb +85 -0
  87. data/spec/flea/standard_library/addition_operator_spec.rb +23 -0
  88. data/spec/flea/standard_library/append_spec.rb +17 -0
  89. data/spec/flea/standard_library/begin_spec.rb +20 -0
  90. data/spec/flea/standard_library/car_spec.rb +17 -0
  91. data/spec/flea/standard_library/cdr_spec.rb +17 -0
  92. data/spec/flea/standard_library/cons_spec.rb +25 -0
  93. data/spec/flea/standard_library/display_spec.rb +36 -0
  94. data/spec/flea/standard_library/division_operator_spec.rb +29 -0
  95. data/spec/flea/standard_library/equality_operator_spec.rb +45 -0
  96. data/spec/flea/standard_library/gets_spec.rb +23 -0
  97. data/spec/flea/standard_library/greater_than_spec.rb +29 -0
  98. data/spec/flea/standard_library/if_spec.rb +59 -0
  99. data/spec/flea/standard_library/lambda_spec.rb +70 -0
  100. data/spec/flea/standard_library/less_than_spec.rb +29 -0
  101. data/spec/flea/standard_library/list_predicate_spec.rb +25 -0
  102. data/spec/flea/standard_library/list_spec.rb +24 -0
  103. data/spec/flea/standard_library/list_tail_spec.rb +17 -0
  104. data/spec/flea/standard_library/mutiplication_operator_spec.rb +23 -0
  105. data/spec/flea/standard_library/null_spec.rb +26 -0
  106. data/spec/flea/standard_library/quote_spec.rb +20 -0
  107. data/spec/flea/standard_library/rand_spec.rb +25 -0
  108. data/spec/flea/standard_library/read_spec.rb +23 -0
  109. data/spec/flea/standard_library/set_spec.rb +23 -0
  110. data/spec/flea/standard_library/string_to_num_spec.rb +28 -0
  111. data/spec/flea/standard_library/subtraction_operator_spec.rb +24 -0
  112. data/spec/spec_helper.rb +10 -0
  113. metadata +231 -0
@@ -0,0 +1,6 @@
1
+ (define x "Hello!")
2
+ (display x)
3
+
4
+ ----
5
+
6
+ assert_output "Hello!"
@@ -0,0 +1,6 @@
1
+ (define x 1)
2
+ (display x)
3
+
4
+ ----
5
+
6
+ assert_output "1"
@@ -0,0 +1,6 @@
1
+ (define x #t)
2
+ (display x)
3
+
4
+ ----
5
+
6
+ assert_output "#t"
@@ -0,0 +1,6 @@
1
+ (define x #f)
2
+ (display x)
3
+
4
+ ----
5
+
6
+ assert_output "#f"
@@ -0,0 +1,6 @@
1
+ (define x (quote ( 1 "Hello!" #t #f )))
2
+ (display x)
3
+
4
+ ----
5
+
6
+ assert_output "(1 Hello! #t #f)"
@@ -0,0 +1,5 @@
1
+ (display (+ 1 4))
2
+
3
+ ----
4
+
5
+ assert_output "5"
@@ -0,0 +1,5 @@
1
+ (display (- 10 5))
2
+
3
+ ----
4
+
5
+ assert_output "5"
@@ -0,0 +1,5 @@
1
+ (display (* 3 2))
2
+
3
+ ----
4
+
5
+ assert_output "6"
@@ -0,0 +1,5 @@
1
+ (display (/ 4 2))
2
+
3
+ ----
4
+
5
+ assert_output "2"
@@ -0,0 +1,5 @@
1
+ (display (equal? "test" "test"))
2
+
3
+ ----
4
+
5
+ assert_output "#t"
@@ -0,0 +1,5 @@
1
+ (display (equal? "test" "test2"))
2
+
3
+ ----
4
+
5
+ assert_output "#f"
@@ -0,0 +1,5 @@
1
+ (display (equal? #t #t))
2
+
3
+ ----
4
+
5
+ assert_output "#t"
@@ -0,0 +1,5 @@
1
+ (display (equal? #t #f))
2
+
3
+ ----
4
+
5
+ assert_output "#f"
@@ -0,0 +1,7 @@
1
+ (display (equal?
2
+ (quote (1 2))
3
+ (quote (1 2))))
4
+
5
+ ----
6
+
7
+ assert_output "#t"
@@ -0,0 +1,7 @@
1
+ (display (equal?
2
+ (quote (1 2))
3
+ (quote (1 3))))
4
+
5
+ ----
6
+
7
+ assert_output "#f"
@@ -0,0 +1,5 @@
1
+ (display '(1 "Hello!" #t #f))
2
+
3
+ ----
4
+
5
+ assert_output "(1 Hello! #t #f)"
@@ -0,0 +1,5 @@
1
+ (lambda (x) (+ x x))
2
+
3
+ ----
4
+
5
+ assert_execution_success
@@ -0,0 +1,5 @@
1
+ (display ((lambda (x) (+ x x)) 4))
2
+
3
+ ----
4
+
5
+ assert_output "8"
@@ -0,0 +1,6 @@
1
+ (define test_add
2
+ (lambda (x y) (+ x y)))
3
+
4
+ ----
5
+
6
+ assert_execution_success
@@ -0,0 +1,8 @@
1
+ (define test_add
2
+ (lambda (x y) (+ x y)))
3
+
4
+ (display (test_add 5 10))
5
+
6
+ ----
7
+
8
+ assert_output "15"
@@ -0,0 +1,9 @@
1
+ (lambda (b b) (display "test"))
2
+
3
+ ----
4
+
5
+ # a variable should not be able to appear
6
+ # more than once in the argument list for a
7
+ # procedure
8
+
9
+ assert_execution_failure
@@ -0,0 +1,8 @@
1
+ (define list_lambda
2
+ (lambda x (display x)))
3
+
4
+ (list_lambda 1 2 3 4)
5
+
6
+ ----
7
+
8
+ assert_output "(1 2 3 4)"
@@ -0,0 +1,12 @@
1
+ (define n_or_more
2
+ (lambda (x y . z)
3
+ ((lambda ()
4
+ (display x)
5
+ (display y)
6
+ (display z)))))
7
+
8
+ (n_or_more 1 2 3 4 5 6)
9
+
10
+ ----
11
+
12
+ assert_output "12(3 4 5 6)"
@@ -0,0 +1,16 @@
1
+ (define a 0)
2
+ (define b 0)
3
+ (define test
4
+ (lambda (x y)
5
+ (+ 5 x)
6
+ (+ 10 y)
7
+ (+ x y)))
8
+
9
+ (define c (test 1 2))
10
+ (display a)
11
+ (display b)
12
+ (display c)
13
+
14
+ ----
15
+
16
+ assert_output "003"
@@ -0,0 +1,6 @@
1
+ (if (equal? #t #t)
2
+ (display "true"))
3
+
4
+ ----
5
+
6
+ assert_output "true"
@@ -0,0 +1,6 @@
1
+ (if (equal? #t #f)
2
+ (display "true"))
3
+
4
+ ----
5
+
6
+ assert_output ""
@@ -0,0 +1,7 @@
1
+ (if (equal? #t #t)
2
+ (display "true")
3
+ (display "false"))
4
+
5
+ ----
6
+
7
+ assert_output "true"
@@ -0,0 +1,7 @@
1
+ (if (equal? #t #f)
2
+ (display "true")
3
+ (display "false"))
4
+
5
+ ----
6
+
7
+ assert_output "false"
@@ -0,0 +1,5 @@
1
+ (set! tester 1)
2
+
3
+ ----
4
+
5
+ assert_execution_failure
@@ -0,0 +1,8 @@
1
+ (define tester 1)
2
+ (display tester)
3
+ (set! tester 5)
4
+ (display tester)
5
+
6
+ ----
7
+
8
+ assert_output "15"
@@ -0,0 +1,8 @@
1
+ (begin
2
+ (display 1)
3
+ (display 2)
4
+ (display 3))
5
+
6
+ ----
7
+
8
+ assert_output "123"
@@ -0,0 +1,7 @@
1
+ (define test-list (quote (1 2 3)))
2
+
3
+ (display (car test-list))
4
+
5
+ ----
6
+
7
+ assert_output "1"
@@ -0,0 +1,7 @@
1
+ (define test-list (quote (1 2 3)))
2
+
3
+ (display (cdr test-list))
4
+
5
+ ----
6
+
7
+ assert_output "(2 3)"
@@ -0,0 +1,7 @@
1
+ (define test-list (quote (1 2 3 4 5 6)))
2
+
3
+ (display (list-tail test-list 3))
4
+
5
+ ----
6
+
7
+ assert_output "(4 5 6)"
@@ -0,0 +1,10 @@
1
+ (define list-1 (quote (1 2 3)))
2
+ (define list-2 (quote (4 5 6)))
3
+ (define list-3 (quote (7 8 9)))
4
+
5
+ (display (append list-1 list-2))
6
+ (display (append list-1 list-2 list-3))
7
+
8
+ ----
9
+
10
+ assert_output "(1 2 3 4 5 6)(1 2 3 4 5 6 7 8 9)"
@@ -0,0 +1,5 @@
1
+ (display (list 1 2 3 4 5))
2
+
3
+ ----
4
+
5
+ assert_output "(1 2 3 4 5)"
@@ -0,0 +1,15 @@
1
+ (define countdown
2
+ (lambda (index)
3
+ (define current (- index 1))
4
+ (display current)
5
+ (if (equal? current 1)
6
+ (display "... Blast off!")
7
+ (begin
8
+ (display ", ")
9
+ (countdown current)))))
10
+
11
+ (countdown 11)
12
+
13
+ ----
14
+
15
+ assert_output "10, 9, 8, 7, 6, 5, 4, 3, 2, 1... Blast off!"
@@ -0,0 +1,5 @@
1
+ require "rubygems"
2
+ require "sexpistol"
3
+
4
+ require File.expand_path(File.join(File.dirname(__FILE__), "flea", "environment.rb"))
5
+ require File.expand_path(File.join(File.dirname(__FILE__), "flea", "interpreter.rb"))
@@ -0,0 +1,38 @@
1
+ module Flea
2
+ class Environment
3
+
4
+ attr_accessor :parent
5
+
6
+ def initialize(parent = nil)
7
+ @parent = parent
8
+ @table = {}
9
+ add_globals if @parent.nil?
10
+ end
11
+
12
+ def has_variable?(name)
13
+ return true if @table.has_key?(name)
14
+ return false if @parent.nil?
15
+ return @parent.has_variable?(name)
16
+ end
17
+
18
+ def find(name)
19
+ return @table[name] if @table.has_key?(name)
20
+ return nil if @parent.nil?
21
+ return @parent.find(name)
22
+ end
23
+
24
+ def define(name, value)
25
+ @table[name] = value
26
+ end
27
+
28
+ private
29
+
30
+ def add_globals
31
+ @table.merge!({
32
+ :"#t" => true,
33
+ :"#f" => false
34
+ })
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,67 @@
1
+ module Flea
2
+ class Interpreter
3
+
4
+ attr_accessor :base_environment,
5
+ :current_environment,
6
+ :parser
7
+
8
+ def initialize(options = {})
9
+ options = {
10
+ :base_environment => Environment.new,
11
+ :load_standard_library => true
12
+ }.merge(options)
13
+
14
+ @base_environment = @current_environment = options[:base_environment]
15
+ @parser = Sexpistol.new
16
+ @parser.ruby_keyword_literals = false
17
+ @parser.scheme_compatability = true
18
+
19
+ load_standard_library unless options[:load_standard_library] == false
20
+ end
21
+
22
+ def run(program)
23
+ expressions = parse(program)
24
+ result = nil
25
+ expressions.each do |expression|
26
+ result = evaluate(expression)
27
+ end
28
+
29
+ return result
30
+ end
31
+
32
+ def parse(string)
33
+ return @parser.parse_string(string)
34
+ end
35
+
36
+ def evaluate(expression)
37
+ return @current_environment.find(expression) if expression.is_a? Symbol
38
+ return expression unless expression.is_a? Array
39
+
40
+ if expression[0] == :define
41
+ return @current_environment.define expression[1], evaluate(expression[2])
42
+
43
+ elsif expression[0] == :native_function
44
+ return eval expression[1]
45
+
46
+ else # function call
47
+ function = evaluate(expression[0])
48
+ raise RuntimeError, "\n#{@parser.to_sexp(expression)}\n ^\n\n#{expression[0]} is not a function" unless function.is_a? Proc
49
+ arguments = expression.slice(1, expression.length)
50
+ return function.call(arguments, self)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def load_standard_library
57
+ library_pattern = File.join(File.dirname(__FILE__), 'standard_library', '*.scm')
58
+
59
+ Dir[library_pattern].each do |item|
60
+ File.open(item) do |file|
61
+ run(file.read)
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ end