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
- #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.
150 151 152 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 150 def initialize @gensyms = {} end |
Instance Method Details
#collected_gensyms ⇒ Object
154 155 156 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 154 def collected_gensyms @gensyms.map { |prefix, sym| [sym, prefix] } end |
#gensym_local_for(prefix) ⇒ Object
250 251 252 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 250 def gensym_local_for(prefix) @gensyms[prefix] ||= MacroExpander.fresh_local_gensym(prefix) end |
#lower(form) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 158 def lower(form) case form when Quasiquote then lower_quasi(form.form) when Unquote, UnquoteSplice raise Error, 'unquote outside quasiquote' when AutoGensym raise Error, "auto-gensym #{form.name}# outside quasiquote" when List then List.new(form.items.map { |item| lower(item) }) when Vec then Vec.new(form.items.map { |item| lower(item) }) when HashLit HashLit.new(form.entries.map do |entry| entry.is_a?(Array) ? [lower(entry[0]), lower(entry[1])] : entry end) else form end end |
#lower_quasi(form) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 176 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, 'unquote-splice must appear inside a quoted list/vec' when Quasiquote raise Error, 'nested quasiquote is not supported' else form end end |
#lower_quasi_hash(hash) ⇒ Object
217 218 219 220 221 222 223 224 225 226 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 217 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
228 229 230 231 232 233 234 235 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 228 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
193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 193 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
206 207 208 209 210 211 212 213 214 215 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 206 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
237 238 239 240 241 242 243 244 |
# File 'lib/kapusta/compiler/macro_expander.rb', line 237 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 |