rouge-lang 0.0.1

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