lucio 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Gemfile +4 -9
  2. data/Gemfile.lock +3 -11
  3. data/README.md +9 -9
  4. data/Rakefile +0 -3
  5. data/VERSION +1 -1
  6. data/bin/lucio +1 -1
  7. data/bin/repl.rb +19 -21
  8. data/lib/lucio.rb +2 -0
  9. data/lib/lucio/lexicon.rb +12 -20
  10. data/lib/lucio/lucio.rb +48 -18
  11. data/lucio.gemspec +17 -42
  12. data/spec/add_spec.rb +34 -0
  13. data/spec/behead_spec.rb +12 -0
  14. data/spec/divide_spec.rb +26 -0
  15. data/spec/empty_list_spec.rb +23 -0
  16. data/spec/internal_spec.rb +13 -0
  17. data/spec/let_spec.rb +29 -0
  18. data/spec/minus_spec.rb +27 -0
  19. data/spec/readme_examples_spec.rb +32 -0
  20. data/spec/spec_helper.rb +3 -1
  21. data/spec/times_spec.rb +34 -0
  22. metadata +31 -80
  23. data/.autotest +0 -3
  24. data/TODO.md +0 -32
  25. data/lib/lucio/grammar.rb +0 -37
  26. data/lib/lucio/list.rb +0 -22
  27. data/lib/lucio/operators.rb +0 -9
  28. data/lib/lucio/operators/attribution.rb +0 -10
  29. data/lib/lucio/operators/conditional.rb +0 -20
  30. data/lib/lucio/operators/division.rb +0 -16
  31. data/lib/lucio/operators/equality.rb +0 -11
  32. data/lib/lucio/operators/macro.rb +0 -15
  33. data/lib/lucio/operators/multiplication.rb +0 -16
  34. data/lib/lucio/operators/operator.rb +0 -29
  35. data/lib/lucio/operators/subtraction.rb +0 -18
  36. data/lib/lucio/operators/sum.rb +0 -13
  37. data/lib/lucio/runner.rb +0 -60
  38. data/lib/lucio_syntax.treetop +0 -92
  39. data/spec/all_the_fun_spec.rb +0 -21
  40. data/spec/division_spec.rb +0 -19
  41. data/spec/eval_spec.rb +0 -116
  42. data/spec/lucio_spec.rb +0 -25
  43. data/spec/multiplication_spec.rb +0 -19
  44. data/spec/parser_spec.rb +0 -105
  45. data/spec/subtraction_spec.rb +0 -19
  46. data/spec/sum_spec.rb +0 -19
  47. data/spec/variable_spec.rb +0 -13
data/lib/lucio/grammar.rb DELETED
@@ -1,37 +0,0 @@
1
- require 'lucio'
2
-
3
- module Lucio
4
- class Grammar < Treetop::Runtime::SyntaxNode
5
- def eval
6
- Lucio::Runner.run make_tree(elements)
7
- end
8
-
9
- private
10
- def make_tree(el)
11
- x = make_list(el)
12
- h = nil
13
- h, x = Lucio.behead(x) if x[0] == '\''
14
-
15
- Kernel::eval("Lucio::List.new(tree = #{x.inject('') {|x, y| x += "'#{y}',"}.strip.chop.gsub(/'\(',/, '[').gsub(/[,]?'\)'/, ']')}, evaluable = #{!h})")
16
- end
17
-
18
- def make_list(el, list = [])
19
- el.each do |e|
20
- methods = e.public_methods.reject{|i| i.to_s.chr != 'v'}.map{|i| i.to_s}.sort
21
- if methods.include?('value')
22
- list << e.value
23
- else
24
- unless e.empty? || e.text_value.strip.empty?
25
- if e.nonterminal?
26
- list = make_list(e.elements, list)
27
- else
28
- list << e.text_value
29
- end
30
- end
31
- end
32
- end
33
- list
34
- end
35
- end
36
- end
37
-
data/lib/lucio/list.rb DELETED
@@ -1,22 +0,0 @@
1
- module Lucio
2
- class List
3
- attr :tree, :evaluable
4
-
5
- def initialize(tree, evaluable = true)
6
- @tree = tree
7
- @evaluable = evaluable
8
- end
9
-
10
- def to_s
11
- flat(tree)
12
- end
13
-
14
- private
15
- def flat(list)
16
- result = "#{'(' if list.empty?}#{list.inject('(') do |result, item|
17
- result += "#{item} "
18
- end.chop})"
19
- end
20
-
21
- end
22
- end
@@ -1,9 +0,0 @@
1
- require 'lucio/operators/operator'
2
-
3
- require 'lucio/operators/sum'
4
- require 'lucio/operators/multiplication'
5
- require 'lucio/operators/division'
6
- require 'lucio/operators/subtraction'
7
- require 'lucio/operators/equality'
8
- require 'lucio/operators/conditional'
9
- require 'lucio/operators/attribution'
@@ -1,10 +0,0 @@
1
- require 'lucio/operators/macro'
2
-
3
- module Lucio
4
- module Operator
5
- class Attribution < Macro
6
- def execute(lexicon, *items)
7
- end
8
- end
9
- end
10
- end
@@ -1,20 +0,0 @@
1
- require 'lucio/operators/macro'
2
-
3
- module Lucio
4
- module Operator
5
- class Conditional < Macro
6
- def execute(lexicon, list)
7
- tree = list.tree
8
- condition = Lucio::Runner.run List.new(tree[0]), lexicon
9
-
10
- if condition
11
- Lucio::Runner.run List.new(tree[1]), lexicon
12
- else
13
- Lucio::Runner.run(List.new(tree[2]), lexicon) if tree.size > 2
14
- end
15
- end
16
- end
17
- end
18
- end
19
-
20
-
@@ -1,16 +0,0 @@
1
- require 'lucio/operators/function'
2
-
3
- module Lucio
4
- module Operator
5
- class Division < Function
6
- def execute(lexicon, *items)
7
- if items.size == 0
8
- 0
9
- else
10
- items.inject {|result, item| result = result / item.to_f }
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
@@ -1,11 +0,0 @@
1
- require 'lucio/operators/function'
2
-
3
- module Lucio
4
- module Operator
5
- class Equality < Function
6
- def execute(lexicon, *items)
7
- items[0] == items[1]
8
- end
9
- end
10
- end
11
- end
@@ -1,15 +0,0 @@
1
- module Lucio
2
- module Operator
3
- class Macro
4
- attr :type
5
-
6
- def initialize
7
- @type = :macro
8
- end
9
-
10
- def execute(*params)
11
- raise "Operator not implemented"
12
- end
13
- end
14
- end
15
- end
@@ -1,16 +0,0 @@
1
- require 'lucio/operators/function'
2
-
3
- module Lucio
4
- module Operator
5
- class Multiplication < Function
6
- def execute(lexicon, *items)
7
- if items.size == 0
8
- 0
9
- else
10
- items.inject(1) {|multiplication, item| multiplication *= item }
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
@@ -1,29 +0,0 @@
1
- module Lucio
2
- module Operator
3
- class Operator
4
- attr :type
5
-
6
- def type
7
- @type
8
- end
9
-
10
- def execute(*items)
11
- raise "Incomplete operator"
12
- end
13
- end
14
-
15
- class Function
16
- def initialize
17
- super.type = :function
18
- end
19
- end
20
-
21
- class Macro
22
- def initialize
23
- super.type = :macro
24
- end
25
-
26
- end
27
-
28
- end
29
- end
@@ -1,18 +0,0 @@
1
- require 'lucio/operators/function'
2
-
3
- module Lucio
4
- module Operator
5
- class Subtraction < Function
6
- def execute(lexicon, *items)
7
- p lexicon, items
8
- if items.size == 0
9
- 0
10
- else
11
- head, tail = Lucio.behead(items)
12
- tail.empty? ? (head * -1) : tail.inject(head) {|subtraction, item| subtraction -= item }
13
- end
14
- end
15
- end
16
- end
17
- end
18
-
@@ -1,13 +0,0 @@
1
- module Lucio
2
- module Operator
3
- class Sum < Function
4
- def execute(lexicon, *items)
5
- if items.size == 0
6
- 0
7
- else
8
- items.inject(0) {|sum, item| sum += item }
9
- end
10
- end
11
- end
12
- end
13
- end
data/lib/lucio/runner.rb DELETED
@@ -1,60 +0,0 @@
1
- module Lucio
2
- class Runner
3
- def self.run(obj_tree, lexicon = Lexicon.new)
4
- tree = obj_tree.tree
5
-
6
- if obj_tree.evaluable
7
- case
8
- when tree.empty?
9
- nil
10
- when tree.size == 1
11
- item = tree[0]
12
- instruction = lexicon.get item
13
- if instruction
14
- instruction.execute lexicon
15
- else
16
- begin
17
- eval(item)
18
- rescue Exception => e
19
- raise "Invalid or unknown symbol: #{item}", e.backtrace
20
- end
21
- end
22
- else
23
- operator, list = Lucio.behead(tree)
24
- start, tail = Lucio.behead(list)
25
-
26
- instruction = lexicon.get operator
27
-
28
- raise "Invalid or unknown operator: #{operator}" unless instruction
29
-
30
- if instruction.type == :function
31
- if(start.kind_of? Array)
32
- first = run List.new(start), lexicon
33
- else
34
- first = eval start
35
- end
36
-
37
- if tail.empty?
38
- instruction.execute(lexicon, first)
39
- else
40
- tail.inject(first) do |result, item|
41
- if item.kind_of? Array
42
- i = run List.new(item), lexicon
43
- else
44
- i = eval item
45
- end
46
-
47
- instruction.execute(lexicon, result, i)
48
- end
49
- end
50
-
51
- elsif instruction.type == :macro
52
- instruction.execute lexicon, List.new(list)
53
- end
54
- end
55
- else
56
- obj_tree
57
- end
58
- end
59
- end
60
- end
@@ -1,92 +0,0 @@
1
- require 'lucio/grammar'
2
-
3
- grammar Lucio
4
-
5
- rule lucio
6
- (whitespace / (quote? list))* <Grammar>
7
- end
8
-
9
- rule list
10
- lparen (whitespace / operator)? (value)* rparen
11
- end
12
-
13
- rule value
14
- list / string / number / boolean / operator / vector / whitespace
15
- end
16
-
17
- rule quote
18
- '\''
19
- end
20
-
21
- rule rparen
22
- ')'
23
- end
24
-
25
- rule lparen
26
- '('
27
- end
28
-
29
- rule whitespace
30
- [ \n\r\t,]+
31
- end
32
-
33
- rule vector
34
- '[' (value)* ']'
35
- end
36
-
37
- rule operator
38
- ((([a-zA-Z] ([-]? [a-zA-Z0-9])* [?]?) !('+' / '-' / '/' / '*')) / ('+' / '-' / '/' / '*')) {
39
- def value
40
- text_value
41
- end
42
- }
43
- end
44
-
45
- rule number
46
- decimal / integer {
47
- def value
48
- f = text_value.to_f
49
- i = text_value.to_i
50
- (f - i == 0 ? i : f)
51
- end
52
- }
53
- end
54
-
55
- rule decimal
56
- integer '.' [0-9]+ {
57
- def value
58
- text_value.to_f
59
- end
60
- }
61
- end
62
-
63
- rule integer
64
- '-'? unsigned_integer
65
- end
66
-
67
- rule unsigned_integer
68
- '0' / [1-9] [0-9]*
69
- end
70
-
71
- rule string
72
- '"' [^"]* '"' {
73
- def value
74
- text_value
75
- end
76
- }
77
- end
78
- #'
79
- rule boolean
80
- true / false
81
- end
82
-
83
- rule true
84
- 'true'
85
- end
86
-
87
- rule false
88
- 'false'
89
- end
90
-
91
- end
92
-
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
- require 'lucio'
3
-
4
- describe "All the fun" do
5
- it "should have all the fun" do
6
- Lucio.literal("'(lisp programmers have all defun)").should == '(lisp programmers have all defun)'
7
- end
8
-
9
- it "should work too =P" do
10
- Lucio.literal("'(a b c)").should == '(a b c)'
11
- end
12
-
13
- it "should work with numbers" do
14
- Lucio.literal("'(1 2 3)").should == '(1 2 3)'
15
- end
16
-
17
- it "should work with mixed values too" do
18
- Lucio.literal("'(a b c 1 2 3)").should == '(a b c 1 2 3)'
19
- end
20
-
21
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
- require 'lucio'
3
-
4
- describe Lucio::Operator::Division do
5
- it "an empty list should return zero" do
6
- Lucio.eval('(/)').should == 0
7
- end
8
-
9
- it "a list with one item should return that item" do
10
- Lucio.eval('(/ 1)').should == 1
11
- Lucio.eval('(/ 2)').should == 2
12
- end
13
-
14
- it "a list with more than one item should eval all items" do
15
- Lucio.eval('(/ 8 4)').should == 2
16
- Lucio.eval('(/ 8 4 2)').should == 1
17
- end
18
-
19
- end
data/spec/eval_spec.rb DELETED
@@ -1,116 +0,0 @@
1
- require 'spec_helper'
2
- require 'lucio'
3
-
4
- describe Lucio do
5
-
6
- context 'empty list' do
7
- it 'should return nil' do
8
- Lucio.eval('()').should == nil
9
- Lucio.eval('( )').should == nil
10
- Lucio.eval('( )').should == nil
11
- end
12
- end
13
-
14
- context 'sum operation' do
15
- it 'should return a numeric value' do
16
- Lucio.eval('(1)').should == 1
17
- Lucio.eval('(+ 1 2)').should == 3
18
- Lucio.eval('(+ 1 2 3 4 5 6)').should == 21
19
- Lucio.eval('(+ 1 (+ 2 3))').should == 6
20
-
21
- Lucio.eval('(+)').should == 0
22
-
23
- lambda { Lucio.eval('(invalid)') }.should raise_error
24
- end
25
- end
26
-
27
- context 'more than one type of operation' do
28
- it 'should return a numeric value' do
29
- Lucio.eval('(/ (* (+ 1 2) (+3 4)) 2)').should == 10.5
30
- Lucio.eval('(- 10.5 (/ (* (+ 1 2) (+3 4)) 2))').should == 0
31
- end
32
- end
33
-
34
- context 'builtin function' do
35
- it 'compare two values using a function' do
36
- Lucio.eval('(eql? (* (+ 1 2) 3) 9)').should be_true
37
- Lucio.eval('(eql? (/ (* (+ 1 2) (+3 4)) 2) 10)').should be_false
38
- Lucio.eval(<<lisp
39
- (eql?
40
- (/
41
- (*
42
- (+ 1 2)
43
- (+3 4))
44
- 2)
45
- 10)
46
- lisp
47
- ).should be_false
48
- end
49
- end
50
-
51
- context 'macro' do
52
- it 'runs a simple if' do
53
- Lucio.eval(<<lisp
54
- (if (eql? 1 1)
55
- ("ok"))
56
- lisp
57
- ).should == 'ok'
58
- end
59
-
60
- it 'a simple if without else returns nil when false' do
61
- Lucio.eval('(if (eql? 1 2)("nope"))').should == nil
62
- end
63
-
64
- it 'runs a if with else' do
65
- Lucio.eval(<<lisp
66
- (if (eql? 1 1)
67
- ("ok")
68
- ("nope"))
69
- lisp
70
- ).should == 'ok'
71
-
72
- Lucio.eval(<<lisp
73
- (if (eql? 2 1)
74
- ("nope")
75
- ("ok"))
76
- lisp
77
- ).should == 'ok'
78
- end
79
-
80
- it 'runs a function before a macro' do
81
- Lucio.eval(<<lisp
82
- (+ 1 2 3 (if (eql? (+ 1 1) 2) (4) (5)))
83
- lisp
84
- ).should == 10
85
-
86
- Lucio.eval(<<lisp
87
- (eql? (+ 1 2 3 (if (eql? (+ 1 1) 2) (4) (5))) 10)
88
- lisp
89
- ).should be_true
90
- end
91
-
92
- it 'runs a macro before a function ' do
93
- code = <<lisp
94
- (if (eql? (+ 1 1) 2) (+ 1 2 3 4) (0))
95
- lisp
96
- Lucio.eval(code).should == 10
97
-
98
- Lucio.eval(<<lisp
99
- (if (eql? (+ 1 1) 2)
100
- (eql? (+ 1 2 3 (4) (5)) 15)
101
- (false))
102
- lisp
103
- ).should be_true
104
- end
105
- end
106
-
107
- context 'quoted list' do
108
-
109
- it 'a quoted empty list should return an empty list' do
110
- Lucio.literal("'()").should == '()'
111
-
112
- end
113
-
114
- end
115
-
116
- end