<s> """<STR_LIT>""" <EOL> __all__ = [ <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' <EOL> ] <EOL> import re <EOL> from . . import util <EOL> from . import lexer <EOL> from . import parser <EOL> PICO8_LUA_CHAR_LIMIT = <NUM_LIT> <EOL> PICO8_LUA_TOKEN_LIMIT = <NUM_LIT> <EOL> PICO8_LUA_COMPRESSED_CHAR_LIMIT = <NUM_LIT> <EOL> PICO8_BUILTINS = { <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:info>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:all>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT:count>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> } <EOL> class Lua ( ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , version ) : <EOL> """<STR_LIT>""" <EOL> self . _version = version <EOL> self . _lexer = lexer . Lexer ( version = version ) <EOL> self . _parser = parser . Parser ( version = version ) <EOL> def get_char_count ( self ) : <EOL> return sum ( len ( l ) for l in self . to_lines ( ) ) <EOL> def get_token_count ( self ) : <EOL> c = <NUM_LIT:0> <EOL> for t in self . _lexer . _tokens : <EOL> if t . matches ( lexer . TokSymbol ( '<STR_LIT>' ) ) : <EOL> c += <NUM_LIT:3> <EOL> elif t . matches ( lexer . TokSymbol ( '<STR_LIT:..>' ) ) : <EOL> c += <NUM_LIT:2> <EOL> elif t . matches ( lexer . TokSymbol ( '<STR_LIT::>' ) ) : <EOL> pass <EOL> elif t . matches ( lexer . TokNumber ) and t . _data . find ( '<STR_LIT:e>' ) != - <NUM_LIT:1> : <EOL> c += <NUM_LIT:2> <EOL> elif ( not isinstance ( t , lexer . TokSpace ) and <EOL> not isinstance ( t , lexer . TokNewline ) and <EOL> not isinstance ( t , lexer . TokComment ) ) : <EOL> c += <NUM_LIT:1> <EOL> if c == <NUM_LIT:0> : <EOL> c = <NUM_LIT:1> <EOL> return c <EOL> def get_line_count ( self ) : <EOL> c = <NUM_LIT:0> <EOL> for t in self . _lexer . _tokens : <EOL> if isinstance ( t , lexer . TokNewline ) : <EOL> c += <NUM_LIT:1> <EOL> return c <EOL> def get_title ( self ) : <EOL> if len ( self . _lexer . tokens ) < <NUM_LIT:1> : <EOL> return None <EOL> title_tok = self . _lexer . tokens [ <NUM_LIT:0> ] <EOL> if not isinstance ( title_tok , lexer . TokComment ) : <EOL> return None <EOL> return title_tok . value [ <NUM_LIT:2> : ] . strip ( ) <EOL> def get_byline ( self ) : <EOL> if len ( self . _lexer . tokens ) < <NUM_LIT:3> : <EOL> return None <EOL> title_tok = self . _lexer . tokens [ <NUM_LIT:2> ] <EOL> if not isinstance ( title_tok , lexer . TokComment ) : <EOL> return None <EOL> return title_tok . value [ <NUM_LIT:2> : ] . strip ( ) <EOL> @ property <EOL> def tokens ( self ) : <EOL> return self . _lexer . tokens <EOL> @ property <EOL> def root ( self ) : <EOL> return self . _parser . root <EOL> @ property <EOL> def version ( self ) : <EOL> return self . _version <EOL> @ classmethod <EOL> def from_lines ( cls , lines , version ) : <EOL> """<STR_LIT>""" <EOL> result = Lua ( version ) <EOL> result . update_from_lines ( lines ) <EOL> return result <EOL> def update_from_lines ( self , lines ) : <EOL> """<STR_LIT>""" <EOL> self . _lexer . process_lines ( lines ) <EOL> self . _parser . process_tokens ( self . _lexer . tokens ) <EOL> def to_lines ( self , writer_cls = None , writer_args = None ) : <EOL> """<STR_LIT>""" <EOL> if writer_cls is None : <EOL> writer_cls = LuaEchoWriter <EOL> writer = writer_cls ( tokens = self . _lexer . tokens , root = self . _parser . root , <EOL> args = writer_args ) <EOL> for line in writer . to_lines ( ) : <EOL> yield line <EOL> def reparse ( self , writer_cls = None , writer_args = None ) : <EOL> """<STR_LIT>""" <EOL> new_lua = Lua . from_lines ( <EOL> self . to_lines ( writer_cls = writer_cls , <EOL> writer_args = writer_args ) , <EOL> version = self . version ) <EOL> self . _lexer = new_lua . _lexer <EOL> self . _parser = new_lua . _parser <EOL> class BaseASTWalker ( ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , tokens , root , args = None ) : <EOL> """<STR_LIT>""" <EOL> self . _tokens = tokens <EOL> self . _root = root <EOL> self . _args = args or { } <EOL> def _walk_token ( self , token ) : <EOL> """<STR_LIT>""" <EOL> if False : <EOL> yield <EOL> def _walk_value ( self , value ) : <EOL> """<STR_LIT>""" <EOL> if False : <EOL> yield <EOL> def _walk ( self , node ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( node , parser . Node ) : <EOL> result = getattr ( self , '<STR_LIT>' + node . __class__ . __name__ ) ( node ) <EOL> if result is not None : <EOL> for t in result : <EOL> yield t <EOL> elif isinstance ( node , lexer . Token ) : <EOL> for t in self . _walk_token ( node ) : <EOL> yield t <EOL> elif hasattr ( node , '<STR_LIT>' ) and type ( node ) != str : <EOL> for item in node : <EOL> for t in self . _walk ( item ) : <EOL> yield t <EOL> else : <EOL> for t in self . _walk_value ( node ) : <EOL> yield t <EOL> def walk ( self ) : <EOL> """<STR_LIT>""" <EOL> for t in self . _walk ( self . _root ) : <EOL> yield t <EOL> def _default_node_handler ( self , node ) : <EOL> '''<STR_LIT>''' <EOL> for field in node . _fields : <EOL> for t in self . _walk ( getattr ( node , field ) ) : <EOL> yield t <EOL> for cname in dir ( parser ) : <EOL> cls = getattr ( parser , cname ) <EOL> if isinstance ( cls , type ) and issubclass ( cls , parser . Node ) : <EOL> setattr ( BaseASTWalker , '<STR_LIT>' + cls . __name__ , _default_node_handler ) <EOL> class BaseLuaWriter ( BaseASTWalker ) : <EOL> """<STR_LIT>""" <EOL> def to_lines ( self ) : <EOL> """<STR_LIT>""" <EOL> raise NotImplementedError <EOL> class LuaEchoWriter ( BaseLuaWriter ) : <EOL> """<STR_LIT>""" <EOL> def to_lines ( self ) : <EOL> """<STR_LIT>""" <EOL> strs = [ ] <EOL> for token in self . _tokens : <EOL> strs . append ( token . code ) <EOL> if token . matches ( lexer . TokNewline ) : <EOL> yield '<STR_LIT>' . join ( strs ) <EOL> strs . clear ( ) <EOL> if strs : <EOL> yield '<STR_LIT>' . join ( strs ) <EOL> class LuaASTEchoWriter ( BaseLuaWriter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( ) . __init__ ( * args , ** kwargs ) <EOL> self . _pos = None <EOL> self . _indent = <NUM_LIT:0> <EOL> def _get_code_for_spaces ( self , node ) : <EOL> """<STR_LIT>""" <EOL> if self . _args . get ( '<STR_LIT>' ) : <EOL> return '<STR_LIT:\n>' <EOL> strs = [ ] <EOL> while ( ( ( node is None and self . _pos < len ( self . _tokens ) ) or <EOL> ( node is not None and self . _pos < node . end_pos ) ) and <EOL> ( isinstance ( self . _tokens [ self . _pos ] , lexer . TokSpace ) or <EOL> isinstance ( self . _tokens [ self . _pos ] , lexer . TokNewline ) or <EOL> isinstance ( self . _tokens [ self . _pos ] , lexer . TokComment ) ) ) : <EOL> strs . append ( self . _tokens [ self . _pos ] . code ) <EOL> self . _pos += <NUM_LIT:1> <EOL> return '<STR_LIT>' . join ( strs ) <EOL> def _get_name ( self , node , tok ) : <EOL> """<STR_LIT>""" <EOL> if self . _args . get ( '<STR_LIT>' ) : <EOL> return '<STR_LIT:U+0020>' + tok . code <EOL> spaces = self . _get_code_for_spaces ( node ) <EOL> assert tok . matches ( lexer . TokName ) <EOL> self . _pos += <NUM_LIT:1> <EOL> return spaces + tok . code <EOL> def _get_text ( self , node , keyword ) : <EOL> """<STR_LIT>""" <EOL> if self . _args . get ( '<STR_LIT>' ) : <EOL> return '<STR_LIT:U+0020>' + keyword <EOL> spaces = self . _get_code_for_spaces ( node ) <EOL> assert ( self . _tokens [ self . _pos ] . matches ( lexer . TokKeyword ( keyword ) ) or <EOL> self . _tokens [ self . _pos ] . matches ( lexer . TokSymbol ( keyword ) ) ) <EOL> self . _pos += <NUM_LIT:1> <EOL> return spaces + keyword <EOL> def _get_semis ( self , node ) : <EOL> """<STR_LIT>""" <EOL> if self . _args . get ( '<STR_LIT>' ) : <EOL> return '<STR_LIT:U+0020>' <EOL> spaces_and_semis = [ ] <EOL> while True : <EOL> spaces = self . _get_code_for_spaces ( node ) <EOL> if self . _tokens [ self . _pos ] . matches ( lexer . TokSymbol ( '<STR_LIT:;>' ) ) : <EOL> self . _pos += <NUM_LIT:1> <EOL> spaces_and_semis . append ( spaces + '<STR_LIT:;>' ) <EOL> else : <EOL> spaces_and_semis . append ( spaces ) <EOL> break <EOL> return '<STR_LIT>' . join ( spaces_and_semis ) <EOL> def _walk_Chunk ( self , node ) : <EOL> for stat in node . stats : <EOL> yield self . _get_semis ( node ) <EOL> for t in self . _walk ( stat ) : <EOL> yield t <EOL> yield self . _get_semis ( node ) <EOL> def _walk_StatAssignment ( self , node ) : <EOL> for t in self . _walk ( node . varlist ) : <EOL> yield t <EOL> yield self . _get_text ( node , node . assignop . code ) <EOL> for t in self . _walk ( node . explist ) : <EOL> yield t <EOL> def _walk_StatFunctionCall ( self , node ) : <EOL> for t in self . _walk ( node . functioncall ) : <EOL> yield t <EOL> def _walk_StatDo ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . block ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:end>' ) <EOL> def _walk_StatWhile ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> for t in self . _walk ( node . exp ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . block ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:end>' ) <EOL> def _walk_StatRepeat ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . block ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> for t in self . _walk ( node . exp ) : <EOL> yield t <EOL> def _walk_StatIf ( self , node ) : <EOL> short_if = ( getattr ( node , '<STR_LIT>' , False ) and <EOL> not self . _args . get ( '<STR_LIT>' ) ) <EOL> first = True <EOL> for ( exp , block ) in node . exp_block_pairs : <EOL> if exp is not None : <EOL> if first : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> first = False <EOL> else : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> if short_if : <EOL> yield self . _get_text ( node , '<STR_LIT:(>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( exp ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:)>' ) <EOL> else : <EOL> for t in self . _walk ( exp ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( block ) : <EOL> yield t <EOL> if not short_if : <EOL> self . _indent -= <NUM_LIT:1> <EOL> else : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( block ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> if not short_if : <EOL> yield self . _get_text ( node , '<STR_LIT:end>' ) <EOL> def _walk_StatForStep ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> yield self . _get_name ( node , node . name ) <EOL> yield self . _get_text ( node , '<STR_LIT:=>' ) <EOL> for t in self . _walk ( node . exp_init ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT:U+002C>' ) <EOL> for t in self . _walk ( node . exp_end ) : <EOL> yield t <EOL> if node . exp_step is not None : <EOL> yield self . _get_text ( node , '<STR_LIT:U+002C>' ) <EOL> for t in self . _walk ( node . exp_step ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . block ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:end>' ) <EOL> def _walk_StatForIn ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> for t in self . _walk ( node . namelist ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> for t in self . _walk ( node . explist ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . block ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:end>' ) <EOL> def _walk_StatFunction ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> for t in self . _walk ( node . funcname ) : <EOL> yield t <EOL> for t in self . _walk ( node . funcbody ) : <EOL> yield t <EOL> def _walk_StatLocalFunction ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> yield self . _get_name ( node , node . funcname ) <EOL> for t in self . _walk ( node . funcbody ) : <EOL> yield t <EOL> def _walk_StatLocalAssignment ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> for t in self . _walk ( node . namelist ) : <EOL> yield t <EOL> if node . explist is not None : <EOL> yield self . _get_text ( node , '<STR_LIT:=>' ) <EOL> for t in self . _walk ( node . explist ) : <EOL> yield t <EOL> def _walk_StatGoto ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> yield self . _get_name ( node , lexer . TokName ( node . label ) ) <EOL> def _walk_StatLabel ( self , node ) : <EOL> yield self . _get_code_for_spaces ( node ) <EOL> yield '<STR_LIT>' <EOL> yield self . _get_name ( node , lexer . TokName ( node . label ) ) <EOL> yield '<STR_LIT>' <EOL> def _walk_StatBreak ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> def _walk_StatReturn ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> if node . explist is not None : <EOL> for t in self . _walk ( node . explist ) : <EOL> yield t <EOL> def _walk_FunctionName ( self , node ) : <EOL> yield self . _get_name ( node , node . namepath [ <NUM_LIT:0> ] ) <EOL> if len ( node . namepath ) > <NUM_LIT:1> : <EOL> for i in range ( <NUM_LIT:1> , len ( node . namepath ) ) : <EOL> yield self . _get_text ( node , '<STR_LIT:.>' ) <EOL> yield self . _get_name ( node , node . namepath [ i ] ) <EOL> if node . methodname is not None : <EOL> yield self . _get_text ( node , '<STR_LIT::>' ) <EOL> yield self . _get_name ( node , node . methodname ) <EOL> def _walk_FunctionArgs ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT:(>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> if node . explist is not None : <EOL> for t in self . _walk ( node . explist ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:)>' ) <EOL> def _walk_VarList ( self , node ) : <EOL> for t in self . _walk ( node . vars [ <NUM_LIT:0> ] ) : <EOL> yield t <EOL> if len ( node . vars ) > <NUM_LIT:1> : <EOL> for i in range ( <NUM_LIT:1> , len ( node . vars ) ) : <EOL> yield self . _get_text ( node , '<STR_LIT:U+002C>' ) <EOL> for t in self . _walk ( node . vars [ i ] ) : <EOL> yield t <EOL> def _walk_VarName ( self , node ) : <EOL> yield self . _get_name ( node , node . name ) <EOL> def _walk_VarIndex ( self , node ) : <EOL> for t in self . _walk ( node . exp_prefix ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT:[>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . exp_index ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:]>' ) <EOL> def _walk_VarAttribute ( self , node ) : <EOL> for t in self . _walk ( node . exp_prefix ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT:.>' ) <EOL> yield self . _get_name ( node , node . attr_name ) <EOL> def _walk_NameList ( self , node ) : <EOL> if node . names is not None : <EOL> yield self . _get_name ( node , node . names [ <NUM_LIT:0> ] ) <EOL> if len ( node . names ) > <NUM_LIT:1> : <EOL> for i in range ( <NUM_LIT:1> , len ( node . names ) ) : <EOL> yield self . _get_text ( node , '<STR_LIT:U+002C>' ) <EOL> yield self . _get_name ( node , node . names [ i ] ) <EOL> def _walk_ExpList ( self , node ) : <EOL> if node . exps is not None : <EOL> for t in self . _walk ( node . exps [ <NUM_LIT:0> ] ) : <EOL> yield t <EOL> if len ( node . exps ) > <NUM_LIT:1> : <EOL> for i in range ( <NUM_LIT:1> , len ( node . exps ) ) : <EOL> yield self . _get_text ( node , '<STR_LIT:U+002C>' ) <EOL> for t in self . _walk ( node . exps [ i ] ) : <EOL> yield t <EOL> def _walk_ExpValue ( self , node ) : <EOL> yield self . _get_code_for_spaces ( node ) <EOL> in_parens = False <EOL> if self . _args . get ( '<STR_LIT>' ) : <EOL> if isinstance ( node . value , parser . Node ) : <EOL> yield '<STR_LIT:(>' <EOL> in_parens = True <EOL> self . _indent += <NUM_LIT:1> <EOL> else : <EOL> if self . _tokens [ self . _pos ] . matches ( lexer . TokSymbol ( '<STR_LIT:(>' ) ) : <EOL> yield '<STR_LIT:(>' <EOL> in_parens = True <EOL> self . _pos += <NUM_LIT:1> <EOL> self . _indent += <NUM_LIT:1> <EOL> if node . value == None : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> elif node . value == False : <EOL> yield self . _get_text ( node , '<STR_LIT:false>' ) <EOL> elif node . value == True : <EOL> yield self . _get_text ( node , '<STR_LIT:true>' ) <EOL> elif isinstance ( node . value , lexer . TokName ) : <EOL> yield self . _get_name ( node , node . value ) <EOL> elif ( isinstance ( node . value , lexer . TokNumber ) or <EOL> isinstance ( node . value , lexer . TokString ) ) : <EOL> yield self . _get_code_for_spaces ( node ) <EOL> yield node . value . code <EOL> if not self . _args . get ( '<STR_LIT>' ) : <EOL> self . _pos += <NUM_LIT:1> <EOL> else : <EOL> for t in self . _walk ( node . value ) : <EOL> yield t <EOL> if in_parens : <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:)>' ) <EOL> def _walk_VarargDots ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> def _walk_ExpBinOp ( self , node ) : <EOL> for t in self . _walk ( node . exp1 ) : <EOL> yield t <EOL> yield self . _get_text ( node , node . binop . code ) <EOL> for t in self . _walk ( node . exp2 ) : <EOL> yield t <EOL> def _walk_ExpUnOp ( self , node ) : <EOL> yield self . _get_text ( node , node . unop . code ) <EOL> for t in self . _walk ( node . exp ) : <EOL> yield t <EOL> def _walk_FunctionCall ( self , node ) : <EOL> for t in self . _walk ( node . exp_prefix ) : <EOL> yield t <EOL> if node . args is None : <EOL> yield self . _get_text ( node , '<STR_LIT:(>' ) <EOL> yield self . _get_text ( node , '<STR_LIT:)>' ) <EOL> elif isinstance ( node . args , lexer . TokString ) : <EOL> yield self . _get_code_for_spaces ( node ) <EOL> if not self . _args . get ( '<STR_LIT>' ) : <EOL> self . _pos += <NUM_LIT:1> <EOL> yield node . args . code <EOL> else : <EOL> for t in self . _walk ( node . args ) : <EOL> yield t <EOL> def _walk_FunctionCallMethod ( self , node ) : <EOL> for t in self . _walk ( node . exp_prefix ) : <EOL> yield t <EOL> yield self . _get_text ( node , '<STR_LIT::>' ) <EOL> yield self . _get_name ( node , node . methodname ) <EOL> if node . args is None : <EOL> yield self . _get_text ( node , '<STR_LIT:(>' ) <EOL> yield self . _get_text ( node , '<STR_LIT:)>' ) <EOL> elif isinstance ( node . args , lexer . TokString ) : <EOL> yield self . _get_code_for_spaces ( node ) <EOL> if not self . _args . get ( '<STR_LIT>' ) : <EOL> assert node . args . matches ( self . _tokens [ self . _pos ] ) <EOL> self . _pos += <NUM_LIT:1> <EOL> yield node . args . code <EOL> else : <EOL> for t in self . _walk ( node . args ) : <EOL> yield t <EOL> def _walk_Function ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT>' ) <EOL> for t in self . _walk ( node . funcbody ) : <EOL> yield t <EOL> def _walk_FunctionBody ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT:(>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> if node . parlist is not None : <EOL> for t in self . _walk ( node . parlist ) : <EOL> yield t <EOL> if node . dots is not None : <EOL> yield self . _get_text ( node , '<STR_LIT:U+002C>' ) <EOL> for t in self . _walk ( node . dots ) : <EOL> yield t <EOL> else : <EOL> if node . dots is not None : <EOL> for t in self . _walk ( node . dots ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:)>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . block ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:end>' ) <EOL> def _walk_TableConstructor ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT:{>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> if node . fields : <EOL> for t in self . _walk ( node . fields [ <NUM_LIT:0> ] ) : <EOL> yield t <EOL> if len ( node . fields ) > <NUM_LIT:1> : <EOL> for i in range ( <NUM_LIT:1> , len ( node . fields ) ) : <EOL> yield self . _get_code_for_spaces ( node ) <EOL> if self . _args . get ( '<STR_LIT>' ) : <EOL> yield '<STR_LIT:U+002CU+0020>' <EOL> else : <EOL> yield self . _get_text ( node , self . _tokens [ self . _pos ] . code ) <EOL> for t in self . _walk ( node . fields [ i ] ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_code_for_spaces ( node ) <EOL> if not self . _args . get ( '<STR_LIT>' ) : <EOL> if ( self . _tokens [ self . _pos ] . matches ( lexer . TokSymbol ( '<STR_LIT:U+002C>' ) ) or <EOL> self . _tokens [ self . _pos ] . matches ( lexer . TokSymbol ( '<STR_LIT:;>' ) ) ) : <EOL> yield self . _get_text ( node , self . _tokens [ self . _pos ] . code ) <EOL> yield self . _get_text ( node , '<STR_LIT:}>' ) <EOL> def _walk_FieldExpKey ( self , node ) : <EOL> yield self . _get_text ( node , '<STR_LIT:[>' ) <EOL> self . _indent += <NUM_LIT:1> <EOL> for t in self . _walk ( node . key_exp ) : <EOL> yield t <EOL> self . _indent -= <NUM_LIT:1> <EOL> yield self . _get_text ( node , '<STR_LIT:]>' ) <EOL> yield self . _get_text ( node , '<STR_LIT:=>' ) <EOL> for t in self . _walk ( node . exp ) : <EOL> yield t <EOL> def _walk_FieldNamedKey ( self , node ) : <EOL> yield self . _get_name ( node , node . key_name ) <EOL> yield self . _get_text ( node , '<STR_LIT:=>' ) <EOL> for t in self . _walk ( node . exp ) : <EOL> yield t <EOL> def _walk_FieldExp ( self , node ) : <EOL> for t in self . _walk ( node . exp ) : <EOL> yield t <EOL> def _walk ( self , node ) : <EOL> """<STR_LIT>""" <EOL> yield self . _get_code_for_spaces ( node ) <EOL> for t in super ( ) . _walk ( node ) : <EOL> yield t <EOL> def to_lines ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _pos = <NUM_LIT:0> <EOL> linebuf = [ ] <EOL> last_was_newline = False <EOL> for chunk in self . walk ( ) : <EOL> if self . _args . get ( '<STR_LIT>' ) : <EOL> if chunk == '<STR_LIT:\n>' : <EOL> if last_was_newline : <EOL> chunk = '<STR_LIT>' <EOL> last_was_newline = True <EOL> else : <EOL> last_was_newline = False <EOL> parts = chunk . split ( '<STR_LIT:\n>' ) <EOL> while len ( parts ) > <NUM_LIT:1> : <EOL> linebuf . append ( parts . pop ( <NUM_LIT:0> ) ) <EOL> yield '<STR_LIT>' . join ( linebuf ) + '<STR_LIT:\n>' <EOL> linebuf . clear ( ) <EOL> linebuf . append ( parts . pop ( <NUM_LIT:0> ) ) <EOL> last = '<STR_LIT>' . join ( linebuf ) + self . _get_code_for_spaces ( None ) <EOL> parts = last . split ( '<STR_LIT:\n>' ) <EOL> for i in range ( len ( parts ) - <NUM_LIT:1> ) : <EOL> yield parts [ i ] + '<STR_LIT:\n>' <EOL> if parts [ - <NUM_LIT:1> ] : <EOL> yield parts [ - <NUM_LIT:1> ] <EOL> class MinifyNameFactory ( ) : <EOL> """<STR_LIT>""" <EOL> NAME_CHARS = '<STR_LIT>' <EOL> PRESERVED_NAMES = lexer . LUA_KEYWORDS | PICO8_BUILTINS <EOL> def __init__ ( self ) : <EOL> self . _name_map = { } <EOL> self . _next_name_id = <NUM_LIT:0> <EOL> @ classmethod <EOL> def _name_for_id ( cls , id ) : <EOL> first = '<STR_LIT>' <EOL> if id >= len ( MinifyNameFactory . NAME_CHARS ) : <EOL> first = cls . _name_for_id ( int ( id / len ( MinifyNameFactory . NAME_CHARS ) ) ) <EOL> return first + ( MinifyNameFactory . NAME_CHARS [ id % len ( MinifyNameFactory . NAME_CHARS ) ] ) <EOL> def get_short_name ( self , name ) : <EOL> if name in MinifyNameFactory . PRESERVED_NAMES : <EOL> return name <EOL> if name not in self . _name_map : <EOL> new_name = None <EOL> while True : <EOL> new_name = self . _name_for_id ( self . _next_name_id ) <EOL> self . _next_name_id += <NUM_LIT:1> <EOL> if not new_name in MinifyNameFactory . PRESERVED_NAMES : <EOL> break <EOL> self . _name_map [ name ] = new_name <EOL> util . debug ( '<STR_LIT>' . format ( <EOL> name , new_name ) ) <EOL> return self . _name_map [ name ] <EOL> class LuaMinifyWriter ( LuaASTEchoWriter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( ) . __init__ ( * args , ** kwargs ) <EOL> self . _name_factory = MinifyNameFactory ( ) <EOL> def _get_name ( self , node , tok ) : <EOL> """<STR_LIT>""" <EOL> spaces = self . _get_code_for_spaces ( node ) <EOL> assert tok . matches ( lexer . TokName ) <EOL> self . _pos += <NUM_LIT:1> <EOL> return spaces + self . _name_factory . get_short_name ( tok . code ) <EOL> def _get_code_for_spaces ( self , node ) : <EOL> """<STR_LIT>""" <EOL> start_pos = self . _pos <EOL> strs = [ ] <EOL> while ( ( ( node is None and self . _pos < len ( self . _tokens ) ) or <EOL> ( node is not None and self . _pos < node . end_pos ) ) and <EOL> ( isinstance ( self . _tokens [ self . _pos ] , lexer . TokSpace ) or <EOL> isinstance ( self . _tokens [ self . _pos ] , lexer . TokNewline ) or <EOL> isinstance ( self . _tokens [ self . _pos ] , lexer . TokComment ) ) ) : <EOL> if not isinstance ( self . _tokens [ self . _pos ] , lexer . TokComment ) : <EOL> strs . append ( self . _tokens [ self . _pos ] . code ) <EOL> self . _pos += <NUM_LIT:1> <EOL> if ( ( start_pos == <NUM_LIT:0> ) or ( self . _pos == len ( self . _tokens ) ) ) : <EOL> return '<STR_LIT>' <EOL> spaces = '<STR_LIT>' . join ( strs ) <EOL> spaces = re . sub ( r'<STR_LIT:\t>' , '<STR_LIT:U+0020>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:\n>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:\n>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:U+0020>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:\n>' , spaces ) <EOL> return spaces <EOL> def _get_semis ( self , node ) : <EOL> """<STR_LIT>""" <EOL> spaces_without_semis = [ ] <EOL> while True : <EOL> spaces = self . _get_code_for_spaces ( node ) <EOL> if self . _tokens [ self . _pos ] . matches ( lexer . TokSymbol ( '<STR_LIT:;>' ) ) : <EOL> self . _pos += <NUM_LIT:1> <EOL> spaces_without_semis . append ( spaces + '<STR_LIT:U+0020>' ) <EOL> else : <EOL> spaces_without_semis . append ( spaces ) <EOL> break <EOL> return '<STR_LIT>' . join ( spaces_without_semis ) <EOL> class LuaFormatterWriter ( LuaASTEchoWriter ) : <EOL> """<STR_LIT>""" <EOL> DEFAULT_INDENT_WIDTH = <NUM_LIT:2> <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( ) . __init__ ( * args , ** kwargs ) <EOL> self . _indent_mult = self . _args . get ( <EOL> '<STR_LIT>' , <EOL> LuaFormatterWriter . DEFAULT_INDENT_WIDTH ) <EOL> def _get_code_for_spaces ( self , node ) : <EOL> """<STR_LIT>""" <EOL> start_pos = self . _pos <EOL> strs = [ ] <EOL> while ( ( ( node is None and self . _pos < len ( self . _tokens ) ) or <EOL> ( node is not None and self . _pos < node . end_pos ) ) and <EOL> ( isinstance ( self . _tokens [ self . _pos ] , lexer . TokSpace ) or <EOL> isinstance ( self . _tokens [ self . _pos ] , lexer . TokNewline ) or <EOL> isinstance ( self . _tokens [ self . _pos ] , lexer . TokComment ) ) ) : <EOL> strs . append ( self . _tokens [ self . _pos ] . code ) <EOL> self . _pos += <NUM_LIT:1> <EOL> spaces = '<STR_LIT>' . join ( strs ) <EOL> spaces = re . sub ( r'<STR_LIT:\t>' , '<STR_LIT:U+0020>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT:\r\n>' , '<STR_LIT:\n>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:\n>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT:\r>' , '<STR_LIT:\n>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:\n>' , spaces ) <EOL> if start_pos != <NUM_LIT:0> : <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , <EOL> '<STR_LIT:\n>' + '<STR_LIT:U+0020>' * self . _indent_mult * self . _indent + '<STR_LIT>' , <EOL> spaces ) <EOL> if start_pos == <NUM_LIT:0> : <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:\n>' + '<STR_LIT:U+0020>' * self . _indent_mult * self . _indent , <EOL> spaces ) <EOL> if start_pos == <NUM_LIT:0> : <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT>' , spaces ) <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT>' , spaces ) <EOL> if self . _pos == len ( self . _tokens ) : <EOL> spaces = re . sub ( r'<STR_LIT>' , '<STR_LIT:\n>' , spaces ) <EOL> return spaces <EOL> class LuaMinifyTokenWriter ( BaseLuaWriter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( ) . __init__ ( * args , ** kwargs ) <EOL> self . _name_factory = MinifyNameFactory ( ) <EOL> self . _last_was_name_keyword_number = False <EOL> self . _saw_if = False <EOL> def to_lines ( self ) : <EOL> """<STR_LIT>""" <EOL> for token in self . _tokens : <EOL> if ( token . matches ( lexer . TokComment ) or <EOL> token . matches ( lexer . TokSpace ) ) : <EOL> continue <EOL> elif token . matches ( lexer . TokNewline ) : <EOL> if self . _saw_if : <EOL> self . _saw_if = False <EOL> self . _last_was_name_keyword_number = False <EOL> yield '<STR_LIT:\n>' <EOL> continue <EOL> elif token . matches ( lexer . TokName ) : <EOL> if self . _last_was_name_keyword_number : <EOL> yield '<STR_LIT:U+0020>' <EOL> self . _last_was_name_keyword_number = True <EOL> yield self . _name_factory . get_short_name ( token . code ) <EOL> elif token . matches ( lexer . TokKeyword ) : <EOL> if token . code == '<STR_LIT>' : <EOL> self . _saw_if = True <EOL> if self . _last_was_name_keyword_number : <EOL> yield '<STR_LIT:U+0020>' <EOL> self . _last_was_name_keyword_number = True <EOL> yield token . code <EOL> elif token . matches ( lexer . TokNumber ) : <EOL> if self . _last_was_name_keyword_number : <EOL> yield '<STR_LIT:U+0020>' <EOL> self . _last_was_name_keyword_number = True <EOL> yield token . code <EOL> else : <EOL> self . _last_was_name_keyword_number = False <EOL> yield token . code <EOL> class LuaFormatterTokenWriter ( LuaASTEchoWriter ) : <EOL> """<STR_LIT>""" <EOL> DEFAULT_INDENT_WIDTH = <NUM_LIT:2> <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( ) . __init__ ( * args , ** kwargs ) <EOL> self . _indent_mult = self . _args . get ( <EOL> '<STR_LIT>' , <EOL> LuaFormatterWriter . DEFAULT_INDENT_WIDTH ) <EOL> def to_lines ( self ) : <EOL> """<STR_LIT>""" <EOL> indent_level = <NUM_LIT:0> <EOL> space_buffer = [ ] <EOL> in_function = False <EOL> previous_nonspace = None <EOL> for token in self . _tokens : <EOL> if token . matches ( lexer . TokNewline ) : <EOL> space_buffer . append ( token ) <EOL> continue <EOL> if token . matches ( lexer . TokSpace ) : <EOL> space_buffer . append ( token ) <EOL> continue <EOL> if ( any ( token . matches ( lexer . TokSymbol ( s ) ) <EOL> for s in ( '<STR_LIT:)>' , '<STR_LIT:}>' , '<STR_LIT:]>' ) ) or <EOL> any ( token . matches ( lexer . TokKeyword ( k ) ) <EOL> for k in ( '<STR_LIT:end>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) ) ) : <EOL> indent_level -= <NUM_LIT:1> <EOL> space_str = '<STR_LIT>' . join ( t . code for t in space_buffer ) <EOL> space_buffer . clear ( ) <EOL> newline_count = space_str . count ( '<STR_LIT:\n>' ) <EOL> if newline_count : <EOL> if newline_count > <NUM_LIT:1> : <EOL> yield '<STR_LIT:\n>' <EOL> yield '<STR_LIT:\n>' + '<STR_LIT:U+0020>' * indent_level * self . _indent_mult <EOL> elif token . matches ( lexer . TokComment ) : <EOL> yield '<STR_LIT:U+0020>' <EOL> elif ( any ( token . matches ( lexer . TokSymbol ( s ) ) <EOL> for s in ( '<STR_LIT:U+002C>' , '<STR_LIT:;>' , '<STR_LIT:)>' , '<STR_LIT:]>' , '<STR_LIT:}>' , '<STR_LIT:..>' ) ) or <EOL> ( previous_nonspace is not None and <EOL> any ( previous_nonspace . matches ( lexer . TokSymbol ( s ) ) <EOL> for s in ( '<STR_LIT:(>' , '<STR_LIT:[>' , '<STR_LIT:{>' , '<STR_LIT:..>' ) ) ) or <EOL> ( previous_nonspace is not None and <EOL> previous_nonspace . matches ( lexer . TokKeyword ( '<STR_LIT>' ) ) and <EOL> token . matches ( lexer . TokSymbol ( '<STR_LIT:(>' ) ) ) or <EOL> previous_nonspace is None ) : <EOL> pass <EOL> else : <EOL> yield '<STR_LIT:U+0020>' <EOL> previous_nonspace = token <EOL> yield token . code <EOL> if in_function and token . matches ( lexer . TokSymbol ( '<STR_LIT:)>' ) ) : <EOL> in_function = False <EOL> indent_level += <NUM_LIT:1> <EOL> if token . matches ( lexer . TokKeyword ( '<STR_LIT>' ) ) : <EOL> in_function = True <EOL> if ( any ( token . matches ( lexer . TokSymbol ( s ) ) <EOL> for s in ( '<STR_LIT:(>' , '<STR_LIT:{>' , '<STR_LIT:[>' ) ) or <EOL> any ( token . matches ( lexer . TokKeyword ( k ) ) <EOL> for k in ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) ) ) : <EOL> indent_level += <NUM_LIT:1> <EOL> yield '<STR_LIT:\n>' </s>
