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/Gemfile CHANGED
@@ -1,17 +1,12 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem 'polyglot'
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 'ZenTest'
13
- gem 'diff-lcs'
14
- gem "yard", "~> 0.6.0"
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
- treetop (1.4.9)
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 (>= 0.4.0)
40
- treetop
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
@@ -37,6 +37,3 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
37
37
  end
38
38
 
39
39
  task :default => :spec
40
-
41
- require 'yard'
42
- YARD::Rake::YardocTask.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.0.8
data/bin/lucio CHANGED
@@ -3,7 +3,7 @@
3
3
  if ARGV.empty?
4
4
  $LOAD_PATH << (File.expand_path(File.dirname(__FILE__)) + '/../bin')
5
5
  require('repl')
6
- Lucio::Repl.run
6
+ Repl.run
7
7
  else
8
8
  puts 'meh'
9
9
  end
data/bin/repl.rb CHANGED
@@ -6,34 +6,32 @@ require 'lucio'
6
6
 
7
7
  QUIT = '.q'
8
8
 
9
- module Lucio
10
- class Repl
11
- def self.run
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
- print 'lucio: '
23
- command = (gets).chomp
24
- exit = (command == QUIT)
25
- unless exit
26
- begin
27
- print '=> '
28
- p Lucio.eval(command)
29
- rescue Exception => msg
30
- puts "Error: #{msg}"
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
@@ -1 +1,3 @@
1
+ require 'sparse'
2
+ require 'lucio/lexicon'
1
3
  require 'lucio/lucio'
data/lib/lucio/lexicon.rb CHANGED
@@ -1,25 +1,17 @@
1
- require 'lucio/operators'
1
+ class Lexicon
2
+ def initialize
3
+ @operator_list = {}
4
+ end
2
5
 
3
- module Lucio
4
- class Lexicon
5
- def initialize
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
- def get(operator)
10
- ret = @operator_list[operator]
11
- end
10
+ def add_macro(token, code)
11
+ @operator_list[token] = {:type => :macro, :code => code}
12
+ end
12
13
 
13
- private
14
- def fill_operator_list
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
- require 'lucio/runner'
2
- require 'lucio/lexicon'
3
- require 'lucio/list'
4
- require 'polyglot'
5
- require 'treetop'
6
- require 'lucio_syntax'
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
- module Lucio
9
- def self.parse(str, debug = false)
10
- parser = LucioParser.new
11
- result = parser.parse str
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
- puts "\n#{parser.failure_reason}" unless result || !debug
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
- result
16
- end
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
- def self.eval(str)
19
- parse(str).eval
20
- end
35
+ instruction[:code].call list
36
+
37
+ elsif instruction[:type] == :macro
38
+ instruction[:code].call @lexicon, list
21
39
 
22
- def self.literal(str)
23
- Lucio.eval(str).to_s
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.7"
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-15}
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/all_the_fun_spec.rb",
55
- "spec/division_spec.rb",
56
- "spec/eval_spec.rb",
57
- "spec/lucio_spec.rb",
58
- "spec/multiplication_spec.rb",
59
- "spec/parser_spec.rb",
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/subtraction_spec.rb",
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<polyglot>, [">= 0"])
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<polyglot>, [">= 0"])
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<polyglot>, [">= 0"])
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