Path: blob/main/python/pylang/src/output/classes.py
1398 views
from __python__ import hash_literals12from ast_types import AST_Class, AST_Method, is_node_type3from output.functions import decorate, function_definition, function_annotation4from output.utils import create_doctring5from utils import has_prop678def print_class(output):9self = this10if self.external:11return1213def class_def(method, is_var):14output.indent()15self.name.print(output)16if not is_var and method and has_prop(self.static, method):17output.assign("." + method)18else:19if is_var:20output.assign(".prototype[" + method + "]")21else:22output.assign(".prototype" +23(("." + method) if method else ""))2425def define_method(stmt, is_property):26name = stmt.name.name27if not is_property:28class_def(name)29# only strip first argument if the method is static30is_static = has_prop(self.static, name)31strip_first = not is_static3233# decorate the method34if stmt.decorators and stmt.decorators.length:35decorate(36stmt.decorators, output,37lambda: function_definition(stmt, output, strip_first, True))38output.end_statement()39else:40function_definition(stmt, output, strip_first)41if not is_property:42output.end_statement()43fname = self.name.name + ('.' if is_static else44'.prototype.') + name45function_annotation(stmt, output, strip_first, fname)4647def define_default_method(name, body):48class_def(name)49output.spaced('function', name, '()', '')50output.with_block(lambda: [output.indent(), body()])51output.end_statement()5253def add_hidden_property(name, proceed):54output.indent(), output.print('Object.defineProperty(')55self.name.print(56output), output.print('.prototype'), output.comma(), output.print(57JSON.stringify(name)), output.comma()58output.spaced(59'{value:',60''), proceed(), output.print('})'), output.end_statement()6162# generate constructor63def write_constructor():64output.print("function")65output.space()66self.name.print(output)67output.print("()")68output.space()6970def f_constructor():71output.indent()72output.spaced('if', '(this.ρσ_object_id', '===', 'undefined)',73'Object.defineProperty(this,', '"ρσ_object_id",',74'{"value":++ρσ_object_counter})')75output.end_statement()76if self.bound.length:77output.indent()78self.name.print(output), output.print(79".prototype.__bind_methods__.call(this)")80output.end_statement()81output.indent()82self.name.print(output)83output.print(".prototype.__init__.apply(this"), output.comma(84), output.print('arguments)')85output.end_statement()8687output.with_block(f_constructor)8889decorators = self.decorators or []90if decorators.length:91output.print('var ')92output.assign(self.name)93write_constructor()94output.semicolon()95else:96write_constructor()97output.newline()98if decorators.length:99output.indent()100self.name.print(output)101output.spaced('.ρσ_decorators', '=', '[')102num = decorators.length103for i in range(num):104decorators[i].expression.print(output)105output.spaced(',' if i < num - 1 else ']')106output.semicolon()107output.newline()108109# inheritance110if self.parent:111output.indent()112output.print("ρσ_extends")113114def f_extends():115self.name.print(output)116output.comma()117self.parent.print(output)118119output.with_parens(f_extends)120output.end_statement()121122# method binding123if self.bound.length:124seen_methods = Object.create(None)125126def f_bind_methods():127output.spaced('function', '()', '')128129def f_bases():130if self.bases.length:131for i in range(self.bases.length - 1, -1, -1):132base = self.bases[i]133output.indent(), base.print(output), output.spaced(134'.prototype.__bind_methods__', '&&', '')135base.print(output), output.print(136'.prototype.__bind_methods__.call(this)')137output.end_statement()138for bname in self.bound:139if seen_methods[bname] or self.dynamic_properties[bname]:140continue141seen_methods[bname] = True142output.indent(), output.assign('this.' + bname)143self.name.print(output), output.print('.prototype.' +144bname +145'.bind(this)')146output.end_statement()147148output.with_block(f_bases)149150add_hidden_property('__bind_methods__', f_bind_methods)151152# dynamic properties153property_names = Object.keys(self.dynamic_properties)154if property_names.length:155output.indent()156output.print('Object.defineProperties')157158def f_props():159self.name.print(output)160output.print('.prototype')161output.comma()162output.space()163164def f_enum():165for name in property_names:166prop = self.dynamic_properties[name]167output.indent(), output.print(JSON.stringify(name) +168':'), output.space()169170def f_enum2():171output.indent(), output.print(172'"enumerable":'), output.space(), output.print(173'true'), output.comma(), output.newline()174if prop.getter:175output.indent(), output.print(176'"get":'), output.space()177define_method(178prop.getter,179True), output.comma(), output.newline()180output.indent(), output.print('"set":'), output.space()181if prop.setter:182define_method(prop.setter, True), output.newline()183else:184output.spaced(185'function', '()', '{',186'''throw new AttributeError("can't set attribute")''',187'}'), output.newline()188189output.with_block(f_enum2)190output.comma()191output.newline()192193output.with_block(f_enum)194195output.with_parens(f_props)196output.end_statement()197198# actual methods199if not self.init:200# Create a default __init__ method201def f_default():202if self.parent:203self.parent.print(output)204output.spaced('.prototype.__init__', '&&')205output.space(), self.parent.print(output)206output.print(".prototype.__init__.apply")207208def f_this_arguments():209output.print("this")210output.comma()211output.print("arguments")212213output.with_parens(f_this_arguments)214output.end_statement()215216define_default_method('__init__', f_default)217218defined_methods = {}219220for stmt in self.body:221if is_node_type(stmt, AST_Method):222if stmt.is_getter or stmt.is_setter:223continue224define_method(stmt)225defined_methods[stmt.name.name] = True226sname = stmt.name.name227if sname is '__init__':228# Copy argument handling data so that kwarg interpolation works when calling the constructor229for attr in [230'.__argnames__', '.__handles_kwarg_interpolation__'231]:232output.indent(), self.name.print(output), output.assign(233attr)234self.name.print(output), output.print(235'.prototype.__init__' + attr), output.end_statement()236if sname is '__iter__':237class_def('ρσ_iterator_symbol', True)238self.name.print(output)239output.print('.prototype.' + stmt.name.name)240output.end_statement()241242elif is_node_type(stmt, AST_Class):243console.error('Nested classes aren\'t supported yet') # noqa:undef244245if not defined_methods['__repr__']:246247def f_repr():248if self.parent:249output.print('if('), self.parent.print(output), output.spaced(250'.prototype.__repr__)', 'return', self.parent)251output.print(252'.prototype.__repr__.call(this)'), output.end_statement()253output.indent(), output.spaced('return', '"<"', '+', '__name__',254'+', '"."', '+',255'this.constructor.name', '')256output.spaced('+', '" #"', '+', 'this.ρσ_object_id', '+', '">"')257output.end_statement()258259define_default_method('__repr__', f_repr)260261if not defined_methods['__str__']:262263def f_str():264if self.parent:265output.print('if('), self.parent.print(output), output.spaced(266'.prototype.__str__)', 'return', self.parent)267output.print(268'.prototype.__str__.call(this)'), output.end_statement()269output.spaced('return', 'this.__repr__()')270output.end_statement()271272define_default_method('__str__', f_str)273274# Multiple inheritance275def f_basis():276output.print('[')277for i in range(len(self.bases)):278self.bases[i].print(output)279if i < self.bases.length - 1:280output.comma()281output.print(']')282283add_hidden_property('__bases__', f_basis)284285if self.bases.length > 1:286output.indent()287output.print("ρσ_mixin(")288self.name.print(output)289for i in range(1, len(self.bases)):290output.comma()291self.bases[i].print(output)292output.print(')'), output.end_statement()293294# Docstring295if self.docstrings and self.docstrings.length and output.options.keep_docstrings:296297def f_doc():298output.print(JSON.stringify(create_doctring(self.docstrings)))299300add_hidden_property('__doc__', f_doc)301302# Other statements in the class context303for stmt in self.statements:304if not is_node_type(stmt, AST_Method):305output.indent()306stmt.print(output)307output.newline()308309if decorators.length:310output.indent()311output.assign(self.name)312for di in range(decorators.length):313self.name.print(output)314output.print(f'.ρσ_decorators[{di}](')315self.name.print(output)316output.print(')' * decorators.length)317output.semicolon()318output.newline()319output.indent()320output.spaced('delete ')321self.name.print(output)322output.print('.ρσ_decorators')323output.semicolon()324output.newline()325326327