Implement unquote and unquote-splicing
This commit is contained in:
parent
9811b7514e
commit
322a9992e5
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user