rubic 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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