Implement unquote and unquote-splicing

This commit is contained in:
Nicolas Dandrimont 2013-05-10 23:11:31 +02:00
parent 9811b7514e
commit 322a9992e5

View File

@ -494,33 +494,75 @@ class HyASTCompiler(object):
ret += ret.expr_as_stmt() ret += ret.expr_as_stmt()
return ret return ret
def _render_quoted_form(self, form): def _render_quoted_form(self, form, level=0):
"""
Render a quoted form as a new HyExpression.
`level` is the level of quasiquoting of the current form. We can
unquote if level is 0.
Returns a three-tuple (`imports`, `expression`, `splice`).
The `splice` return value is used to mark `unquote-splice`d forms.
We need to distinguish them as want to concatenate them instead of
just nesting them.
"""
if level == 0:
if isinstance(form, HyExpression):
if form and form[0] in ("unquote", "unquote_splice"):
if len(form) != 2:
raise HyTypeError(form,
("`%s' needs 1 argument, got %s" %
form[0], len(form) - 1))
return set(), form[1], (form[0] == "unquote_splice")
if isinstance(form, HyExpression):
if form and form[0] == "quote":
level += 1
if form and form[0] in ("unquote", "unquote_splice"):
level -= 1
name = form.__class__.__name__ name = form.__class__.__name__
imports = [name] imports = set([name])
if isinstance(form, HyList): if isinstance(form, HyList):
contents = [] contents = HyList()
for x in form: for x in form:
form_imports, form_contents = self._render_quoted_form(x) f_imports, f_contents, splice = self._render_quoted_form(x,
imports += form_imports level)
contents.append(form_contents) imports.update(f_imports)
if splice:
contents = HyExpression([HySymbol('+'),
contents,
f_contents])
else:
contents.append(f_contents)
return imports, HyExpression( return imports, HyExpression(
[HySymbol(name), [HySymbol(name),
HyList(contents)] contents]
).replace(form) ).replace(form), False
elif isinstance(form, HySymbol): elif isinstance(form, HySymbol):
return imports, HyExpression([HySymbol(name), return imports, HyExpression([HySymbol(name),
HyString(form)]).replace(form) HyString(form)]).replace(form), False
return imports, HyExpression([HySymbol(name), form]).replace(form)
return imports, HyExpression([HySymbol(name),
form]).replace(form), False
@builds("quote") @builds("quote")
@checkargs(exact=1) @checkargs(exact=1)
def compile_quote(self, entries): def compile_quote(self, entries):
imports, stmts = self._render_quoted_form(entries[1]) imports, stmts, splice = self._render_quoted_form(entries[1])
ret = self.compile(stmts) ret = self.compile(stmts)
ret.add_imports("hy", imports) ret.add_imports("hy", imports)
return ret return ret
@builds("unquote")
@builds("unquote-splicing")
def compile_unquote(self, expr):
raise HyTypeError(expr,
"`%s' can't be used at the top-level" % expr[0])
@builds("eval") @builds("eval")
@checkargs(exact=1) @checkargs(exact=1)
def compile_eval(self, expr): def compile_eval(self, expr):