Use model patterns for defclass
This commit is contained in:
parent
9368e4bc4e
commit
3ebff987e0
@ -6,7 +6,7 @@
|
|||||||
from hy.models import (HyObject, HyExpression, HyKeyword, HyInteger, HyComplex,
|
from hy.models import (HyObject, HyExpression, HyKeyword, HyInteger, HyComplex,
|
||||||
HyString, HyBytes, HySymbol, HyFloat, HyList, HySet,
|
HyString, HyBytes, HySymbol, HyFloat, HyList, HySet,
|
||||||
HyDict, HySequence, wrap_value)
|
HyDict, HySequence, wrap_value)
|
||||||
from hy.model_patterns import FORM, SYM, sym, brackets, whole, notpexpr, dolike, pexpr
|
from hy.model_patterns import FORM, SYM, STR, sym, brackets, whole, notpexpr, dolike, pexpr
|
||||||
from funcparserlib.parser import many, oneplus, maybe, NoParseError
|
from funcparserlib.parser import many, oneplus, maybe, NoParseError
|
||||||
from hy.errors import HyCompileError, HyTypeError
|
from hy.errors import HyCompileError, HyTypeError
|
||||||
|
|
||||||
@ -1812,79 +1812,61 @@ class HyASTCompiler(object):
|
|||||||
ret += self.compile(expr[1])
|
ret += self.compile(expr[1])
|
||||||
return ret + asty.Return(expr, value=ret.force_expr)
|
return ret + asty.Return(expr, value=ret.force_expr)
|
||||||
|
|
||||||
@builds("defclass")
|
@special("defclass", [
|
||||||
@checkargs(min=1)
|
SYM,
|
||||||
def compile_class_expression(self, expressions):
|
maybe(brackets(many(FORM)) + maybe(STR) +
|
||||||
def rewire_init(expr):
|
maybe(brackets(many(SYM + FORM))) + many(FORM))])
|
||||||
new_args = []
|
def compile_class_expression(self, expr, root, name, rest):
|
||||||
if (isinstance(expr, HyExpression)
|
base_list, docstring, attrs, body = rest or ([[]], None, None, [])
|
||||||
and len(expr) > 1
|
|
||||||
and isinstance(expr[0], HySymbol)
|
|
||||||
and expr[0] == HySymbol("setv")):
|
|
||||||
pairs = expr[1:]
|
|
||||||
while len(pairs) > 0:
|
|
||||||
k, v = (pairs.pop(0), pairs.pop(0))
|
|
||||||
if ast_str(k) == "__init__":
|
|
||||||
v.append(HySymbol("None"))
|
|
||||||
new_args.append(k)
|
|
||||||
new_args.append(v)
|
|
||||||
expr = HyExpression([
|
|
||||||
HySymbol("setv")
|
|
||||||
] + new_args).replace(expr)
|
|
||||||
|
|
||||||
return expr
|
bases_expr, bases, keywords = (
|
||||||
|
self._compile_collect(base_list[0], with_kwargs=PY3))
|
||||||
|
|
||||||
expressions.pop(0) # class
|
bodyr = Result()
|
||||||
|
|
||||||
class_name = expressions.pop(0)
|
if docstring is not None:
|
||||||
if not isinstance(class_name, HySymbol):
|
|
||||||
raise HyTypeError(class_name, "Class name must be a symbol.")
|
|
||||||
|
|
||||||
bases_expr = []
|
|
||||||
bases = Result()
|
|
||||||
keywords = []
|
|
||||||
if expressions:
|
|
||||||
base_list = expressions.pop(0)
|
|
||||||
if not isinstance(base_list, HyList):
|
|
||||||
raise HyTypeError(base_list, "Base classes must be a list.")
|
|
||||||
bases_expr, bases, keywords = self._compile_collect(base_list, with_kwargs=PY3)
|
|
||||||
|
|
||||||
body = Result()
|
|
||||||
|
|
||||||
# grab the doc string, if there is one
|
|
||||||
docstring = None
|
|
||||||
if expressions and isinstance(expressions[0], HyString):
|
|
||||||
docstring = expressions.pop(0)
|
|
||||||
if not PY37:
|
if not PY37:
|
||||||
body += self.compile(docstring).expr_as_stmt()
|
bodyr += self.compile(docstring).expr_as_stmt()
|
||||||
docstring = None
|
docstring = None
|
||||||
|
|
||||||
if expressions and isinstance(expressions[0], HyList) \
|
if attrs is not None:
|
||||||
and not isinstance(expressions[0], HyExpression):
|
bodyr += self.compile(self._rewire_init(HyExpression(
|
||||||
expr = expressions.pop(0)
|
[HySymbol("setv")] +
|
||||||
expr = HyExpression([
|
[x for pair in attrs[0] for x in pair]).replace(attrs)))
|
||||||
HySymbol("setv")
|
|
||||||
] + expr).replace(expr)
|
|
||||||
body += self.compile(rewire_init(expr))
|
|
||||||
|
|
||||||
for expression in expressions:
|
for e in body:
|
||||||
e = self.compile(rewire_init(macroexpand(expression, self)))
|
e = self.compile(self._rewire_init(macroexpand(e, self)))
|
||||||
body += e + e.expr_as_stmt()
|
bodyr += e + e.expr_as_stmt()
|
||||||
|
|
||||||
if not body.stmts:
|
|
||||||
body += asty.Pass(expressions)
|
|
||||||
|
|
||||||
return bases + asty.ClassDef(
|
return bases + asty.ClassDef(
|
||||||
expressions,
|
expr,
|
||||||
decorator_list=[],
|
decorator_list=[],
|
||||||
name=ast_str(class_name),
|
name=ast_str(name),
|
||||||
keywords=keywords,
|
keywords=keywords,
|
||||||
starargs=None,
|
starargs=None,
|
||||||
kwargs=None,
|
kwargs=None,
|
||||||
bases=bases_expr,
|
bases=bases_expr,
|
||||||
body=body.stmts,
|
body=bodyr.stmts or [asty.Pass(expr)],
|
||||||
docstring=(None if docstring is None else str_type(docstring)))
|
docstring=(None if docstring is None else str_type(docstring)))
|
||||||
|
|
||||||
|
def _rewire_init(self, expr):
|
||||||
|
"Given a (setv …) form, append None to definitions of __init__."
|
||||||
|
|
||||||
|
if not (isinstance(expr, HyExpression)
|
||||||
|
and len(expr) > 1
|
||||||
|
and isinstance(expr[0], HySymbol)
|
||||||
|
and expr[0] == HySymbol("setv")):
|
||||||
|
return expr
|
||||||
|
|
||||||
|
new_args = []
|
||||||
|
pairs = list(expr[1:])
|
||||||
|
while pairs:
|
||||||
|
k, v = (pairs.pop(0), pairs.pop(0))
|
||||||
|
if ast_str(k) == "__init__" and isinstance(v, HyExpression):
|
||||||
|
v += HyExpression([HySymbol("None")])
|
||||||
|
new_args.extend([k, v])
|
||||||
|
return HyExpression([HySymbol("setv")] + new_args).replace(expr)
|
||||||
|
|
||||||
@builds("dispatch-tag-macro")
|
@builds("dispatch-tag-macro")
|
||||||
@checkargs(exact=2)
|
@checkargs(exact=2)
|
||||||
def compile_dispatch_tag_macro(self, expression):
|
def compile_dispatch_tag_macro(self, expression):
|
||||||
|
Loading…
Reference in New Issue
Block a user