Use model patterns for the remaining special forms

This commit is contained in:
Kodi Arfer 2018-04-21 15:13:15 -07:00
parent 8b2733e921
commit a933646bdd

View File

@ -921,25 +921,16 @@ class HyASTCompiler(object):
return ret return ret
@builds("break") @special(["break", "continue"], [])
@checkargs(0) def compile_break_or_continue_expression(self, expr, root):
def compile_break_expression(self, expr): return (asty.Break if root == "break" else asty.Continue)(expr)
return asty.Break(expr)
@builds("continue") @special("assert", [FORM, maybe(FORM)])
@checkargs(0) def compile_assert_expression(self, expr, root, test, msg):
def compile_continue_expression(self, expr): ret = self.compile(test)
return asty.Continue(expr)
@builds("assert")
@checkargs(min=1, max=2)
def compile_assert_expression(self, expr):
expr.pop(0) # assert
ret = self.compile(expr.pop(0))
e = ret.force_expr e = ret.force_expr
msg = None if msg is not None:
if expr: msg = self.compile(msg).force_expr
msg = self.compile(expr.pop(0)).force_expr
return ret + asty.Assert(expr, test=e, msg=msg) return ret + asty.Assert(expr, test=e, msg=msg)
@special(["global", (PY3, "nonlocal")], [oneplus(SYM)]) @special(["global", (PY3, "nonlocal")], [oneplus(SYM)])
@ -947,20 +938,17 @@ class HyASTCompiler(object):
node = asty.Global if root == "global" else asty.Nonlocal node = asty.Global if root == "global" else asty.Nonlocal
return node(expr, names=list(map(ast_str, syms))) return node(expr, names=list(map(ast_str, syms)))
@builds("yield") @special("yield", [maybe(FORM)])
@checkargs(max=1) def compile_yield_expression(self, expr, root, arg):
def compile_yield_expression(self, expr):
ret = Result(contains_yield=(not PY3)) ret = Result(contains_yield=(not PY3))
if len(expr) > 1: if arg is not None:
ret += self.compile(expr[1]) ret += self.compile(arg)
return ret + asty.Yield(expr, value=ret.force_expr) return ret + asty.Yield(expr, value=ret.force_expr)
@builds("yield-from", iff=PY3) @special([(PY3, "yield-from"), (PY35, "await")], [FORM])
@builds("await", iff=PY35) def compile_yield_from_or_await_expression(self, expr, root, arg):
@checkargs(1) ret = Result() + self.compile(arg)
def compile_yield_from_or_await_expression(self, expr): node = asty.YieldFrom if root == "yield-from" else asty.Await
ret = Result() + self.compile(expr[1])
node = asty.YieldFrom if expr[0] == "yield-from" else asty.Await
return ret + node(expr, value=ret.force_expr) return ret + node(expr, value=ret.force_expr)
@special("get", [FORM, oneplus(FORM)]) @special("get", [FORM, oneplus(FORM)])
@ -1077,9 +1065,9 @@ class HyASTCompiler(object):
return ret return ret
@builds(",") @special(",", [many(FORM)])
def compile_tuple(self, expr): def compile_tuple(self, expr, root, args):
elts, ret, _ = self._compile_collect(expr[1:]) elts, ret, _ = self._compile_collect(args)
return ret + asty.Tuple(expr, elts=elts, ctx=ast.Load()) return ret + asty.Tuple(expr, elts=elts, ctx=ast.Load())
def _compile_generator_iterables(self, trailers): def _compile_generator_iterables(self, trailers):
@ -1343,33 +1331,15 @@ class HyASTCompiler(object):
return ret return ret
@builds("+=", "/=", "//=", "*=", "-=", "%=", "**=", "<<=", ">>=", "|=", a_ops = {x + "=": v for x, v in m_ops.items()}
"^=", "&=")
@builds("@=", iff=PY35)
@checkargs(2)
def compile_augassign_expression(self, expression):
ops = {"+=": ast.Add,
"/=": ast.Div,
"//=": ast.FloorDiv,
"*=": ast.Mult,
"-=": ast.Sub,
"%=": ast.Mod,
"**=": ast.Pow,
"<<=": ast.LShift,
">>=": ast.RShift,
"|=": ast.BitOr,
"^=": ast.BitXor,
"&=": ast.BitAnd}
if PY35:
ops.update({"@=": ast.MatMult})
op = ops[expression[0]]
target = self._storeize(expression[1], self.compile(expression[1]))
ret = self.compile(expression[2])
@special(list(a_ops.keys()), [FORM, FORM])
def compile_augassign_expression(self, expr, root, target, value):
op = self.a_ops[unmangle(ast_str(root))]
target = self._storeize(target, self.compile(target))
ret = self.compile(value)
return ret + asty.AugAssign( return ret + asty.AugAssign(
expression, target=target, value=ret.force_expr, op=op()) expr, target=target, value=ret.force_expr, op=op())
@checkargs(1) @checkargs(1)
def _compile_keyword_call(self, expression): def _compile_keyword_call(self, expression):
@ -1668,14 +1638,12 @@ class HyASTCompiler(object):
defaults.append(ret.force_expr) defaults.append(ret.force_expr)
return names, defaults, ret return names, defaults, ret
@builds("return") @special("return", [maybe(FORM)])
@checkargs(max=1) def compile_return(self, expr, root, arg):
def compile_return(self, expr):
ret = Result() ret = Result()
if len(expr) == 1: if arg is None:
return asty.Return(expr, value=None) return asty.Return(expr, value=None)
ret += self.compile(arg)
ret += self.compile(expr[1])
return ret + asty.Return(expr, value=ret.force_expr) return ret + asty.Return(expr, value=ret.force_expr)
@special("defclass", [ @special("defclass", [
@ -1733,29 +1701,21 @@ class HyASTCompiler(object):
new_args.extend([k, v]) new_args.extend([k, v])
return HyExpression([HySymbol("setv")] + new_args).replace(expr) return HyExpression([HySymbol("setv")] + new_args).replace(expr)
@builds("dispatch-tag-macro") @special("dispatch-tag-macro", [STR, FORM])
@checkargs(exact=2) def compile_dispatch_tag_macro(self, expr, root, tag, arg):
def compile_dispatch_tag_macro(self, expression): return self.compile(tag_macroexpand(
expression.pop(0) # dispatch-tag-macro HyString(mangle(tag)).replace(tag),
tag = expression.pop(0) arg,
if not type(tag) == HyString: self))
raise HyTypeError(
tag,
"Trying to expand a tag macro using `{0}' instead "
"of string".format(type(tag).__name__),
)
tag = HyString(mangle(tag)).replace(tag)
expr = tag_macroexpand(tag, expression.pop(0), self)
return self.compile(expr)
@builds("eval-and-compile", "eval-when-compile") @special(["eval-and-compile", "eval-when-compile"], [many(FORM)])
def compile_eval_and_compile(self, expression, building): def compile_eval_and_compile(self, expr, root, body):
expression[0] = HySymbol("do") new_expr = HyExpression([HySymbol("do").replace(root)]).replace(expr)
hy.importer.hy_eval(expression, hy.importer.hy_eval(new_expr + body,
compile_time_ns(self.module_name), compile_time_ns(self.module_name),
self.module_name) self.module_name)
return (self._compile_branch(expression[1:]) return (self._compile_branch(body)
if building == "eval_and_compile" if ast_str(root) == "eval_and_compile"
else Result()) else Result())
@builds(HyInteger, HyFloat, HyComplex) @builds(HyInteger, HyFloat, HyComplex)