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.
@@ -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: