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()
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__
imports = [name]
imports = set([name])
if isinstance(form, HyList):
contents = []
contents = HyList()
for x in form:
form_imports, form_contents = self._render_quoted_form(x)
imports += form_imports
contents.append(form_contents)
f_imports, f_contents, splice = self._render_quoted_form(x,
level)
imports.update(f_imports)
if splice:
contents = HyExpression([HySymbol('+'),
contents,
f_contents])
else:
contents.append(f_contents)
return imports, HyExpression(
[HySymbol(name),
HyList(contents)]
).replace(form)
contents]
).replace(form), False
elif isinstance(form, HySymbol):
return imports, HyExpression([HySymbol(name),
HyString(form)]).replace(form)
return imports, HyExpression([HySymbol(name), form]).replace(form)
HyString(form)]).replace(form), False
return imports, HyExpression([HySymbol(name),
form]).replace(form), False
@builds("quote")
@checkargs(exact=1)
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.add_imports("hy", imports)
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")
@checkargs(exact=1)
def compile_eval(self, expr):