Class: Kapusta::Compiler::MacroExpander::Lowering
- Inherits:
-
Object
- Object
- Kapusta::Compiler::MacroExpander::Lowering
- Defined in:
- lib/kapusta/compiler/macro_expander.rb
Instance Method Summary collapse
- #collected_gensyms ⇒ Object
- #copy_position(target, source) ⇒ Object
- #gensym_local_for(prefix) ⇒ Object
-
#initialize ⇒ Lowering
constructor
A new instance of Lowering.
- #lower(form) ⇒ Object
- #lower_quasi(form) ⇒ Object
- #lower_quasi_hash(hash) ⇒ Object
- #lower_quasi_item(item) ⇒ Object
- #lower_quasi_list(list) ⇒ Object
- #lower_quasi_vec(vec) ⇒ Object
- #splice_tail(items) ⇒ Object
- #unpack_call?(form) ⇒ Boolean
Constructor Details
#initialize ⇒ Lowering
Returns a new instance of Lowering.
169 170 171 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 169 def initialize @gensyms = {} end |
Instance Method Details
#collected_gensyms ⇒ Object
173 174 175 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 173 def collected_gensyms @gensyms.map { |prefix, sym| [sym, prefix] } end |
#copy_position(target, source) ⇒ Object
198 199 200 201 202 203 204 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 198 def copy_position(target, source) return target unless target.respond_to?(:line=) && source.respond_to?(:line) target.line ||= source.line target.column ||= source.column target end |
#gensym_local_for(prefix) ⇒ Object
280 281 282 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 280 def gensym_local_for(prefix) @gensyms[prefix] ||= MacroExpander.fresh_local_gensym(prefix) end |
#lower(form) ⇒ Object
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 177 def lower(form) case form when Quasiquote then copy_position(lower_quasi(form.form), form) when Unquote, UnquoteSplice raise Error, Kapusta::Errors.format(:unquote_outside_quasiquote) when AutoGensym raise Error, Kapusta::Errors.format(:auto_gensym_outside_quasiquote, name: form.name) when List then copy_position(List.new(form.items.map { |item| lower(item) }), form) when Vec then copy_position(Vec.new(form.items.map { |item| lower(item) }), form) when HashLit copy_position( HashLit.new(form.entries.map do |entry| entry.is_a?(Array) ? [lower(entry[0]), lower(entry[1])] : entry end), form ) else form end end |
#lower_quasi(form) ⇒ Object
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 206 def lower_quasi(form) case form when AutoGensym then gensym_local_for(form.name) when Sym then List.new([Sym.new('quasi-sym'), form.name]) when List then lower_quasi_list(form) when Vec then lower_quasi_vec(form) when HashLit then lower_quasi_hash(form) when Unquote then lower(form.form) when UnquoteSplice raise Error, Kapusta::Errors.format(:unquote_splice_outside_list) when Quasiquote raise Error, Kapusta::Errors.format(:nested_quasiquote) else form end end |
#lower_quasi_hash(hash) ⇒ Object
247 248 249 250 251 252 253 254 255 256 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 247 def lower_quasi_hash(hash) parts = [] hash.entries.each do |entry| next unless entry.is_a?(Array) key, value = entry parts << lower_quasi(key) << lower_quasi(value) end List.new([Sym.new('quasi-hash'), *parts]) end |
#lower_quasi_item(item) ⇒ Object
258 259 260 261 262 263 264 265 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 258 def lower_quasi_item(item) if item.is_a?(Unquote) && unpack_call?(item.form) inner = lower(item.form.items[1]) List.new([Sym.new('.'), inner, 0]) else lower_quasi(item) end end |
#lower_quasi_list(list) ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 223 def lower_quasi_list(list) items = list.items return List.new([Sym.new('quasi-list')]) if items.empty? if (tail_expr = splice_tail(items)) head_items = items[0...-1].map { |item| lower_quasi(item) } return List.new([Sym.new('quasi-list-tail'), Vec.new(head_items), tail_expr]) end lowered_items = items.map { |item| lower_quasi_item(item) } List.new([Sym.new('quasi-list'), *lowered_items]) end |
#lower_quasi_vec(vec) ⇒ Object
236 237 238 239 240 241 242 243 244 245 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 236 def lower_quasi_vec(vec) items = vec.items if (tail_expr = splice_tail(items)) head_items = items[0...-1].map { |item| lower_quasi(item) } return List.new([Sym.new('quasi-vec-tail'), Vec.new(head_items), tail_expr]) end lowered_items = items.map { |item| lower_quasi_item(item) } List.new([Sym.new('quasi-vec'), *lowered_items]) end |
#splice_tail(items) ⇒ Object
267 268 269 270 271 272 273 274 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 267 def splice_tail(items) last = items.last return unless last return lower(last.form) if last.is_a?(UnquoteSplice) return lower(last.form.items[1]) if last.is_a?(Unquote) && unpack_call?(last.form) nil end |