rouge-lang 0.0.1

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/lib/rouge/repl.rb ADDED
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+ require 'readline'
3
+
4
+ module Rouge::REPL; end
5
+
6
+ class << Rouge::REPL
7
+ def repl_error(e)
8
+ STDOUT.puts "!! #{e.class}: #{e.message}"
9
+ STDOUT.puts "#{e.backtrace.join "\n"}"
10
+ end
11
+
12
+ def repl(argv)
13
+ context = Rouge::Context.new Rouge[:user]
14
+
15
+ if ARGV == ["--time-startup"]
16
+ STDOUT.puts Time.now - Rouge.start
17
+ exit(0)
18
+ elsif argv.length == 1
19
+ f = File.read(argv[0])
20
+ if f[0] == ?#
21
+ f = f[f.index("\n") + 1..-1]
22
+ end
23
+
24
+ context.readeval(f)
25
+ exit(0)
26
+ elsif argv.length > 1
27
+ STDERR.puts "!! usage: #$0 [FILE]"
28
+ exit(1)
29
+ end
30
+
31
+ count = 0
32
+ chaining = false
33
+ while true
34
+ if not chaining
35
+ prompt = "#{context.ns.name}=> "
36
+ input = Readline.readline(prompt, true)
37
+ else
38
+ prompt = "#{" " * [0, context.ns.name.length - 2].max}#_=> "
39
+ input += "\n" + Readline.readline(prompt, true)
40
+ end
41
+
42
+ if input.nil?
43
+ STDOUT.print "\n"
44
+ break
45
+ end
46
+
47
+ begin
48
+ form = context.ns.read(input)
49
+ rescue Rouge::Reader::EndOfDataError
50
+ chaining = true
51
+ next
52
+ rescue Rouge::Reader::UnexpectedCharacterError => reader_err
53
+ repl_error reader_err
54
+ end
55
+
56
+ chaining = false
57
+ begin
58
+ form = Rouge::Compiler.compile(
59
+ context.ns,
60
+ Set[*context.lexical_keys],
61
+ form)
62
+ result = context.eval(form)
63
+
64
+ Rouge.print(result, STDOUT)
65
+ STDOUT.puts
66
+
67
+ count += 1 if count < 10
68
+ count.downto(2) do |i|
69
+ context.set_here :"*#{i}", context[:"*#{i - 1}"]
70
+ end
71
+ context.set_here :"*1", result
72
+ rescue Rouge::Context::ChangeContextException => cce
73
+ context = cce.context
74
+ count = 0
75
+ rescue => e
76
+ repl_error e
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ # vim: set sw=2 et cc=80:
data/lib/rouge/seq.rb ADDED
@@ -0,0 +1,221 @@
1
+ # encoding: utf-8
2
+
3
+ module Rouge::Seq
4
+ Empty = Object.new
5
+
6
+ class Cons; end
7
+
8
+ module ISeq; end
9
+
10
+ module ASeq
11
+ include ISeq
12
+
13
+ def inspect
14
+ "(#{to_a.map(&:inspect).join " "})"
15
+ end
16
+
17
+ def to_s; inspect; end
18
+
19
+ def seq; self; end
20
+
21
+ def first; raise NotImplementedError; end
22
+ def next; raise NotImplementedError; end
23
+
24
+ def more
25
+ s = self.next
26
+ if s.nil?
27
+ Empty
28
+ else
29
+ s
30
+ end
31
+ end
32
+
33
+ def cons(o)
34
+ Cons.new(o, self)
35
+ end
36
+
37
+ def length
38
+ l = 0
39
+ cursor = self
40
+
41
+ while cursor != Empty
42
+ l += 1
43
+ cursor = cursor.more
44
+ end
45
+
46
+ l
47
+ end
48
+
49
+ alias count length
50
+
51
+ def [](i)
52
+ return to_a[i] if i.is_a? Range
53
+
54
+ cursor = self
55
+
56
+ i += self.length if i < 0
57
+
58
+ while i > 0
59
+ i -= 1
60
+ cursor = cursor.more
61
+ return nil if cursor == Empty
62
+ end
63
+
64
+ cursor.first
65
+ end
66
+
67
+ def ==(seq)
68
+ (seq.is_a?(ISeq) and self.to_a == seq.to_a) or
69
+ (seq.is_a?(::Array) and self.to_a == seq)
70
+ end
71
+
72
+ def each(&block)
73
+ return self.enum_for(:each) if block.nil?
74
+
75
+ yield self.first
76
+
77
+ cursor = self.more
78
+ while cursor != Empty
79
+ yield cursor.first
80
+ cursor = cursor.more
81
+ end
82
+
83
+ self
84
+ end
85
+
86
+ def map(&block)
87
+ return self.enum_for(:map) if block.nil?
88
+
89
+ r = []
90
+ self.each {|e| r << block.call(e)}
91
+ r
92
+ end
93
+
94
+ def to_a
95
+ r = []
96
+ self.each {|e| r << e}
97
+ r
98
+ end
99
+
100
+ def map(&block)
101
+ Cons[*to_a.map(&block)]
102
+ end
103
+ end
104
+
105
+ class << Empty
106
+ include ASeq
107
+
108
+ def inspect; "()"; end
109
+ def to_s; inspect; end
110
+
111
+ def seq; nil; end
112
+ def first; nil; end
113
+ def next; nil; end
114
+
115
+ def each(&block)
116
+ return self.enum_for(:each) if block.nil?
117
+ end
118
+ end
119
+
120
+ Empty.freeze
121
+
122
+ class Cons
123
+ include ASeq
124
+
125
+ def initialize(head, tail)
126
+ if tail and !tail.is_a?(ISeq)
127
+ raise ArgumentError,
128
+ "tail should be an ISeq, not #{tail.inspect} (#{tail.class})"
129
+ end
130
+
131
+ @head, @tail = head, tail
132
+ end
133
+
134
+ def first; @head; end
135
+ def next; Rouge::Seq.seq @tail; end
136
+
137
+ def self.[](*elements)
138
+ return Empty if elements.length.zero?
139
+
140
+ head = nil
141
+ (elements.length - 1).downto(0).each do |i|
142
+ head = new(elements[i], head.freeze)
143
+ end
144
+
145
+ head.freeze
146
+ end
147
+
148
+ attr_reader :head, :tail
149
+ end
150
+
151
+ class Array
152
+ include ASeq
153
+
154
+ def initialize(array, i)
155
+ @array, @i = array, i
156
+ end
157
+
158
+ def first
159
+ @array[@i]
160
+ end
161
+
162
+ def next
163
+ if @i + 1 < @array.length
164
+ Array.new(@array, @i + 1)
165
+ end
166
+ end
167
+ end
168
+
169
+ class Lazy
170
+ include ISeq
171
+
172
+ def initialize(body)
173
+ @body = body
174
+ @realized = false
175
+ end
176
+
177
+ def seq
178
+ if @realized
179
+ @result
180
+ else
181
+ @result = Rouge::Seq.seq(@body.call) || Empty
182
+ @realized = true
183
+ @result
184
+ end
185
+ rescue UnknownSeqError
186
+ @realized = true
187
+ @result = Empty
188
+ raise
189
+ end
190
+
191
+ def method_missing(sym, *args, &block)
192
+ seq.send(sym, *args, &block)
193
+ end
194
+
195
+ def inspect; seq.inspect; end
196
+ def to_s; seq.to_s; end
197
+ end
198
+
199
+ UnknownSeqError = Class.new(StandardError)
200
+
201
+ def self.seq(form)
202
+ case form
203
+ when ISeq
204
+ form.seq
205
+ when NilClass
206
+ form
207
+ when ::Array
208
+ if form.empty?
209
+ nil
210
+ else
211
+ Rouge::Seq::Array.new(form, 0)
212
+ end
213
+ when Enumerator
214
+ seq(form.to_a)
215
+ else
216
+ raise UnknownSeqError, form.inspect
217
+ end
218
+ end
219
+ end
220
+
221
+ # vim: set sw=2 et cc=80:
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+ require 'rouge/metadata'
3
+
4
+ class Rouge::Symbol
5
+ include Rouge::Metadata
6
+
7
+ # The symbols for t/f/n are the Ruby objects themselves.
8
+ LOOKUP = {
9
+ :true => true,
10
+ :false => false,
11
+ :nil => nil,
12
+ }
13
+
14
+ KNOWNS = {
15
+ :/ => [nil, :/],
16
+ :"./" => [nil, :"./"],
17
+ :"rouge.core//" => [:"rouge.core", :/],
18
+ :"rouge.core/./" => [:"rouge.core", :"./"]
19
+ }
20
+
21
+ CACHE = {}
22
+
23
+ def initialize(sym)
24
+ if r = KNOWNS[sym]
25
+ @ns = r[0]
26
+ @name = r[1]
27
+ else
28
+ str = sym.to_s
29
+ solidus = str.rindex('/')
30
+ if solidus
31
+ @ns = str[0...solidus].intern
32
+ @name = str[solidus + 1..-1].intern
33
+ else
34
+ @ns = nil
35
+ @name = sym
36
+ end
37
+ end
38
+
39
+ @ns_s = @ns.to_s unless @ns.nil?
40
+ @name_s = @name.to_s
41
+
42
+ # split(sep, 0) means a trailing '.' won't become an empty component. (0
43
+ # is default) Contrast with split(sep, -1).
44
+ @name_parts =
45
+ @name_s.length > 1 ? @name_s.split('.', 0).map(&:intern) : [@name]
46
+
47
+ @new_sym = (@name_s[-1] == ?. and @name_s.length > 1)
48
+ end
49
+
50
+ def self.[](inner)
51
+ return LOOKUP[inner] if LOOKUP.include? inner
52
+ c = CACHE[inner]
53
+ return c.dup if c
54
+ # Note: don't cache symbols themselves, they may have metadata.
55
+ c = new inner
56
+ CACHE[inner] = c.dup.freeze
57
+ c
58
+ end
59
+
60
+ def to_sym
61
+ :"#{@ns ? "#@ns/" : ""}#@name"
62
+ end
63
+
64
+ def inspect
65
+ "Rouge::Symbol[#{to_sym.inspect}]"
66
+ end
67
+
68
+ def to_s; inspect; end
69
+
70
+ def ==(right)
71
+ right.is_a?(Rouge::Symbol) and right.ns == @ns and right.name == @name
72
+ end
73
+
74
+ attr_reader :ns, :name, :ns_s, :name_s, :name_parts, :new_sym
75
+ end
76
+
77
+ # vim: set sw=2 et cc=80:
data/lib/rouge/var.rb ADDED
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ class Rouge::Var
4
+ @@stack = []
5
+
6
+ def initialize(ns, name, root=Rouge::Var::UnboundSentinel)
7
+ @ns = ns
8
+ @name = name
9
+ raise ArgumentError, "bad var ns" unless ns.is_a? Symbol
10
+ raise ArgumentError, "bad var name" unless name.is_a? Symbol
11
+ if root == Rouge::Var::UnboundSentinel
12
+ @root = Rouge::Var::Unbound.new self
13
+ else
14
+ @root = root
15
+ end
16
+ end
17
+
18
+ def ==(var)
19
+ var.is_a?(Rouge::Var) and @ns == var.ns and @name == var.name
20
+ end
21
+
22
+ attr_reader :ns, :name
23
+
24
+ def deref
25
+ @@stack.reverse_each do |map|
26
+ if map.include? @name
27
+ return map[@name]
28
+ end
29
+ end
30
+
31
+ @root
32
+ end
33
+
34
+ def inspect
35
+ "Rouge::Var.new(#{@ns.inspect}, #{@name.inspect}, #{@root.inspect})"
36
+ end
37
+
38
+ def to_s
39
+ inspect
40
+ end
41
+
42
+ def self.push(map)
43
+ @@stack << map
44
+ end
45
+
46
+ def self.pop
47
+ @@stack.pop
48
+ end
49
+ end
50
+
51
+ Rouge::Var::UnboundSentinel = Object.new
52
+ class << Rouge::Var::UnboundSentinel
53
+ def inspect; "#<Rouge::Var::UnboundSentinel>"; end
54
+ def to_s; inspect; end
55
+ end
56
+
57
+ class Rouge::Var::Unbound
58
+ def initialize(var)
59
+ @var = var
60
+ end
61
+
62
+ def ==(ub)
63
+ @var == ub.var
64
+ end
65
+
66
+ attr_reader :var
67
+ end
68
+
69
+ # vim: set sw=2 et cc=80: