rouge-lang 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,108 @@
1
+ # encoding: utf-8
2
+ require 'set'
3
+
4
+ module Rouge::Compiler
5
+ class Resolved
6
+ def initialize(res)
7
+ @res = res
8
+ end
9
+
10
+ attr_reader :res
11
+ end
12
+
13
+ def self.compile(ns, lexicals, form)
14
+ case form
15
+ when Rouge::Symbol
16
+ name = form.name
17
+ is_new = (name[-1] == ?. and name.length > 1)
18
+ name = name[0..-2].to_sym if is_new
19
+
20
+ if !form.ns and
21
+ (lexicals.include?(name) or
22
+ (name[0] == ?. and name.length > 1) or
23
+ [:|, :&].include?(name))
24
+ # TODO: cache found ns/var/context or no. of context parents.
25
+ form
26
+ else
27
+ resolved = form.ns ? Rouge[form.ns] : ns
28
+
29
+ lookups = form.name_parts
30
+ resolved = resolved[lookups[0]]
31
+ i, count = 1, lookups.length
32
+
33
+ while i < count
34
+ resolved = resolved.deref if resolved.is_a?(Rouge::Var)
35
+ resolved = resolved.const_get(lookups[i])
36
+ i += 1
37
+ end
38
+
39
+ if is_new
40
+ klass = resolved
41
+ klass = klass.deref if klass.is_a?(Rouge::Var)
42
+ resolved = klass.method(:new)
43
+ end
44
+
45
+ Resolved.new resolved
46
+ end
47
+ when Array
48
+ form.map {|f| compile(ns, lexicals, f)}
49
+ when Hash
50
+ Hash[form.map {|k, v| [compile(ns, lexicals, k),
51
+ compile(ns, lexicals, v)]}]
52
+ when Rouge::Seq::ISeq
53
+ to_a = form.to_a
54
+ if to_a.empty?
55
+ return Rouge::Seq::Empty
56
+ end
57
+
58
+ head, *tail = to_a
59
+
60
+ if head.is_a?(Rouge::Symbol) and
61
+ (head.ns.nil? or head.ns == :"rouge.builtin") and
62
+ Rouge::Builtins.respond_to?("_compile_#{head.name}")
63
+ Rouge::Seq::Cons[*
64
+ Rouge::Builtins.send(
65
+ "_compile_#{head.name}",
66
+ ns, lexicals, *tail)]
67
+ else
68
+ head = compile(ns, lexicals, head)
69
+
70
+ # XXX ↓↓↓ This is insane ↓↓↓
71
+ if head.is_a?(Resolved) and
72
+ head.res.is_a?(Rouge::Var) and
73
+ head.res.deref.is_a?(Rouge::Macro)
74
+ # TODO: backtrace_fix
75
+ compile(ns, lexicals, head.res.deref.inner.call(*tail))
76
+ else
77
+ # Regular function call!
78
+ if tail.include? Rouge::Symbol[:|]
79
+ index = tail.index Rouge::Symbol[:|]
80
+ if tail.length == index + 2
81
+ # Function.
82
+ block = compile(ns, lexicals, tail[index + 1])
83
+ else
84
+ # Inline block.
85
+ block = compile(
86
+ ns, lexicals,
87
+ Rouge::Seq::Cons[Rouge::Symbol[:fn],
88
+ *tail[index + 1..-1]])
89
+ end
90
+ tail = tail[0...index]
91
+ else
92
+ block = nil
93
+ end
94
+ Rouge::Seq::Cons[
95
+ head,
96
+ *tail.map {|f| compile(ns, lexicals, f)},
97
+ *(block ? [Rouge::Symbol[:|],
98
+ block]
99
+ : [])]
100
+ end
101
+ end
102
+ else
103
+ form
104
+ end
105
+ end
106
+ end
107
+
108
+ # vim: set sw=2 et cc=80:
@@ -0,0 +1,235 @@
1
+ # encoding: utf-8
2
+ require 'rouge/wrappers'
3
+ require 'rouge/namespace'
4
+
5
+ class Rouge::Context
6
+ class BindingNotFoundError < StandardError; end
7
+ class BadBindingError < StandardError; end
8
+ class ChangeContextException < Exception
9
+ def initialize(context); @context = context; end
10
+ attr_reader :context
11
+ end
12
+
13
+ def initialize(parent_or_ns)
14
+ case parent_or_ns
15
+ when Rouge::Namespace
16
+ @ns = parent_or_ns
17
+ when Rouge::Context
18
+ @parent = parent_or_ns
19
+ @ns = @parent.ns
20
+ end
21
+ @table = {}
22
+ end
23
+
24
+ def [](key)
25
+ if @table.include? key
26
+ @table[key]
27
+ elsif @parent
28
+ @parent[key]
29
+ elsif @ns
30
+ @ns[key]
31
+ else
32
+ raise BindingNotFoundError, key
33
+ end
34
+ end
35
+
36
+ def set_here(key, value)
37
+ if Rouge::Symbol[key].ns != nil
38
+ raise BadBindingError, "cannot bind #{key.inspect}"
39
+ end
40
+
41
+ @table[key] = value
42
+ end
43
+
44
+ def set_lexical(key, value)
45
+ if @table.include? key
46
+ @table[key] = value
47
+ elsif @parent
48
+ @parent.set_lexical key, value
49
+ else
50
+ raise BindingNotFoundError,
51
+ "setting #{key} to #{value.inspect}"
52
+ end
53
+ end
54
+
55
+ def lexical_keys
56
+ @table.keys + (@parent ? @parent.lexical_keys : [])
57
+ end
58
+
59
+ # This readeval post-processes the backtrace. Accordingly, it should only
60
+ # be called by consumers, and never by Rouge internally itself, lest it
61
+ # catches an exception and processes the backtrace too early.
62
+ def readeval(input)
63
+ reader = Rouge::Reader.new(ns, input)
64
+ context = self
65
+ r = nil
66
+
67
+ while true
68
+ begin
69
+ form = reader.lex
70
+ rescue Rouge::Reader::EndOfDataError
71
+ return r
72
+ end
73
+
74
+ form = Rouge::Compiler.compile(context.ns, Set[*lexical_keys], form)
75
+
76
+ begin
77
+ r = context.eval(form)
78
+ rescue ChangeContextException => cce
79
+ context = cce.context
80
+ reader.ns = context.ns
81
+ end
82
+ end
83
+ rescue Exception => e
84
+ # Remove Rouge-related lines unless the exception originated in Rouge.
85
+ # root = File.dirname(File.dirname(__FILE__))
86
+ # e.backtrace.map! {|line|
87
+ # line.scan(root).length > 0 ? nil : line
88
+ # }.compact! unless e.backtrace[0].scan(root).length > 0
89
+ raise e
90
+ end
91
+
92
+ # Internal use only -- doesn't post-process backtrace.
93
+ def eval(form)
94
+ case form
95
+ when Rouge::Compiler::Resolved
96
+ result = form.res
97
+ if result.is_a?(Rouge::Var)
98
+ result.deref
99
+ else
100
+ result
101
+ end
102
+ when Rouge::Symbol
103
+ eval_symbol form
104
+ when Rouge::Seq::Cons
105
+ eval_cons form
106
+ when Hash
107
+ Hash[form.map {|k,v| [eval(k), eval(v)]}].freeze
108
+ when Array
109
+ form.map {|f| eval(f)}.freeze
110
+ else
111
+ form
112
+ end
113
+ end
114
+
115
+ # +symbol+ should be a Rouge::Symbol.
116
+ def locate(symbol)
117
+ if !symbol.is_a?(Rouge::Symbol)
118
+ raise ArgumentError, "locate not called with R::S"
119
+ elsif symbol.ns
120
+ raise ArgumentError, "locate called with NS'd R::S #{symbol}"
121
+ end
122
+
123
+ if symbol.name_s[-1] == ?. and symbol.name_s.length > 1
124
+ lambda {|*args, &block|
125
+ self[symbol.name_s[0..-2].intern].new(*args, &block)
126
+ }
127
+ else
128
+ self[symbol.name]
129
+ end
130
+ end
131
+
132
+ attr_reader :ns
133
+
134
+ private
135
+
136
+ def eval_symbol(form)
137
+ if !form.ns and form.name_s[0] == ?. and form.name_s.length > 1
138
+ lambda {|receiver, *args, &block|
139
+ receiver.send(form.name_s[1..-1], *args, &block)
140
+ }
141
+ else
142
+ result = locate form
143
+ if result.is_a?(Rouge::Var)
144
+ result.deref
145
+ else
146
+ result
147
+ end
148
+ end
149
+ end
150
+
151
+ def eval_cons(form)
152
+ fun = eval form[0]
153
+
154
+ case fun
155
+ when Rouge::Builtin
156
+ backtrace_fix("(rouge):?:builtin: ", form) do
157
+ fun.inner.call self, *form.to_a[1..-1]
158
+ end
159
+ else
160
+ args = form.to_a[1..-1]
161
+
162
+ if args.include? Rouge::Symbol[:|]
163
+ index = args.index Rouge::Symbol[:|]
164
+ if args.length == index + 2
165
+ # Function.
166
+ block = eval args[index + 1]
167
+ else
168
+ # Inline block.
169
+ block = eval(Rouge::Seq::Cons[
170
+ Rouge::Symbol[:fn],
171
+ args[index + 1],
172
+ *args[index + 2..-1]
173
+ ])
174
+ end
175
+ args = args[0...index]
176
+ else
177
+ block = nil
178
+ end
179
+
180
+ args = args.map {|f| eval(f)}
181
+
182
+ backtrace_fix("(rouge):?:lambda: ", form) do
183
+ eval_call(fun, args, block)
184
+ end
185
+ end
186
+ end
187
+
188
+ def eval_call(fun, args, block)
189
+ num_args = args.length
190
+ case fun
191
+ when Symbol
192
+ if num_args == 1 || num_args == 2
193
+ default = args[1]
194
+ if args[0].is_a? Hash
195
+ args[0].fetch(fun) { default }
196
+ else
197
+ default
198
+ end
199
+ else
200
+ raise ArgumentError,
201
+ "Wrong number of args (#{num_args}) passed to ruby/Symbol :#{fun}"
202
+ end
203
+ when Hash
204
+ if num_args == 1 || num_args == 2
205
+ default = args[1]
206
+ fun.fetch(args[0]) { default }
207
+ else
208
+ raise ArgumentError,
209
+ "Wrong number of args (#{num_args}) passed to ruby/Hash"
210
+ end
211
+ else
212
+ fun.call(*args, &block)
213
+ end
214
+ end
215
+
216
+ def backtrace_fix(name, form, &block)
217
+ begin
218
+ block.call
219
+ rescue Exception => e
220
+ # target = block.source_location.join(':')
221
+ # changed = 0
222
+ # $!.backtrace.map! {|line|
223
+ # if line.scan("#{target}:").size > 0 and changed == 0
224
+ # changed += 1
225
+ # Rouge.print(form, name.dup)
226
+ # else
227
+ # line
228
+ # end
229
+ # }
230
+ raise e
231
+ end
232
+ end
233
+ end
234
+
235
+ # vim: set sw=2 et cc=80:
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module Rouge::Metadata
4
+ class InvalidMetadataError < StandardError; end
5
+
6
+ def meta
7
+ @meta
8
+ end
9
+
10
+ def meta= m
11
+ if m != nil and m.class != Hash
12
+ raise InvalidMetadataError, "bad metadata: #{m.inspect}"
13
+ end
14
+
15
+ @meta = m
16
+ end
17
+ end
18
+
19
+ # vim: set sw=2 et cc=80:
@@ -0,0 +1,125 @@
1
+ # encoding: utf-8
2
+ require 'rouge/context'
3
+ require 'rouge/builtins'
4
+ require 'rouge/var'
5
+ require 'rouge/atom'
6
+
7
+ class Rouge::Namespace
8
+ @namespaces = {}
9
+
10
+ class VarNotFoundError < StandardError; end
11
+ class RecursiveNamespaceError < StandardError; end
12
+
13
+ def initialize(name)
14
+ @name = name
15
+ raise ArgumentError, "bad ns name" unless @name.is_a? Symbol
16
+ @table = {}
17
+ @refers = []
18
+ end
19
+
20
+ def inspect
21
+ "#<Rouge::NS #{@name.inspect}, " \
22
+ "refers #{@refers.map(&:inspect).join(", ")}>"
23
+ end
24
+
25
+ def refer(ns)
26
+ if ns.name == @name
27
+ raise RecursiveNamespaceError, "#@name will not refer #{ns.name}"
28
+ end
29
+
30
+ @refers << ns if not @refers.include? ns
31
+ end
32
+
33
+ def [](key)
34
+ if @table.include? key
35
+ return @table[key]
36
+ end
37
+
38
+ @refers.each do |ns|
39
+ begin
40
+ return ns[key]
41
+ rescue VarNotFoundError
42
+ # no-op
43
+ end
44
+ end
45
+
46
+ raise VarNotFoundError, key
47
+ end
48
+
49
+ def set_here(key, value)
50
+ @table[key] = Rouge::Var.new(@name, key, value)
51
+ end
52
+
53
+ def intern(key)
54
+ @table[key] ||= Rouge::Var.new(@name, key)
55
+ end
56
+
57
+ def read(input)
58
+ Rouge::Reader.new(self, input).lex
59
+ end
60
+
61
+ def clear
62
+ @table = {}
63
+ self
64
+ end
65
+
66
+ attr_reader :name, :refers
67
+ end
68
+
69
+ class << Rouge::Namespace
70
+ def exists?(ns)
71
+ @namespaces.include? ns
72
+ end
73
+
74
+ def [](ns)
75
+ r = @namespaces[ns]
76
+ return r if r
77
+
78
+ self[ns] = new(ns)
79
+ @namespaces[ns] = new(ns)
80
+ end
81
+
82
+ def []=(ns, value)
83
+ @namespaces[ns] = value
84
+ end
85
+
86
+ def destroy(ns)
87
+ @namespaces.delete ns
88
+ end
89
+ end
90
+
91
+ class Rouge::Namespace::Ruby
92
+ @@cache = {}
93
+
94
+ def [](name)
95
+ return @@cache[name] if @@cache.include? name
96
+ if name =~ /^\$/
97
+ @@cache[name] = Rouge::Var.new(:ruby, name, eval(name.to_s))
98
+ else
99
+ @@cache[name] = Rouge::Var.new(:ruby, name, Kernel.const_get(name))
100
+ end
101
+ rescue NameError
102
+ raise Rouge::Namespace::VarNotFoundError, name
103
+ end
104
+
105
+ def set_here(name, value)
106
+ @@cache[name] = Rouge::Var.new(:ruby, name, value)
107
+ Kernel.const_set name, value
108
+ end
109
+
110
+ def name
111
+ :ruby
112
+ end
113
+ end
114
+
115
+ ns = Rouge::Namespace[:"rouge.builtin"]
116
+ Rouge::Builtins.methods(false).reject {|s| s =~ /^_compile_/}.each do |m|
117
+ ns.set_here m, Rouge::Builtin[Rouge::Builtins.method(m)]
118
+ end
119
+ Rouge::Builtins::SYMBOLS.each do |name, val|
120
+ ns.set_here name, val
121
+ end
122
+
123
+ Rouge::Namespace[:ruby] = Rouge::Namespace::Ruby.new
124
+
125
+ # vim: set sw=2 et cc=80: