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.
- data/Gemfile +4 -9
- data/Gemfile.lock +3 -11
- data/README.md +9 -9
- data/Rakefile +0 -3
- data/VERSION +1 -1
- data/bin/lucio +1 -1
- data/bin/repl.rb +19 -21
- data/lib/lucio.rb +2 -0
- data/lib/lucio/lexicon.rb +12 -20
- data/lib/lucio/lucio.rb +48 -18
- data/lucio.gemspec +17 -42
- data/spec/add_spec.rb +34 -0
- data/spec/behead_spec.rb +12 -0
- data/spec/divide_spec.rb +26 -0
- data/spec/empty_list_spec.rb +23 -0
- data/spec/internal_spec.rb +13 -0
- data/spec/let_spec.rb +29 -0
- data/spec/minus_spec.rb +27 -0
- data/spec/readme_examples_spec.rb +32 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/times_spec.rb +34 -0
- metadata +31 -80
- data/.autotest +0 -3
- data/TODO.md +0 -32
- data/lib/lucio/grammar.rb +0 -37
- data/lib/lucio/list.rb +0 -22
- data/lib/lucio/operators.rb +0 -9
- data/lib/lucio/operators/attribution.rb +0 -10
- data/lib/lucio/operators/conditional.rb +0 -20
- data/lib/lucio/operators/division.rb +0 -16
- data/lib/lucio/operators/equality.rb +0 -11
- data/lib/lucio/operators/macro.rb +0 -15
- data/lib/lucio/operators/multiplication.rb +0 -16
- data/lib/lucio/operators/operator.rb +0 -29
- data/lib/lucio/operators/subtraction.rb +0 -18
- data/lib/lucio/operators/sum.rb +0 -13
- data/lib/lucio/runner.rb +0 -60
- data/lib/lucio_syntax.treetop +0 -92
- data/spec/all_the_fun_spec.rb +0 -21
- data/spec/division_spec.rb +0 -19
- data/spec/eval_spec.rb +0 -116
- data/spec/lucio_spec.rb +0 -25
- data/spec/multiplication_spec.rb +0 -19
- data/spec/parser_spec.rb +0 -105
- data/spec/subtraction_spec.rb +0 -19
- data/spec/sum_spec.rb +0 -19
- data/spec/variable_spec.rb +0 -13
data/Gemfile
CHANGED
@@ -1,17 +1,12 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
gem '
|
4
|
-
gem 'treetop'
|
5
|
-
|
6
|
-
gem 'simplecov', '>= 0.4.0', :require => false, :group => :test
|
3
|
+
gem 'sparse', '~> 0.0.3'
|
7
4
|
|
8
5
|
# Add dependencies to develop your gem here.
|
9
6
|
# Include everything needed to run rake, tests, features, etc.
|
10
7
|
group :development, :test do
|
11
8
|
gem 'rspec'
|
12
|
-
gem
|
13
|
-
gem
|
14
|
-
gem
|
15
|
-
gem "bundler", "~> 1.0.0"
|
16
|
-
gem "jeweler", "~> 1.6.4"
|
9
|
+
gem "bundler", "~> 1.0.0", :require => false
|
10
|
+
gem "jeweler", "~> 1.6.4", :require => false
|
11
|
+
gem 'simplecov', '~> 0.4.0', :require => false
|
17
12
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
ZenTest (4.5.0)
|
5
4
|
diff-lcs (1.1.2)
|
6
5
|
git (1.2.5)
|
7
6
|
jeweler (1.6.4)
|
8
7
|
bundler (~> 1.0)
|
9
8
|
git (>= 1.2.5)
|
10
9
|
rake
|
11
|
-
polyglot (0.3.1)
|
12
10
|
rake (0.9.2)
|
13
11
|
rspec (2.6.0)
|
14
12
|
rspec-core (~> 2.6.0)
|
@@ -21,21 +19,15 @@ GEM
|
|
21
19
|
simplecov (0.4.2)
|
22
20
|
simplecov-html (~> 0.4.4)
|
23
21
|
simplecov-html (0.4.5)
|
24
|
-
|
25
|
-
polyglot (>= 0.3.1)
|
26
|
-
yard (0.6.8)
|
22
|
+
sparse (0.0.3)
|
27
23
|
|
28
24
|
PLATFORMS
|
29
25
|
ruby
|
30
26
|
x86-mingw32
|
31
27
|
|
32
28
|
DEPENDENCIES
|
33
|
-
ZenTest
|
34
29
|
bundler (~> 1.0.0)
|
35
|
-
diff-lcs
|
36
30
|
jeweler (~> 1.6.4)
|
37
|
-
polyglot
|
38
31
|
rspec
|
39
|
-
simplecov (
|
40
|
-
|
41
|
-
yard (~> 0.6.0)
|
32
|
+
simplecov (~> 0.4.0)
|
33
|
+
sparse (~> 0.0.3)
|
data/README.md
CHANGED
@@ -17,19 +17,19 @@ Lucio is developed in my almost nonexistent spare time as a way to keep me learn
|
|
17
17
|
I'm just an ordinary software developer, passionate and curious. If you want to collaborate, fork this and start to code. Simple.
|
18
18
|
|
19
19
|
## Small sample
|
20
|
-
(/ (* (+ 1 2) (+3 4)) 2)
|
20
|
+
(/ (* (+ 1 2) (+ 3 4)) 2)
|
21
21
|
=> 10.5
|
22
22
|
|
23
23
|
(eql? (* (+ 1 2) 3) 9)
|
24
24
|
=> true
|
25
25
|
|
26
|
-
(if (eql? 10.5 (/ (* (+ 1 2) (+3 4)) 2))
|
26
|
+
(if (eql? 10.5 (/ (* (+ 1 2) (+ 3 4)) 2))
|
27
27
|
("great"))
|
28
28
|
=> "great"
|
29
29
|
|
30
|
-
(if (eql? 0 (/ (* (+ 1 2) (+3 4)) 2))
|
30
|
+
(if (eql? 0 (/ (* (+ 1 2) (+ 3 4)) 2))
|
31
31
|
("great")
|
32
|
-
("ouch")
|
32
|
+
("ouch"))
|
33
33
|
=> "ouch"
|
34
34
|
|
35
35
|
# Lucio (pt\_BR)
|
@@ -51,17 +51,17 @@ Lucio está sendo desenvolvido em meu quase inexistente tempo livre como uma for
|
|
51
51
|
Sou apenas um rapaz latino-americano sem dinheiro no bolso nem amigos importantes, mas que realmente adora o que faz e muito curioso. Se você quiser participar e colaborar, crie um fork e comece a codificar. Simples assim.
|
52
52
|
|
53
53
|
## Exemplos simples
|
54
|
-
(/ (* (+ 1 2) (+3 4)) 2)
|
54
|
+
(/ (* (+ 1 2) (+ 3 4)) 2)
|
55
55
|
=> 10.5
|
56
56
|
|
57
57
|
(eql? (* (+ 1 2) 3) 9)
|
58
58
|
=> true
|
59
59
|
|
60
|
-
(if (eql? 10.5 (/ (* (+ 1 2) (+3 4)) 2))
|
60
|
+
(if (eql? 10.5 (/ (* (+ 1 2) (+ 3 4)) 2))
|
61
61
|
("great"))
|
62
62
|
=> "great"
|
63
63
|
|
64
|
-
(if (eql? 0 (/ (* (+ 1 2) (+3 4)) 2))
|
64
|
+
(if (eql? 0 (/ (* (+ 1 2) (+ 3 4)) 2))
|
65
65
|
("great")
|
66
|
-
("ouch")
|
67
|
-
=> "ouch"
|
66
|
+
("ouch"))
|
67
|
+
=> "ouch"
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.8
|
data/bin/lucio
CHANGED
data/bin/repl.rb
CHANGED
@@ -6,34 +6,32 @@ require 'lucio'
|
|
6
6
|
|
7
7
|
QUIT = '.q'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
exit = false
|
13
|
-
|
14
|
-
puts <<lisp
|
9
|
+
class Repl
|
10
|
+
def self.run
|
11
|
+
@lucio = Lucio.new
|
12
|
+
exit = false
|
13
|
+
puts <<lisp
|
15
14
|
# lucio interactive console
|
16
15
|
-------------------------
|
17
16
|
# type a lucio expression and press ENTER
|
18
17
|
# type .q and press ENTER to exit
|
19
18
|
|
20
19
|
lisp
|
21
|
-
while !exit
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
while !exit
|
21
|
+
print 'lucio: '
|
22
|
+
command = (gets).chomp
|
23
|
+
exit = (command == QUIT)
|
24
|
+
unless exit
|
25
|
+
begin
|
26
|
+
print '=> '
|
27
|
+
p @lucio.eval(command)
|
28
|
+
rescue Exception => msg
|
29
|
+
puts "Error: #{msg}"
|
30
|
+
end
|
31
|
+
puts ''
|
32
|
+
end
|
31
33
|
end
|
32
|
-
puts ''
|
33
|
-
end
|
34
|
-
end
|
35
34
|
|
36
|
-
puts '# bye!'
|
37
|
-
end
|
35
|
+
puts '# bye!'
|
38
36
|
end
|
39
37
|
end
|
data/lib/lucio.rb
CHANGED
data/lib/lucio/lexicon.rb
CHANGED
@@ -1,25 +1,17 @@
|
|
1
|
-
|
1
|
+
class Lexicon
|
2
|
+
def initialize
|
3
|
+
@operator_list = {}
|
4
|
+
end
|
2
5
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
fill_operator_list
|
7
|
-
end
|
6
|
+
def add_function(token, code)
|
7
|
+
@operator_list[token] = {:type => :function, :code => code}
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def add_macro(token, code)
|
11
|
+
@operator_list[token] = {:type => :macro, :code => code}
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
@operator_list = {}
|
16
|
-
@operator_list['+'] = Operator::Sum.new
|
17
|
-
@operator_list['*'] = Operator::Multiplication.new
|
18
|
-
@operator_list['/'] = Operator::Division.new
|
19
|
-
@operator_list['-'] = Operator::Subtraction.new
|
20
|
-
@operator_list['eql?'] = Operator::Equality.new
|
21
|
-
@operator_list['if'] = Operator::Conditional.new
|
22
|
-
@operator_list['let'] = Operator::Attribution.new
|
23
|
-
end
|
14
|
+
def get(operator)
|
15
|
+
@operator_list[operator]
|
24
16
|
end
|
25
17
|
end
|
data/lib/lucio/lucio.rb
CHANGED
@@ -1,29 +1,59 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
class Lucio
|
2
|
+
def initialize(lexicon = Lexicon.new)
|
3
|
+
@lexicon = lexicon
|
4
|
+
@lexicon.add_function :+ , lambda{|items| items.reduce(0, :+)}
|
5
|
+
@lexicon.add_function :* , lambda{|items| items.reduce(1, :*)}
|
6
|
+
@lexicon.add_function :- , lambda{|items| case when items.size == 0; 0; else; head, tail = Lucio.behead(items); tail.empty? ? (head * -1) : tail.inject(head) {|subtraction, item| subtraction -= item}; end}
|
7
|
+
@lexicon.add_function :/ , lambda{|items| case when items.size == 0; raise 'expects at least 1 arguments, given 0'; when items.size == 1; 1.0 / items[0]; else items.reduce{|result, item| result = result / item.to_f}; end}
|
8
|
+
@lexicon.add_function :true , lambda{ true }
|
9
|
+
@lexicon.add_function :false, lambda{ false }
|
10
|
+
@lexicon.add_function :eql? , lambda{|items| items.map{|item| item == items[0]}.reduce{|memo, item| memo && item}}
|
11
|
+
@lexicon.add_macro :let , lambda{|lexicon, items| lexicon.add_function(items[0].to_sym, lambda{(items[1].kind_of? Array) ? evaluate_tree(items[1]) : items[1]})}
|
12
|
+
@lexicon.add_macro :if , lambda{|lexicon, items| evaluate_tree(items[0]) ? evaluate_tree(items[1]) : evaluate_tree(items[2]) }
|
13
|
+
end
|
7
14
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
15
|
+
def eval(source_code)
|
16
|
+
tree = Sparse.new.parse(source_code)
|
17
|
+
ret = nil
|
18
|
+
tree.each {|list| ret = evaluate_tree list}
|
19
|
+
ret
|
20
|
+
end
|
12
21
|
|
13
|
-
|
22
|
+
private
|
23
|
+
def evaluate_tree(tree)
|
24
|
+
unless tree.empty?
|
25
|
+
operator, list = Lucio.behead tree
|
26
|
+
|
27
|
+
if operator.kind_of?(Symbol) || operator.kind_of?(Array)
|
28
|
+
instruction = @lexicon.get operator
|
14
29
|
|
15
|
-
|
16
|
-
|
30
|
+
if instruction
|
31
|
+
if instruction[:type] == :function
|
32
|
+
list.map! {|item| (item.kind_of? Array) ? item = evaluate_tree(item) : item}
|
33
|
+
list.map! {|item| (item.kind_of? Symbol) ? item = @lexicon.get(item)[:code].call : item}
|
17
34
|
|
18
|
-
|
19
|
-
|
20
|
-
|
35
|
+
instruction[:code].call list
|
36
|
+
|
37
|
+
elsif instruction[:type] == :macro
|
38
|
+
instruction[:code].call @lexicon, list
|
21
39
|
|
22
|
-
|
23
|
-
|
40
|
+
end
|
41
|
+
|
42
|
+
else
|
43
|
+
raise UnboundSymbolException.new "Unbound symbol #{operator.to_s}"
|
44
|
+
|
45
|
+
end
|
46
|
+
else
|
47
|
+
operator
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
24
51
|
end
|
25
52
|
|
26
53
|
def self.behead(list)
|
27
54
|
[list[0], list.drop(1)]
|
28
55
|
end
|
29
56
|
end
|
57
|
+
|
58
|
+
class UnboundSymbolException < Exception
|
59
|
+
end
|
data/lucio.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{lucio}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["pbalduino"]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-19}
|
13
13
|
s.description = %q{Lucio is intended to be a Lisp-like language developed in Ruby only for knowledge and fun.}
|
14
14
|
s.email = %q{pbalduino+github@gmail.com}
|
15
15
|
s.executables = ["lucio", "repl.rb"]
|
@@ -19,7 +19,6 @@ Gem::Specification.new do |s|
|
|
19
19
|
"README.md"
|
20
20
|
]
|
21
21
|
s.files = [
|
22
|
-
".autotest",
|
23
22
|
".document",
|
24
23
|
".rspec",
|
25
24
|
".rvmrc",
|
@@ -29,38 +28,23 @@ Gem::Specification.new do |s|
|
|
29
28
|
"LICENSE.txt",
|
30
29
|
"README.md",
|
31
30
|
"Rakefile",
|
32
|
-
"TODO.md",
|
33
31
|
"VERSION",
|
34
32
|
"bin/lucio",
|
35
33
|
"bin/repl.rb",
|
36
34
|
"lib/lucio.rb",
|
37
|
-
"lib/lucio/grammar.rb",
|
38
35
|
"lib/lucio/lexicon.rb",
|
39
|
-
"lib/lucio/list.rb",
|
40
36
|
"lib/lucio/lucio.rb",
|
41
|
-
"lib/lucio/operators.rb",
|
42
|
-
"lib/lucio/operators/attribution.rb",
|
43
|
-
"lib/lucio/operators/conditional.rb",
|
44
|
-
"lib/lucio/operators/division.rb",
|
45
|
-
"lib/lucio/operators/equality.rb",
|
46
|
-
"lib/lucio/operators/macro.rb",
|
47
|
-
"lib/lucio/operators/multiplication.rb",
|
48
|
-
"lib/lucio/operators/operator.rb",
|
49
|
-
"lib/lucio/operators/subtraction.rb",
|
50
|
-
"lib/lucio/operators/sum.rb",
|
51
|
-
"lib/lucio/runner.rb",
|
52
|
-
"lib/lucio_syntax.treetop",
|
53
37
|
"lucio.gemspec",
|
54
|
-
"spec/
|
55
|
-
"spec/
|
56
|
-
"spec/
|
57
|
-
"spec/
|
58
|
-
"spec/
|
59
|
-
"spec/
|
38
|
+
"spec/add_spec.rb",
|
39
|
+
"spec/behead_spec.rb",
|
40
|
+
"spec/divide_spec.rb",
|
41
|
+
"spec/empty_list_spec.rb",
|
42
|
+
"spec/internal_spec.rb",
|
43
|
+
"spec/let_spec.rb",
|
44
|
+
"spec/minus_spec.rb",
|
45
|
+
"spec/readme_examples_spec.rb",
|
60
46
|
"spec/spec_helper.rb",
|
61
|
-
"spec/
|
62
|
-
"spec/sum_spec.rb",
|
63
|
-
"spec/variable_spec.rb"
|
47
|
+
"spec/times_spec.rb"
|
64
48
|
]
|
65
49
|
s.homepage = %q{https://github.com/pbalduino/lucio}
|
66
50
|
s.licenses = ["MIT"]
|
@@ -72,33 +56,24 @@ Gem::Specification.new do |s|
|
|
72
56
|
s.specification_version = 3
|
73
57
|
|
74
58
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
75
|
-
s.add_runtime_dependency(%q<
|
76
|
-
s.add_runtime_dependency(%q<treetop>, [">= 0"])
|
59
|
+
s.add_runtime_dependency(%q<sparse>, ["~> 0.0.3"])
|
77
60
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
78
|
-
s.add_development_dependency(%q<ZenTest>, [">= 0"])
|
79
|
-
s.add_development_dependency(%q<diff-lcs>, [">= 0"])
|
80
|
-
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
81
61
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
82
62
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
63
|
+
s.add_development_dependency(%q<simplecov>, ["~> 0.4.0"])
|
83
64
|
else
|
84
|
-
s.add_dependency(%q<
|
85
|
-
s.add_dependency(%q<treetop>, [">= 0"])
|
65
|
+
s.add_dependency(%q<sparse>, ["~> 0.0.3"])
|
86
66
|
s.add_dependency(%q<rspec>, [">= 0"])
|
87
|
-
s.add_dependency(%q<ZenTest>, [">= 0"])
|
88
|
-
s.add_dependency(%q<diff-lcs>, [">= 0"])
|
89
|
-
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
90
67
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
91
68
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
69
|
+
s.add_dependency(%q<simplecov>, ["~> 0.4.0"])
|
92
70
|
end
|
93
71
|
else
|
94
|
-
s.add_dependency(%q<
|
95
|
-
s.add_dependency(%q<treetop>, [">= 0"])
|
72
|
+
s.add_dependency(%q<sparse>, ["~> 0.0.3"])
|
96
73
|
s.add_dependency(%q<rspec>, [">= 0"])
|
97
|
-
s.add_dependency(%q<ZenTest>, [">= 0"])
|
98
|
-
s.add_dependency(%q<diff-lcs>, [">= 0"])
|
99
|
-
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
100
74
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
101
75
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
76
|
+
s.add_dependency(%q<simplecov>, ["~> 0.4.0"])
|
102
77
|
end
|
103
78
|
end
|
104
79
|
|
data/spec/add_spec.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lucio do
|
4
|
+
context 'add' do
|
5
|
+
before :each do
|
6
|
+
@lucio = Lucio.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'without parameters should return zero' do
|
10
|
+
@lucio.eval('(+)').should == 0
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'with one value should return that value' do
|
14
|
+
@lucio.eval('(+ 3)').should == 3
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'with two values should return the sum' do
|
18
|
+
@lucio.eval('(+ 3 5)').should == 8
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'with nested lists should eval the list before return the sum' do
|
22
|
+
@lucio.eval('(+ 3 (+ 3 2))').should == 8
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'with neeeeeeesteeeeeeeed freeeeezy!' do
|
26
|
+
@lucio.eval('(+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 (+ 3 2))))))))))))))').should == 44
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'with invalid operator should raise error' do
|
30
|
+
lambda {@lucio.eval('((+ 3 4))')}.should raise_error UnboundSymbolException
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|