rubic 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51da002edc71251bec55d378b94e41dc2ffe3282
4
- data.tar.gz: 3c9ca15aebeebf042e077838498437772c31ac65
3
+ metadata.gz: 9ce7e32bbc4068cda59ee86d64f3210c2b6272ae
4
+ data.tar.gz: d823d0e4f0c57f89681e0f14bb650ae700effef6
5
5
  SHA512:
6
- metadata.gz: dcbf36feedcd3b82fd8ba5d80e5adda3c7d9e8857714bdc2c5fd25f9dab2d786a8a67fc049474cb52afdc3bb8f211fc1822df8e14a7c94df34afb59af709f65b
7
- data.tar.gz: b6519390237eef8156b89ba255af847d62c2edf9eddb2778d0df24503bc43c39f94d25a1c24bbd35ced3ff823f82b23840c147d312c96cee0f635a56afb7f397
6
+ metadata.gz: 80788b219b735f2c54aeaa57b5957e8018e8a5c34fbd074ed4fa6a85d43bed4f955eaa547f5f782ba9e482eb19233dafdf197ac77ece18d284c13f47dce0c12c
7
+ data.tar.gz: a1682bcb6a83ebff28c20da879a9bc73aa69cde0b8e86e06d2f6dbae37e74007fa5664ad8c66e115050b17af8fb683ded60c1179e1ea8b9a07471362033ea732
data/README.md CHANGED
@@ -26,9 +26,24 @@ Or install it yourself as:
26
26
 
27
27
  ## Usage
28
28
 
29
+ Once you install this gem, the `rubic` executable can be used. Simply run it as:
30
+
31
+ $ rubic
32
+
33
+ then the <abbr title="Read-Eval-Print Loop">REPL</abbr> will start. Or pass the Scheme source file as:
34
+
35
+ $ rubic /path/to/your_code.scm
36
+
37
+ then the program will be executed.
38
+
39
+ You can also evaluate Scheme code from your Ruby application:
40
+
29
41
  ```ruby
42
+ require 'rubic'
30
43
  rubic = Rubic::Interpreter.new
31
- rubic.evaluate("...write your Scheme code here...")
44
+ rubic.evaluate('(define x 100)')
45
+ rubic.evaluate('(+ x 3)') # => 103
46
+ rubic.evaluate('(list 1 2 3)') # => [1, [2, [3, []]]
32
47
  ```
33
48
 
34
49
  ## Development
data/bin/rubic CHANGED
@@ -6,22 +6,36 @@ require 'readline'
6
6
 
7
7
  using Rubic::Inspector
8
8
 
9
- # TODO: read the code from file when argument passed
9
+ if ARGV.size == 1
10
+ file = ARGV.shift
11
+ File.open(file) do |f|
12
+ rubic = Rubic::Interpreter.new
10
13
 
11
- puts "Welcome to interactive Rubic (v#{Rubic::VERSION})"
12
- puts 'Hit ^D to exit'
14
+ begin
15
+ rubic.evaluate(f.read)
16
+ rescue Rubic::RubicError => e
17
+ puts "\e[31mError: #{e.message}\e[0m"
18
+ exit false
19
+ end
20
+ end
21
+ else
22
+ # REPL mode
13
23
 
14
- rubic = Rubic::Interpreter.new
24
+ puts "Welcome to interactive Rubic (v#{Rubic::VERSION})"
25
+ puts 'Hit ^D to exit'
15
26
 
16
- while input = Readline.readline(">> ", true)
17
- next if input.empty?
18
- while input.count('(') > input.count(')')
19
- input << Readline.readline(' | ', true)
20
- end
27
+ rubic = Rubic::Interpreter.new
28
+
29
+ while input = Readline.readline(">> ", true)
30
+ next if input.empty?
31
+ while input.count('(') > input.count(')')
32
+ input << Readline.readline(' | ', true)
33
+ end
21
34
 
22
- begin
23
- puts '=> ' + rubic.evaluate(input).inspect
24
- rescue Rubic::RubicError => e
25
- puts "\e[31mError: #{e.message}\e[0m"
35
+ begin
36
+ puts '=> ' + rubic.evaluate(input).inspect
37
+ rescue Rubic::RubicError => e
38
+ puts "\e[31mError: #{e.message}\e[0m"
39
+ end
26
40
  end
27
41
  end
@@ -4,6 +4,7 @@ module Rubic
4
4
  class NameError < RubicError; end
5
5
  class ParseError < RubicError; end
6
6
  class RuntimeError < RubicError; end
7
+ class TypeError < RubicError; end
7
8
  end
8
9
 
9
10
  require 'rubic/version'
@@ -0,0 +1,3 @@
1
+ require 'rubic/builtin/list'
2
+ require 'rubic/builtin/number'
3
+ require 'rubic/builtin/output'
@@ -0,0 +1,35 @@
1
+ module Rubic
2
+ module Builtin
3
+ class List
4
+ def cons(a, b)
5
+ [a, b]
6
+ end
7
+
8
+ def car(l)
9
+ unless pair? l
10
+ raise Rubic::TypeError, "pair required, but got `#{l}'"
11
+ end
12
+ l.first
13
+ end
14
+
15
+ def cdr(l)
16
+ unless pair? l
17
+ raise Rubic::TypeError, "pair required, but got `#{l}'"
18
+ end
19
+ l.last
20
+ end
21
+
22
+ def list(*args)
23
+ args.reverse.reduce([]) {|res, e| [e, res] }
24
+ end
25
+
26
+ def pair?(suspect)
27
+ suspect.is_a?(Array) ? suspect.any? : false
28
+ end
29
+
30
+ def null?(suspect)
31
+ suspect.is_a?(Array) ? suspect.empty? : false
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,80 @@
1
+ module Rubic
2
+ module Builtin
3
+ class Number
4
+ def +(*args)
5
+ args.reduce(0) do |res, i|
6
+ unless number? i
7
+ raise Rubic::TypeError, "operation `+' is not defined between `#{res}' and `#{i}'"
8
+ end
9
+ res + i
10
+ end
11
+ end
12
+
13
+ def -(*args)
14
+ case args.size
15
+ when 0
16
+ raise Rubic::ArgumentError, "wrong number of arguments (0 for 1+)"
17
+ when 1
18
+ -args.first
19
+ else
20
+ args.reduce do |res, i|
21
+ unless number? i
22
+ raise Rubic::TypeError, "operation `-' is not defined between `#{res}' and `#{i}'"
23
+ end
24
+ res - i
25
+ end
26
+ end
27
+ end
28
+
29
+ def *(*args)
30
+ args.reduce(1) do |res, i|
31
+ unless number? i
32
+ raise Rubic::TypeError, "operation `*' is not defined between `#{res}' and `#{i}'"
33
+ end
34
+ res * i
35
+ end
36
+ end
37
+
38
+ def /(*args)
39
+ case args.size
40
+ when 0
41
+ raise Rubic::ArgumentError, "wrong number of arguments (0 for 1+)"
42
+ when 1
43
+ 1 / args.first
44
+ else
45
+ args.reduce do |res, i|
46
+ unless number? i
47
+ raise Rubic::TypeError, "operation `/' is not defined between `#{res}' and `#{i}'"
48
+ end
49
+ res / i
50
+ end
51
+ end
52
+ end
53
+
54
+ def <(a, b)
55
+ unless number?(a) && number?(b)
56
+ raise Rubic::TypeError, "operation `<' is not defined between `#{a}' and `#{b}'"
57
+ end
58
+ a < b
59
+ end
60
+
61
+ def >(a, b)
62
+ unless number?(a) && number?(b)
63
+ raise Rubic::TypeError, "operation `>' is not defined between `#{a}' and `#{b}'"
64
+ end
65
+ a > b
66
+ end
67
+
68
+ define_method '=' do |a, b|
69
+ unless number?(a) && number?(b)
70
+ raise Rubic::TypeError, "operation `=' is not defined between `#{a}' and `#{b}'"
71
+ end
72
+ a == b
73
+ end
74
+
75
+ def number?(suspect)
76
+ suspect.is_a?(Integer) || suspect.is_a?(Float)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubic/inspector'
2
+
3
+ module Rubic
4
+ module Builtin
5
+ class Output
6
+ using Rubic::Inspector
7
+
8
+ def display(a)
9
+ print a
10
+ end
11
+
12
+ def newline
13
+ puts
14
+ end
15
+ end
16
+ end
17
+ end
@@ -29,6 +29,13 @@ module Rubic
29
29
  end
30
30
  end
31
31
 
32
+ def extend(klass)
33
+ ext = klass.new
34
+ klass.instance_methods(false).each do |mname|
35
+ defvar(mname, ext.method(mname))
36
+ end
37
+ end
38
+
32
39
  alias []= defvar
33
40
  alias [] refvar
34
41
  end
@@ -14,12 +14,36 @@ module Rubic
14
14
  "#{first.inspect} . #{last.inspect}"
15
15
  end
16
16
  end
17
+
18
+ def to_s
19
+ "(#{to_s_rec})"
20
+ end
21
+
22
+ def to_s_rec
23
+ if empty?
24
+ ''
25
+ elsif last.is_a?(Array)
26
+ [first.to_s, last.to_s_rec].join(' ').strip
27
+ else
28
+ "#{first.to_s} . #{last.to_s}"
29
+ end
30
+ end
17
31
  end
18
32
 
19
33
  refine Proc do
20
34
  def inspect
21
35
  "#<lambda:#{object_id}>"
22
36
  end
37
+
38
+ def to_s
39
+ "#<lambda:#{object_id}>"
40
+ end
41
+ end
42
+
43
+ refine Symbol do
44
+ def inspect
45
+ to_s
46
+ end
23
47
  end
24
48
  end
25
49
  end
@@ -1,35 +1,29 @@
1
- require 'rubic/parser'
1
+ require 'rubic/builtin'
2
2
  require 'rubic/environment'
3
+ require 'rubic/parser'
3
4
 
4
5
  module Rubic
5
6
  class Interpreter
6
7
  DEFAULT_GLOBAL_VARS = {
7
- '+' => -> (*args) { args.reduce(:+) },
8
- '-' => -> (*args) { args.size == 1 ? -args.first : args.reduce(:-) },
9
- '*' => -> (*args) { args.reduce(:*) },
10
- '/' => -> (*args) { args.reduce(:/) },
11
- '<' => -> (a, b) { a < b },
12
- '>' => -> (a, b) { a > b },
13
- '=' => -> (a, b) { a == b },
14
- 'not' => -> (a) { !a },
15
- 'cons' => -> (a, b) { [a, b] },
16
- 'car' => -> (l) { l.first },
17
- 'cdr' => -> (l) { l.last },
18
- 'nil' => [],
19
- 'list' => -> (*args) { args.reverse.reduce([]) {|res, e| [e, res] } },
20
- 'null?' => -> (l) { l.is_a?(Array) ? l.empty? : false },
21
- 'pair?' => -> (l) { l.is_a?(Array) ? l.any? : false },
8
+ :not => -> (a) { !a },
9
+ :eq? => -> (a, b) { a.equal? b },
10
+
11
+ :true => true,
12
+ :false => false,
13
+ :nil => [],
22
14
  }
23
15
 
24
16
  def initialize
25
17
  @parser = Parser.new
26
18
  @global = Environment.new
27
19
  DEFAULT_GLOBAL_VARS.each {|k, v| @global[k] = v }
20
+ builtins = Rubic::Builtin.constants.map {|c| Rubic::Builtin.const_get(c) }
21
+ builtins.each {|ext| @global.extend(ext) }
28
22
  end
29
23
 
30
24
  def evaluate(str)
31
- list = @parser.parse(str)
32
- execute(list, @global)
25
+ seq = @parser.parse(str)
26
+ execute_sequence(seq, @global)
33
27
  end
34
28
 
35
29
  private
@@ -37,34 +31,37 @@ module Rubic
37
31
  def execute(list_or_atom, env)
38
32
  # Atom
39
33
  case list_or_atom
40
- when Float, Integer
34
+ when Float, Integer, String
41
35
  atom = list_or_atom
42
- when String
36
+ when Symbol
43
37
  atom = env[list_or_atom]
44
38
  else
45
39
  # fallthrough
46
40
  end
47
- return atom if atom
41
+ return atom unless atom.nil?
48
42
 
49
43
  list = list_or_atom
50
44
 
51
45
  # Empty list
52
- return nil if list.empty?
46
+ return [] if list.empty?
53
47
 
54
48
  # Special Forms
55
49
  case list.first
56
50
  when :define
57
- _, name, expr = list
58
- env[name] = execute(expr, env)
59
- return
60
- when :define_proc
61
- _, (name, *params), *body = list
62
- env[name] = -> (*args) do
63
- local = Environment.new(env)
64
- local.bind(params, args)
65
- execute_sequence(body, local)
51
+ if list[1].is_a?(Array) # procedure definition
52
+ _, (name, *params), *body = list
53
+ env[name] = -> (*args) do
54
+ local = Environment.new(env)
55
+ local.bind(params, args)
56
+ execute_sequence(body, local)
57
+ end
58
+ return
59
+ else # variable definition
60
+ _, name, expr = list
61
+ env[name] = execute(expr, env)
62
+ return
66
63
  end
67
- return
64
+
68
65
  when :cond
69
66
  _, *clauses = list
70
67
  clauses.each do |pred, expr|
@@ -73,21 +70,25 @@ module Rubic
73
70
  end
74
71
  end
75
72
  return
73
+
76
74
  when :if
77
75
  _, pred, cons, alt = list
78
76
  return execute(pred, env) ? execute(cons, env) : execute(alt, env)
77
+
79
78
  when :and
80
79
  _, *exprs = list
81
80
  exprs.each do |expr|
82
81
  return false unless execute(expr, env)
83
82
  end
84
83
  return true
84
+
85
85
  when :or
86
86
  _, *exprs = list
87
87
  exprs.each do |expr|
88
88
  return true if execute(expr, env)
89
89
  end
90
90
  return false
91
+
91
92
  when :lambda
92
93
  _, (*params), *body = list
93
94
  return -> (*args) do
@@ -95,11 +96,17 @@ module Rubic
95
96
  local.bind(params, args)
96
97
  execute_sequence(body, local)
97
98
  end
99
+
98
100
  when :let
99
101
  _, (*defs), *body = list
100
102
  local = Environment.new(env)
101
103
  defs.each {|name, expr| local[name] = execute(expr, env) }
102
104
  return execute_sequence(body, local)
105
+
106
+ when :quote
107
+ _, expr = list
108
+ return quote(expr)
109
+
103
110
  else
104
111
  # fallthrough
105
112
  end
@@ -109,6 +116,10 @@ module Rubic
109
116
  unless op.respond_to? :call
110
117
  raise Rubic::RuntimeError, "`#{op}' is not a procedure"
111
118
  end
119
+ required = op.arity >= 0 ? op.arity : -op.arity - 1
120
+ if op.arity >= 0 ? required != args.size : required > args.size
121
+ raise Rubic::ArgumentError, "wrong number of arguments (#{args.size} for #{required})"
122
+ end
112
123
  op.call(*args)
113
124
  end
114
125
 
@@ -116,5 +127,13 @@ module Rubic
116
127
  # execute expressions sequentially and returns the last result
117
128
  seq.reduce(nil) {|res, expr| res = execute(expr, env) }
118
129
  end
130
+
131
+ def quote(expr)
132
+ if expr.is_a? Array
133
+ expr.map {|e| quote(e) }.reverse.reduce([]) {|res, e| [e, res] }
134
+ else
135
+ expr
136
+ end
137
+ end
119
138
  end
120
139
  end
@@ -12,7 +12,7 @@ module Rubic
12
12
 
13
13
  class Parser < Racc::Parser
14
14
 
15
- module_eval(<<'...end parser.y/module_eval...', 'parser.y', 113)
15
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 134)
16
16
  EOT = [false, nil] # end of token
17
17
  SYM_CHARS = Regexp.escape("+-*/<>=?")
18
18
 
@@ -28,7 +28,7 @@ def next_token
28
28
  case
29
29
  when @s.scan(/[0-9]+(\.[0-9]+)?/)
30
30
  [:NUMBER, @s[0].include?('.') ? @s[0].to_f : @s[0].to_i]
31
- when @s.scan(/[\(\)]/o)
31
+ when @s.scan(/[()']/)
32
32
  [@s[0], nil]
33
33
  when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o)
34
34
  case @s[0] # keyword check
@@ -48,9 +48,13 @@ def next_token
48
48
  [:KW_LAMBDA, nil]
49
49
  when 'let'
50
50
  [:KW_LET, nil]
51
+ when 'quote'
52
+ [:KW_QUOTE, nil]
51
53
  else
52
- [:IDENT, @s[0]]
54
+ [:IDENT, @s[0].to_sym]
53
55
  end
56
+ when @s.scan(/"([^"]*)"/)
57
+ [:STRING, @s[1]]
54
58
  else
55
59
  raise Rubic::ParseError, "unknown character #{@s.getch}"
56
60
  end
@@ -64,108 +68,141 @@ end
64
68
  ##### State transition tables begin ###
65
69
 
66
70
  racc_action_table = [
67
- 2, 12, 38, 13, 3, 4, 15, 16, 2, 17,
68
- 18, 19, 3, 4, 2, 57, 42, 2, 3, 4,
69
- 2, 3, 4, 2, 3, 4, 2, 3, 4, 26,
70
- 3, 4, 2, 25, 64, 58, 3, 4, 2, 56,
71
- 63, 2, 3, 4, 2, 3, 4, 2, 3, 4,
72
- 32, 3, 4, 2, 52, 33, 51, 3, 4, 2,
73
- 29, 35, 39, 3, 4, 2, 61, 36, 2, 3,
74
- 4, 2, 3, 4, 2, 3, 4, 31, 3, 4,
75
- 2, 29, 66, 2, 3, 4, 2, 3, 4, 2,
76
- 3, 4, 46, 3, 4, 54, 55, 53, 51, 20,
77
- 11, 67 ]
71
+ 3, 64, 67, 60, 4, 5, 6, 3, 37, 75,
72
+ 47, 4, 5, 6, 15, 34, 63, 55, 62, 33,
73
+ 65, 15, 3, 17, 20, 18, 4, 5, 6, 21,
74
+ 22, 66, 23, 24, 25, 26, 15, 3, 46, 44,
75
+ 3, 4, 5, 6, 4, 5, 6, 61, 40, 60,
76
+ 70, 15, 3, 39, 15, 3, 4, 5, 6, 4,
77
+ 5, 6, 37, 54, 29, 16, 15, 3, 76, 15,
78
+ 3, 4, 5, 6, 4, 5, 6, nil, nil, nil,
79
+ nil, 15, nil, 3, 15, 73, nil, 4, 5, 6,
80
+ 3, nil, 72, nil, 4, 5, 6, 15, nil, nil,
81
+ nil, 3, nil, nil, 15, 4, 5, 6, 3, nil,
82
+ nil, nil, 4, 5, 6, 15, nil, nil, nil, 3,
83
+ nil, nil, 15, 4, 5, 6, 3, nil, nil, nil,
84
+ 4, 5, 6, 15, nil, nil, nil, 3, nil, 42,
85
+ 15, 4, 5, 6, 3, nil, 43, nil, 4, 5,
86
+ 6, 15, nil, nil, nil, 3, nil, nil, 15, 4,
87
+ 5, 6, 3, nil, nil, nil, 4, 5, 6, 15,
88
+ nil, nil, nil, 3, nil, nil, 15, 4, 5, 6,
89
+ 3, nil, nil, nil, 4, 5, 6, 15, nil, nil,
90
+ nil, 3, nil, nil, 15, 4, 5, 6, 3, nil,
91
+ nil, nil, 4, 5, 6, 15, nil, nil, nil, 3,
92
+ nil, nil, 15, 4, 5, 6, nil, nil, 50, nil,
93
+ nil, nil, nil, 15 ]
78
94
 
79
95
  racc_action_check = [
80
- 2, 2, 26, 2, 2, 2, 2, 2, 29, 2,
81
- 2, 2, 29, 29, 55, 49, 29, 61, 55, 55,
82
- 12, 61, 61, 13, 12, 12, 14, 13, 13, 15,
83
- 14, 14, 60, 15, 60, 50, 60, 60, 59, 48,
84
- 59, 17, 59, 59, 0, 17, 17, 53, 0, 0,
85
- 19, 53, 53, 21, 44, 21, 44, 21, 21, 23,
86
- 27, 23, 27, 23, 23, 24, 54, 24, 25, 24,
87
- 24, 52, 25, 25, 43, 52, 52, 18, 43, 43,
88
- 62, 16, 62, 41, 62, 62, 42, 41, 41, 30,
89
- 42, 42, 37, 30, 30, 45, 47, 45, 47, 11,
90
- 1, 65 ]
96
+ 0, 56, 59, 56, 0, 0, 0, 71, 35, 71,
97
+ 35, 71, 71, 71, 0, 21, 53, 45, 53, 21,
98
+ 57, 71, 3, 3, 3, 3, 3, 3, 3, 3,
99
+ 3, 58, 3, 3, 3, 3, 3, 14, 34, 32,
100
+ 15, 14, 14, 14, 15, 15, 15, 52, 25, 52,
101
+ 63, 14, 70, 24, 15, 17, 70, 70, 70, 17,
102
+ 17, 17, 22, 41, 16, 1, 70, 18, 74, 17,
103
+ 19, 18, 18, 18, 19, 19, 19, nil, nil, nil,
104
+ nil, 18, nil, 69, 19, 69, nil, 69, 69, 69,
105
+ 68, nil, 68, nil, 68, 68, 68, 69, nil, nil,
106
+ nil, 23, nil, nil, 68, 23, 23, 23, 64, nil,
107
+ nil, nil, 64, 64, 64, 23, nil, nil, nil, 62,
108
+ nil, nil, 64, 62, 62, 62, 26, nil, nil, nil,
109
+ 26, 26, 26, 62, nil, nil, nil, 30, nil, 30,
110
+ 26, 30, 30, 30, 31, nil, 31, nil, 31, 31,
111
+ 31, 30, nil, nil, nil, 61, nil, nil, 31, 61,
112
+ 61, 61, 33, nil, nil, nil, 33, 33, 33, 61,
113
+ nil, nil, nil, 51, nil, nil, 33, 51, 51, 51,
114
+ 50, nil, nil, nil, 50, 50, 50, 51, nil, nil,
115
+ nil, 49, nil, nil, 50, 49, 49, 49, 38, nil,
116
+ nil, nil, 38, 38, 38, 49, nil, nil, nil, 37,
117
+ nil, nil, 38, 37, 37, 37, nil, nil, 37, nil,
118
+ nil, nil, nil, 37 ]
91
119
 
92
120
  racc_action_pointer = [
93
- 42, 100, -2, nil, nil, nil, nil, nil, nil, nil,
94
- nil, 99, 18, 21, 24, 27, 79, 39, 75, 48,
95
- nil, 51, nil, 57, 63, 66, -4, 58, nil, 6,
96
- 87, nil, nil, nil, nil, nil, nil, 88, nil, nil,
97
- nil, 81, 84, 72, 50, 93, nil, 92, 35, 11,
98
- 31, nil, 69, 45, 60, 12, nil, nil, nil, 36,
99
- 30, 15, 78, nil, nil, 97, nil, nil ]
121
+ -2, 65, nil, 20, nil, nil, nil, nil, nil, nil,
122
+ nil, nil, nil, nil, 35, 38, 64, 53, 65, 68,
123
+ nil, 13, 60, 99, 51, 46, 124, nil, nil, nil,
124
+ 135, 142, 35, 160, 32, 6, nil, 207, 196, nil,
125
+ nil, 59, nil, nil, nil, 13, nil, nil, nil, 189,
126
+ 178, 171, 43, 14, nil, nil, -3, 16, 27, -2,
127
+ nil, 153, 117, 44, 106, nil, nil, nil, 88, 81,
128
+ 50, 5, nil, nil, 64, nil, nil ]
100
129
 
101
130
  racc_action_default = [
102
- -28, -28, -28, -4, -5, -6, -7, -8, -9, -10,
103
- -11, -28, -28, -28, -28, -28, -28, -28, -28, -28,
104
- 68, -28, -12, -28, -28, -28, -28, -28, -19, -28,
105
- -28, -16, -26, -1, -13, -2, -3, -28, -16, -18,
106
- -20, -28, -28, -28, -28, -28, -14, -28, -28, -28,
107
- -28, -17, -28, -28, -28, -28, -21, -22, -23, -28,
108
- -28, -28, -28, -24, -25, -28, -15, -27 ]
131
+ -17, -35, -1, -35, -6, -7, -8, -9, -10, -11,
132
+ -12, -13, -14, -15, -18, -35, -35, -35, -35, -17,
133
+ -5, -35, -35, -35, -35, -35, -35, -16, -34, 77,
134
+ -35, -35, -35, -35, -35, -35, -24, -35, -35, -21,
135
+ -31, -35, -2, -3, -4, -35, -21, -23, -25, -35,
136
+ -35, -35, -35, -35, -33, -19, -35, -35, -35, -35,
137
+ -22, -35, -35, -35, -35, -26, -27, -28, -35, -35,
138
+ -35, -35, -29, -30, -35, -20, -32 ]
109
139
 
110
140
  racc_goto_table = [
111
- 1, 28, 14, 44, 21, 23, 24, 27, 45, nil,
112
- 47, nil, 40, nil, nil, nil, nil, 30, nil, nil,
113
- nil, 34, nil, 34, 34, 37, nil, nil, nil, 41,
114
- 43, nil, nil, nil, nil, nil, nil, nil, nil, nil,
115
- nil, 48, 49, 50, 59, 60, nil, 62, nil, nil,
116
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 34,
117
- 34, 65, 34 ]
141
+ 19, 36, 2, 52, 1, 30, 31, 35, 53, nil,
142
+ 56, 27, 28, nil, 48, nil, nil, nil, nil, nil,
143
+ 38, 32, nil, 41, nil, nil, nil, 27, 27, nil,
144
+ 45, nil, nil, nil, 49, 51, nil, nil, nil, nil,
145
+ nil, nil, nil, nil, nil, nil, 57, 58, 59, 68,
146
+ 69, nil, 71, nil, nil, nil, nil, nil, nil, nil,
147
+ nil, nil, nil, nil, nil, 27, 27, 74, 27 ]
118
148
 
119
149
  racc_goto_check = [
120
- 1, 11, 1, 9, 2, 2, 2, 10, 12, nil,
121
- 9, nil, 11, nil, nil, nil, nil, 1, nil, nil,
122
- nil, 1, nil, 1, 1, 1, nil, nil, nil, 1,
123
- 1, nil, nil, nil, nil, nil, nil, nil, nil, nil,
124
- nil, 1, 1, 1, 2, 2, nil, 2, nil, nil,
125
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 1,
126
- 1, 1, 1 ]
150
+ 3, 13, 2, 11, 1, 4, 4, 12, 14, nil,
151
+ 11, 3, 3, nil, 13, nil, nil, nil, nil, nil,
152
+ 3, 2, nil, 3, nil, nil, nil, 3, 3, nil,
153
+ 3, nil, nil, nil, 3, 3, nil, nil, nil, nil,
154
+ nil, nil, nil, nil, nil, nil, 3, 3, 3, 4,
155
+ 4, nil, 4, nil, nil, nil, nil, nil, nil, nil,
156
+ nil, nil, nil, nil, nil, 3, 3, 3, 3 ]
127
157
 
128
158
  racc_goto_pointer = [
129
- nil, 0, -8, nil, nil, nil, nil, nil, nil, -28,
130
- -9, -15, -24 ]
159
+ nil, 4, 2, -3, -12, nil, nil, nil, nil, nil,
160
+ nil, -36, -15, -21, -32 ]
131
161
 
132
162
  racc_goto_default = [
133
- nil, 22, nil, 5, 6, 7, 8, 9, 10, nil,
134
- nil, nil, nil ]
163
+ nil, nil, nil, 13, 14, 7, 8, 9, 10, 11,
164
+ 12, nil, nil, nil, nil ]
135
165
 
136
166
  racc_reduce_table = [
137
167
  0, 0, :racc_error,
138
- 4, 15, :_reduce_1,
139
- 4, 15, :_reduce_2,
140
- 4, 15, :_reduce_3,
141
- 1, 15, :_reduce_none,
142
- 1, 15, :_reduce_none,
143
- 1, 15, :_reduce_none,
144
- 1, 15, :_reduce_none,
145
- 1, 15, :_reduce_none,
146
- 1, 15, :_reduce_none,
147
- 1, 15, :_reduce_none,
148
- 1, 15, :_reduce_none,
149
- 1, 16, :_reduce_12,
150
- 2, 16, :_reduce_13,
151
- 5, 17, :_reduce_14,
152
- 8, 18, :_reduce_15,
153
- 0, 23, :_reduce_16,
154
- 2, 23, :_reduce_17,
155
- 4, 19, :_reduce_18,
156
- 1, 24, :_reduce_19,
157
- 2, 24, :_reduce_20,
158
- 4, 25, :_reduce_21,
159
- 4, 25, :_reduce_22,
160
- 6, 20, :_reduce_23,
161
- 7, 21, :_reduce_24,
162
- 7, 22, :_reduce_25,
163
- 0, 26, :_reduce_26,
164
- 5, 26, :_reduce_27 ]
165
-
166
- racc_reduce_n = 28
167
-
168
- racc_shift_n = 68
168
+ 1, 18, :_reduce_none,
169
+ 4, 20, :_reduce_2,
170
+ 4, 20, :_reduce_3,
171
+ 4, 20, :_reduce_4,
172
+ 2, 20, :_reduce_5,
173
+ 1, 20, :_reduce_none,
174
+ 1, 20, :_reduce_none,
175
+ 1, 20, :_reduce_none,
176
+ 1, 20, :_reduce_none,
177
+ 1, 20, :_reduce_none,
178
+ 1, 20, :_reduce_none,
179
+ 1, 20, :_reduce_none,
180
+ 1, 20, :_reduce_none,
181
+ 1, 20, :_reduce_none,
182
+ 1, 21, :_reduce_15,
183
+ 2, 21, :_reduce_16,
184
+ 0, 19, :_reduce_17,
185
+ 1, 19, :_reduce_none,
186
+ 5, 22, :_reduce_19,
187
+ 8, 22, :_reduce_20,
188
+ 0, 28, :_reduce_21,
189
+ 2, 28, :_reduce_22,
190
+ 4, 23, :_reduce_23,
191
+ 1, 29, :_reduce_24,
192
+ 2, 29, :_reduce_25,
193
+ 4, 30, :_reduce_26,
194
+ 4, 30, :_reduce_27,
195
+ 6, 24, :_reduce_28,
196
+ 7, 25, :_reduce_29,
197
+ 7, 26, :_reduce_30,
198
+ 0, 31, :_reduce_31,
199
+ 5, 31, :_reduce_32,
200
+ 4, 27, :_reduce_33,
201
+ 2, 27, :_reduce_34 ]
202
+
203
+ racc_reduce_n = 35
204
+
205
+ racc_shift_n = 77
169
206
 
170
207
  racc_token_table = {
171
208
  false => 0,
@@ -176,14 +213,17 @@ racc_token_table = {
176
213
  :KW_OR => 5,
177
214
  :IDENT => 6,
178
215
  :NUMBER => 7,
179
- :KW_DEFINE => 8,
180
- :KW_COND => 9,
181
- :KW_ELSE => 10,
182
- :KW_IF => 11,
183
- :KW_LAMBDA => 12,
184
- :KW_LET => 13 }
185
-
186
- racc_nt_base = 14
216
+ :STRING => 8,
217
+ :KW_DEFINE => 9,
218
+ :KW_COND => 10,
219
+ :KW_ELSE => 11,
220
+ :KW_IF => 12,
221
+ :KW_LAMBDA => 13,
222
+ :KW_LET => 14,
223
+ :KW_QUOTE => 15,
224
+ "'" => 16 }
225
+
226
+ racc_nt_base = 17
187
227
 
188
228
  racc_use_result_var = false
189
229
 
@@ -212,21 +252,26 @@ Racc_token_to_s_table = [
212
252
  "KW_OR",
213
253
  "IDENT",
214
254
  "NUMBER",
255
+ "STRING",
215
256
  "KW_DEFINE",
216
257
  "KW_COND",
217
258
  "KW_ELSE",
218
259
  "KW_IF",
219
260
  "KW_LAMBDA",
220
261
  "KW_LET",
262
+ "KW_QUOTE",
263
+ "\"'\"",
221
264
  "$start",
265
+ "program",
266
+ "opt_seq",
222
267
  "expr",
223
268
  "seq",
224
269
  "define",
225
- "define_proc",
226
270
  "cond",
227
271
  "if",
228
272
  "lambda",
229
273
  "let",
274
+ "quote",
230
275
  "params",
231
276
  "clauses",
232
277
  "clause",
@@ -238,30 +283,35 @@ Racc_debug_parser = false
238
283
 
239
284
  # reduce 0 omitted
240
285
 
241
- module_eval(<<'.,.,', 'parser.y', 6)
242
- def _reduce_1(val, _values)
286
+ # reduce 1 omitted
287
+
288
+ module_eval(<<'.,.,', 'parser.y', 8)
289
+ def _reduce_2(val, _values)
243
290
  [:and, *val[2]]
244
291
 
245
292
  end
246
293
  .,.,
247
294
 
248
- module_eval(<<'.,.,', 'parser.y', 10)
249
- def _reduce_2(val, _values)
295
+ module_eval(<<'.,.,', 'parser.y', 12)
296
+ def _reduce_3(val, _values)
250
297
  [:or, *val[2]]
251
298
 
252
299
  end
253
300
  .,.,
254
301
 
255
- module_eval(<<'.,.,', 'parser.y', 14)
256
- def _reduce_3(val, _values)
302
+ module_eval(<<'.,.,', 'parser.y', 16)
303
+ def _reduce_4(val, _values)
257
304
  [val[1], *val[2]]
258
305
 
259
306
  end
260
307
  .,.,
261
308
 
262
- # reduce 4 omitted
263
-
264
- # reduce 5 omitted
309
+ module_eval(<<'.,.,', 'parser.y', 20)
310
+ def _reduce_5(val, _values)
311
+ []
312
+
313
+ end
314
+ .,.,
265
315
 
266
316
  # reduce 6 omitted
267
317
 
@@ -275,118 +325,147 @@ module_eval(<<'.,.,', 'parser.y', 14)
275
325
 
276
326
  # reduce 11 omitted
277
327
 
278
- module_eval(<<'.,.,', 'parser.y', 27)
279
- def _reduce_12(val, _values)
280
- [val[0]]
281
-
328
+ # reduce 12 omitted
329
+
330
+ # reduce 13 omitted
331
+
332
+ # reduce 14 omitted
333
+
334
+ module_eval(<<'.,.,', 'parser.y', 34)
335
+ def _reduce_15(val, _values)
336
+ [val[0]]
337
+
282
338
  end
283
339
  .,.,
284
340
 
285
- module_eval(<<'.,.,', 'parser.y', 31)
286
- def _reduce_13(val, _values)
287
- val[0].push(val[1])
288
-
341
+ module_eval(<<'.,.,', 'parser.y', 38)
342
+ def _reduce_16(val, _values)
343
+ val[0].push(val[1])
344
+
345
+ end
346
+ .,.,
347
+
348
+ module_eval(<<'.,.,', 'parser.y', 43)
349
+ def _reduce_17(val, _values)
350
+ []
351
+
289
352
  end
290
353
  .,.,
291
354
 
292
- module_eval(<<'.,.,', 'parser.y', 37)
293
- def _reduce_14(val, _values)
355
+ # reduce 18 omitted
356
+
357
+ module_eval(<<'.,.,', 'parser.y', 50)
358
+ def _reduce_19(val, _values)
294
359
  [:define, val[2], val[3]]
295
360
 
296
361
  end
297
362
  .,.,
298
363
 
299
- module_eval(<<'.,.,', 'parser.y', 43)
300
- def _reduce_15(val, _values)
301
- [:define_proc, [val[3], *val[4]], *val[6]]
302
-
364
+ module_eval(<<'.,.,', 'parser.y', 54)
365
+ def _reduce_20(val, _values)
366
+ [:define, [val[3], *val[4]], *val[6]]
367
+
303
368
  end
304
369
  .,.,
305
370
 
306
- module_eval(<<'.,.,', 'parser.y', 48)
307
- def _reduce_16(val, _values)
371
+ module_eval(<<'.,.,', 'parser.y', 59)
372
+ def _reduce_21(val, _values)
308
373
  []
309
374
 
310
375
  end
311
376
  .,.,
312
377
 
313
- module_eval(<<'.,.,', 'parser.y', 52)
314
- def _reduce_17(val, _values)
378
+ module_eval(<<'.,.,', 'parser.y', 63)
379
+ def _reduce_22(val, _values)
315
380
  val[0].push(val[1])
316
381
 
317
382
  end
318
383
  .,.,
319
384
 
320
- module_eval(<<'.,.,', 'parser.y', 58)
321
- def _reduce_18(val, _values)
385
+ module_eval(<<'.,.,', 'parser.y', 69)
386
+ def _reduce_23(val, _values)
322
387
  [:cond, *val[2]]
323
388
 
324
389
  end
325
390
  .,.,
326
391
 
327
- module_eval(<<'.,.,', 'parser.y', 63)
328
- def _reduce_19(val, _values)
392
+ module_eval(<<'.,.,', 'parser.y', 74)
393
+ def _reduce_24(val, _values)
329
394
  [val[0]]
330
395
 
331
396
  end
332
397
  .,.,
333
398
 
334
- module_eval(<<'.,.,', 'parser.y', 67)
335
- def _reduce_20(val, _values)
399
+ module_eval(<<'.,.,', 'parser.y', 78)
400
+ def _reduce_25(val, _values)
336
401
  val[0].push(val[1])
337
402
 
338
403
  end
339
404
  .,.,
340
405
 
341
- module_eval(<<'.,.,', 'parser.y', 72)
342
- def _reduce_21(val, _values)
406
+ module_eval(<<'.,.,', 'parser.y', 83)
407
+ def _reduce_26(val, _values)
343
408
  [val[1], val[2]]
344
409
 
345
410
  end
346
411
  .,.,
347
412
 
348
- module_eval(<<'.,.,', 'parser.y', 76)
349
- def _reduce_22(val, _values)
413
+ module_eval(<<'.,.,', 'parser.y', 87)
414
+ def _reduce_27(val, _values)
350
415
  [:else, val[2]]
351
416
 
352
417
  end
353
418
  .,.,
354
419
 
355
- module_eval(<<'.,.,', 'parser.y', 82)
356
- def _reduce_23(val, _values)
420
+ module_eval(<<'.,.,', 'parser.y', 93)
421
+ def _reduce_28(val, _values)
357
422
  [:if, val[2], val[3], val[4]]
358
423
 
359
424
  end
360
425
  .,.,
361
426
 
362
- module_eval(<<'.,.,', 'parser.y', 88)
363
- def _reduce_24(val, _values)
427
+ module_eval(<<'.,.,', 'parser.y', 99)
428
+ def _reduce_29(val, _values)
364
429
  [:lambda, val[3], *val[5]]
365
430
 
366
431
  end
367
432
  .,.,
368
433
 
369
- module_eval(<<'.,.,', 'parser.y', 94)
370
- def _reduce_25(val, _values)
434
+ module_eval(<<'.,.,', 'parser.y', 105)
435
+ def _reduce_30(val, _values)
371
436
  [:let, val[3], *val[5]]
372
437
 
373
438
  end
374
439
  .,.,
375
440
 
376
- module_eval(<<'.,.,', 'parser.y', 98)
377
- def _reduce_26(val, _values)
441
+ module_eval(<<'.,.,', 'parser.y', 109)
442
+ def _reduce_31(val, _values)
378
443
  []
379
444
 
380
445
  end
381
446
  .,.,
382
447
 
383
- module_eval(<<'.,.,', 'parser.y', 102)
384
- def _reduce_27(val, _values)
448
+ module_eval(<<'.,.,', 'parser.y', 113)
449
+ def _reduce_32(val, _values)
385
450
  val[0].push([val[2], val[3]])
386
451
 
387
452
  end
388
453
  .,.,
389
454
 
455
+ module_eval(<<'.,.,', 'parser.y', 119)
456
+ def _reduce_33(val, _values)
457
+ [:quote, val[2]]
458
+
459
+ end
460
+ .,.,
461
+
462
+ module_eval(<<'.,.,', 'parser.y', 123)
463
+ def _reduce_34(val, _values)
464
+ [:quote, val[1]]
465
+
466
+ end
467
+ .,.,
468
+
390
469
  def _reduce_none(val, _values)
391
470
  val[0]
392
471
  end
@@ -2,6 +2,8 @@ class Parser
2
2
  options no_result_var
3
3
 
4
4
  rule
5
+ program : opt_seq
6
+
5
7
  expr : '(' KW_AND seq ')'
6
8
  {
7
9
  [:and, *val[2]]
@@ -10,39 +12,48 @@ rule
10
12
  {
11
13
  [:or, *val[2]]
12
14
  }
13
- | '(' expr seq ')'
15
+ | '(' expr opt_seq ')'
14
16
  {
15
17
  [val[1], *val[2]]
16
18
  }
19
+ | '(' ')'
20
+ {
21
+ []
22
+ }
17
23
  | IDENT
18
24
  | NUMBER
25
+ | STRING
19
26
  | define
20
- | define_proc
21
27
  | cond
22
28
  | if
23
29
  | lambda
24
30
  | let
31
+ | quote
25
32
 
26
- seq : expr
27
- {
28
- [val[0]]
29
- }
30
- | seq expr
31
- {
32
- val[0].push(val[1])
33
- }
33
+ seq : expr
34
+ {
35
+ [val[0]]
36
+ }
37
+ | seq expr
38
+ {
39
+ val[0].push(val[1])
40
+ }
41
+
42
+ opt_seq : /* empty */
43
+ {
44
+ []
45
+ }
46
+ | seq
34
47
 
35
48
  /* Define statement */
36
49
  define : '(' KW_DEFINE IDENT expr ')'
37
50
  {
38
51
  [:define, val[2], val[3]]
39
52
  }
40
-
41
- /* Procedure definition */
42
- define_proc : '(' KW_DEFINE '(' IDENT params ')' seq ')'
43
- {
44
- [:define_proc, [val[3], *val[4]], *val[6]]
45
- }
53
+ | '(' KW_DEFINE '(' IDENT params ')' seq ')'
54
+ {
55
+ [:define, [val[3], *val[4]], *val[6]]
56
+ }
46
57
 
47
58
  params : /* empty */
48
59
  {
@@ -102,6 +113,16 @@ rule
102
113
  {
103
114
  val[0].push([val[2], val[3]])
104
115
  }
116
+
117
+ /* quote expression */
118
+ quote : '(' KW_QUOTE expr ')'
119
+ {
120
+ [:quote, val[2]]
121
+ }
122
+ | '\'' expr
123
+ {
124
+ [:quote, val[1]]
125
+ }
105
126
  end
106
127
 
107
128
  ---- header
@@ -125,7 +146,7 @@ def next_token
125
146
  case
126
147
  when @s.scan(/[0-9]+(\.[0-9]+)?/)
127
148
  [:NUMBER, @s[0].include?('.') ? @s[0].to_f : @s[0].to_i]
128
- when @s.scan(/[\(\)]/o)
149
+ when @s.scan(/[()']/)
129
150
  [@s[0], nil]
130
151
  when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o)
131
152
  case @s[0] # keyword check
@@ -145,9 +166,13 @@ def next_token
145
166
  [:KW_LAMBDA, nil]
146
167
  when 'let'
147
168
  [:KW_LET, nil]
169
+ when 'quote'
170
+ [:KW_QUOTE, nil]
148
171
  else
149
- [:IDENT, @s[0]]
172
+ [:IDENT, @s[0].to_sym]
150
173
  end
174
+ when @s.scan(/"([^"]*)"/)
175
+ [:STRING, @s[1]]
151
176
  else
152
177
  raise Rubic::ParseError, "unknown character #{@s.getch}"
153
178
  end
@@ -1,3 +1,3 @@
1
1
  module Rubic
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - notozeki
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-15 00:00:00.000000000 Z
11
+ date: 2015-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -112,6 +112,10 @@ files:
112
112
  - bin/rubic
113
113
  - bin/setup
114
114
  - lib/rubic.rb
115
+ - lib/rubic/builtin.rb
116
+ - lib/rubic/builtin/list.rb
117
+ - lib/rubic/builtin/number.rb
118
+ - lib/rubic/builtin/output.rb
115
119
  - lib/rubic/environment.rb
116
120
  - lib/rubic/inspector.rb
117
121
  - lib/rubic/interpreter.rb