lucio 0.0.7 → 0.0.8

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