123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695(*
Copyright 2012-2025 Codinuum Software Lab <https://codinuum.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)(*
* A pretty printer for the Python programming language
*
* printer.ml
*
*)(*open Printf*)openAst(*open Common*)letindent_unit=ref2letpr_strings=print_stringsletpr_space()=print_string" "letpr_comma()=print_string","letpr_period()=print_string"."letpr_colon()=print_string":"letpr_semicolon()=print_string";"letpr_equal()=print_string"="letpr_null()=()letpr_newline()=print_newline()letrecpr_listprsep=function|[]->()|[x]->prx|h::t->prh;sep();pr_listprseptletpr_opt?(pr_head=fun()->())pr=functionNone->()|Somex->pr_head();prxletpr_indentlevel=pr_string(String.make(level*!indent_unit)' ')letpr_name=function_,n->pr_stringnletpr_namesnames=pr_listpr_namepr_commanamesletpr_dottednamedname=pr_listpr_namepr_perioddnameletrecpr_fileinput=function|Fileinput(_,finput)->pr_list(pr_statement0)pr_nullfinputandpr_statementlevelstmt=matchstmt.stmt_descwith|Ssimplesstmts->pr_indentlevel;pr_listpr_smallstmtpr_semicolonsstmts;pr_newline()|Sasyncstmt->pr_string"async ";pr_statementlevelstmt|Sif(cnd,thn,elifs,else_opt)->pr_expr_suitelevel"if"(cnd,thn);pr_list(pr_eliflevel)pr_nullelifs;pr_else_optlevelelse_opt|Swhile(cnd,suite,else_opt)->pr_expr_suitelevel"while"(cnd,suite);pr_else_optlevelelse_opt|Sfor(targs,exprs,suite,else_opt)->pr_indentlevel;pr_string"for ";pr_listpr_targetpr_commatargs;pr_string" in ";pr_exprsexprs;pr_colon();pr_suitelevelsuite;pr_else_optlevelelse_opt|Stry(suite,except_suites,else_opt,fin_opt)->pr_indentlevel;pr_string"try:";pr_suitelevelsuite;pr_list(function|EX_,suite->pr_indentlevel;pr_string"except:";pr_suitelevelsuite|EX1(_,expr),suite->pr_indentlevel;pr_string"except ";pr_exprexpr;pr_colon();pr_suitelevelsuite|EX2(_,expr,targ),suite->pr_indentlevel;pr_string"except ";pr_exprexpr;pr_comma();pr_targettarg;pr_colon();pr_suitelevelsuite)pr_nullexcept_suites;pr_else_optlevelelse_opt;pr_finally_optlevelfin_opt|Stryfin(suite1,(_,suite2))->pr_indentlevel;pr_string"try:";pr_suitelevelsuite1;pr_indentlevel;pr_string"finally:";pr_suitelevelsuite2;|Swith(withitems,suite)->pr_indentlevel;pr_string"with ";pr_listpr_with_itempr_commawithitems;pr_colon();pr_suitelevelsuite|Sasync_funcdef(decs,name,params,retann_opt,suite)->pr_indentlevel;pr_listpr_decoratorpr_nulldecs;pr_string"async def ";pr_namename;pr_string"(";pr_parametersparams;pr_string")";beginmatchretann_optwith|Somee->pr_string"->";pr_expre|_->()end;pr_colon();pr_suitelevelsuite|Sfuncdef(decs,name,params,retann_opt,suite)->pr_indentlevel;pr_listpr_decoratorpr_nulldecs;pr_string"def ";pr_namename;pr_string"(";pr_parametersparams;pr_string")";beginmatchretann_optwith|Somee->pr_string"->";pr_expre|_->()end;pr_colon();pr_suitelevelsuite|Sclassdef(decs,name,arglist,suite)->pr_indentlevel;pr_listpr_decoratorpr_nulldecs;pr_string"class ";pr_namename;(matcharglistwith|loc,[]whenloc=Ast.Loc.dummy->()|_,[]->pr_string"()"|_->pr_string"(";pr_arglistarglist;pr_string")");pr_colon();pr_suitelevelsuite|Smatch(subj,case_blocks)->pr_indentlevel;pr_string"match ";pr_subject_exprsubj;pr_colon();letlevel'=level+1inpr_newline();pr_list(pr_case_blocklevel')pr_nullcase_blocks|Serror->pr_indentlevel;pr_string"ERROR";pr_newline()|Smarkerm->pr_stringm;pr_newline()andpr_subject_expr=function|SEstar(_,e,el)->pr_expre;pr_comma();pr_listpr_exprpr_commael|SEnamed(_,e)->pr_expreandpr_case_blocklevelcase_block=let_,pat,guard_opt,suite=case_blockinpr_indentlevel;pr_string"case ";pr_patternpat;pr_optpr_guardguard_opt;pr_colon();pr_suitelevelsuiteandpr_pattern=function|PAas(_,p0,p1)->pr_patternp0;pr_string" as ";pr_patternp1|PAor(_,pl)->pr_listpr_pattern(fun()->pr_string" | ")pl|PAcapturen->pr_namen|PAliteralle->pr_literal_exprle|PAwildcard_->pr_string"_"|PAvalue(_,nl)->pr_dottednamenl|PAgroup(_,p)->pr_string"(";pr_patternp;pr_string")"|PAseqB(_,p_opt)->pr_string"[";pr_optpr_patternp_opt;pr_string"]"|PAseqP(_,p_opt)->pr_string"(";pr_optpr_patternp_opt;pr_string")"|PAseqOpen(_,p,p_opt)->pr_patternp;pr_comma();pr_optpr_patternp_opt|PAseqMaybe(_,pl)->pr_listpr_patternpr_commapl|PAstar(_,p)->pr_string"*";pr_patternp|PAdblStar(_,p)->pr_string"**";pr_patternp|PAmap(_,pl,p_opt)->beginpr_string"{";pr_listpr_patternpr_commapl;pr_opt~pr_head:pr_commapr_patternp_opt;pr_string"}"end|PAkeyValue(_,k,p)->pr_keyk;pr_colon();pr_patternp|PAkeyword(_,n,p)->pr_namen;pr_equal();pr_patternp|PAclass(_,nl,pl0,pl1)->pr_dottednamenl;pr_string"(";pr_listpr_patternpr_commapl0;beginmatchpl0with|[]->()|_->pr_comma()end;pr_listpr_patternpr_commapl1;pr_string")"andpr_literal_expr=function|LEsigned(_,l)->pr_literall|LEsignedMinus(_,l)->pr_string"-";pr_literall|LEcmplxPlus(_,le,s)->pr_literal_exprle;pr_string"+";pr_strings|LEcmplxMinus(_,le,s)->pr_literal_exprle;pr_string"-";pr_strings|LEstrings(_,sl)->beginpr_list(function|PSlong(_,s)->pr_strings|PSshort(_,s)->pr_strings)pr_spaceslend|LEnone_->pr_string"None"|LEtrue_->pr_string"True"|LEfalse_->pr_string"False"andpr_key=function|Kliteral(_,le)->pr_literal_exprle|Kattr(_,nl)->pr_dottednamenlandpr_guard(_,e)=pr_string"if ";pr_expreandpr_with_item(expr,targ_opt)=pr_exprexpr;beginmatchtarg_optwith|None->()|Sometarg->pr_string" as ";pr_targettargendandpr_else_optlevel=pr_opt(fun(_,suite)->pr_indentlevel;pr_string"else:";pr_suitelevelsuite)andpr_finally_optlevel=pr_opt(fun(_,suite)->pr_indentlevel;pr_string"finally:";pr_suitelevelsuite)andpr_eliflevel(_,expr,suite)=pr_expr_suitelevel"elif"(expr,suite)andpr_expr_suitelevelkw(expr,suite)=pr_indentlevel;pr_stringkw;pr_space();pr_exprexpr;pr_colon();pr_suitelevelsuiteandpr_exprsexprs=pr_listpr_exprpr_commaexprsandpr_testlisttestlist=iftestlist.yieldthenpr_string"yield ";pr_listpr_exprpr_commatestlist.listandpr_targsts=pr_exprstsandpr_smallstmtsstmt=matchsstmt.sstmt_descwith|SSexprexprs->pr_listpr_exprpr_commaexprs|SSassign(testlist_list,testlist)->beginpr_listpr_testlistpr_equaltestlist_list;pr_equal();pr_testlisttestlistend|SSannassign(targs,(_,expr),testlist_opt)->beginpr_targstargs;pr_colon();pr_space();pr_exprexpr;beginmatchtestlist_optwith|Sometestlist->pr_space();pr_testlisttestlist|_->()endend|SSaugassign(targs,augop,testlist)->beginpr_targstargs;pr_space();pr_augopaugop;pr_space();pr_testlisttestlistend|SSprintexprs->pr_string"print ";pr_exprsexprs|SSprintchevron(expr,exprs)->beginpr_string"print>>";pr_exprexpr;pr_comma();pr_exprsexprsend|SSdel(targs)->pr_string"del ";pr_targstargs|SSpass->pr_string"pass"|SSbreak->pr_string"break"|SScontinue->pr_string"continue"|SSreturnexprs->pr_string"return ";pr_exprsexprs|SSraise->pr_string"raise"|SSraise1expr->pr_string"raise ";pr_exprexpr|SSraise2(expr1,expr2)->beginpr_string"raise ";pr_exprexpr1;pr_comma();pr_exprexpr2;end|SSraisefrom(expr1,expr2)->beginpr_string"raise ";pr_exprexpr1;pr_string" from ";pr_exprexpr2;end|SSraise3(expr1,expr2,expr3)->beginpr_string"raise ";pr_exprexpr1;pr_comma();pr_exprexpr2;pr_comma();pr_exprexpr3;end|SSyieldexprs->pr_string"yield ";pr_exprsexprs|SSimport(dname_as_names)->beginpr_string"import ";pr_listpr_dottedname_as_namepr_commadname_as_namesend|SSfrom(dots_opt,dname_opt,name_as_names)->beginpr_string"from ";beginmatchdots_optwith|Some(_,ndots)->pr_string(String.makendots'.');pr_space()|_->()end;beginmatchdname_optwith|Somedname->pr_dottednamedname;pr_space()|_->()end;pr_string"import ";beginmatchname_as_nameswith|[]->pr_string"*"|_->pr_listpr_name_as_namepr_commaname_as_namesendend|SSglobalnames->pr_string"global ";pr_namesnames|SSnonlocalnames->pr_string"nonlocal ";pr_namesnames|SSexecexpr->pr_string"exec ";pr_exprexpr|SSexec2(expr1,expr2)->beginpr_string"exec ";pr_exprexpr1;pr_string" in ";pr_exprexpr2end|SSexec3(expr1,expr2,expr3)->beginpr_string"exec ";pr_exprexpr1;pr_string" in ";pr_exprexpr2;pr_comma();pr_exprexpr3end|SSassertexpr->pr_string"assert ";pr_exprexpr|SSassert2(expr1,expr2)->beginpr_string"assert ";pr_exprexpr1;pr_comma();pr_exprexpr2end|SSerror->pr_string"ERROR"andpr_dottedname_as_name(dname,name_opt)=pr_dottednamedname;pr_opt(funname->pr_string" as ";pr_namename)name_optandpr_name_as_name(name,name_opt)=pr_namename;pr_opt(funname->pr_string" as ";pr_namename)name_optandpr_suitelevel(_,stmts)=matchstmtswith|[{stmt_desc=(Ssimple_);stmt_loc=_}assstmt]->pr_statement0sstmt|_->letlevel'=level+1inpr_newline();pr_list(pr_statementlevel')pr_nullstmtsandpr_vararg=function|VAarg(fpdef,expr_opt)->beginpr_fpdeffpdef;pr_opt(funexpr->pr_equal();pr_exprexpr)expr_optend|VAargs(_,None,expr_opt)->beginpr_string"*";pr_opt(funexpr->pr_colon();pr_exprexpr)expr_optend|VAargs(_,Somen,expr_opt)->beginpr_string"*";pr_namen;pr_opt(funexpr->pr_colon();pr_exprexpr)expr_optend|VAkwargs(_,n,expr_opt)->beginpr_string"**";pr_namen;pr_opt(funexpr->pr_colon();pr_exprexpr)expr_optend|VAsep_->pr_string"/"andpr_parameters(_,vargs)=pr_listpr_varargpr_commavargsandpr_fpdef=function|Fnamename->pr_namename|Ftyped(_,name,expr)->pr_namename;pr_colon();pr_exprexpr|Flist(_,fpdefs)->pr_string"(";pr_listpr_fpdefpr_commafpdefs;pr_string")"andpr_decorator(_,dname,arglist)=pr_string"@";pr_dottednamedname;pr_arglistarglist;pr_newline();andpr_exprexpr=matchexpr.expr_descwith|Eprimaryprim->pr_primaryprim|Epower(prim,expr)->pr_primaryprim;pr_string"**";pr_exprexpr|Ebop(expr1,bop,expr2)->pr_exprexpr1;pr_bopbop;pr_exprexpr2;|Euop(uop,expr)->pr_uopuop;pr_exprexpr|Elambda(params,expr)->pr_string"lambda";(matchparamswith|_,[]->()|_->pr_space();pr_parametersparams);pr_colon();pr_exprexpr|Econd(expr1,expr2,expr3)->pr_exprexpr1;pr_string" if ";pr_exprexpr2;pr_string" else ";pr_exprexpr3|Estarexpr->pr_string"*";pr_exprexpr|Enamed(expr1,expr2)->pr_exprexpr1;pr_string":=";pr_exprexpr2|Efromexpr->pr_string"from ";pr_exprexpr|Earg(expr1,expr2)->pr_exprexpr1;pr_string"=";pr_exprexpr2(* for print *)|Eerror->pr_string"ERROR"andpr_primaryprim=_pr_primaryprim.prim_descand_pr_primary=function|Pnamename->pr_namename|Pliterallit->pr_literallit|Pexprexpr->pr_exprexpr|Pparenexpr->pr_string"(";pr_exprexpr;pr_string")"|Ptuple[]->pr_string"()"|Ptupleexprs->pr_exprsexprs|Pyieldexprs->pr_string"(yield";pr_exprsexprs;pr_string")"|PcompT(expr,compfor)->pr_string"(";pr_exprexpr;pr_space();pr_compforcompfor;pr_string")"|PcompL(expr,compfor)->pr_string"[";pr_exprexpr;pr_space();pr_compforcompfor;pr_string"]"|Plistexprs->pr_string"[";pr_exprsexprs;pr_string"]"|Plistnull->pr_string"[]"|Pdictorsetdictorsetmaker->pr_string"{";pr_dictorsetmakerdictorsetmaker;pr_string"}"|Pdictnull->pr_string"{}"|Pstrconvexprs->pr_string"`";pr_exprsexprs;pr_string"`"|Pattrref(prim,name)->pr_primaryprim;pr_period();pr_namename|Psubscript(prim,exprs)->pr_primaryprim;pr_string"[";pr_exprsexprs;pr_string"]"|Pslice(prim,sliceitems)->pr_primaryprim;pr_string"[";pr_listpr_sliceitempr_commasliceitems;pr_string"]"|Pcall(prim,arglist)->pr_primaryprim;pr_string"(";pr_arglistarglist;pr_string")"|Pawaitprim->pr_string"await ";pr_primaryprim|Pellipsis->pr_string"..."andpr_literal=function|Lintegerstr->pr_stringstr|Llongintegerstr->pr_stringstr|Lfloatnumberstr->pr_stringstr|Limagnumberstr->pr_stringstr|Lstringpystrs->pr_list(function|PSlong(_,s)->pr_strings|PSshort(_,s)->pr_strings)pr_spacepystrs|Lnone->pr_string"None"|Ltrue->pr_string"True"|Lfalse->pr_string"False"andpr_targetx=pr_exprxandpr_listfor(_,exprs1,exprs2,listiter_opt)=pr_string"for ";pr_exprsexprs1;pr_string" in ";pr_exprsexprs2;pr_opt(funlistiter->pr_space();pr_listiterlistiter)listiter_optandpr_listif(_,expr,listiter_opt)=pr_string"if ";pr_exprexpr;pr_opt(funlistiter->pr_space();pr_listiterlistiter)listiter_optandpr_listiter=function|LIforlistfor->pr_listforlistfor|LIiflistif->pr_listiflistifandpr_dictelemdelem=matchdelem.delem_descwith|DEkeyValue(e1,e2)->pr_expre1;pr_colon();pr_expre2|DEstarStare->pr_string"**";pr_expreandpr_dictorsetmaker=function|DSMdictkey_dats->pr_listpr_dictelempr_commakey_dats|DSMdictC(delem,compfor)->pr_dictelemdelem;pr_space();pr_compforcompfor|DSMsetes->pr_listpr_exprpr_commaes|DSMsetC(e,compfor)->pr_expre;pr_space();pr_compforcompforandpr_expr_optexpr_opt=pr_optpr_exprexpr_optandpr_sliceitem=function|SIexprexpr->pr_exprexpr|SI2(_,expr_opt1,expr_opt2)->pr_expr_optexpr_opt1;pr_colon();pr_expr_optexpr_opt2|SI3(_,expr_opt1,expr_opt2,expr_opt3)->pr_expr_optexpr_opt1;pr_colon();pr_expr_optexpr_opt2;pr_colon();pr_expr_optexpr_opt3(*| SIellipsis _ -> pr_string "..."*)andpr_arglist(_,args)=pr_listpr_argumentpr_commaargsandpr_argument=function|Aarg(_,expr,expr_opt)->beginpr_exprexpr;beginmatchexpr_optwith|Somee->pr_equal();pr_expre|_->()endend|Acomp(_,expr,compfor)->pr_exprexpr;pr_space();pr_compforcompfor|Aassign(_,expr1,expr2)->pr_exprexpr1;pr_string":=";pr_exprexpr2|Aargs(_,expr)->pr_string"*";pr_exprexpr|Akwargs(_,expr)->pr_string"**";pr_exprexprandpr_compiter=function|Cforcompfor->pr_compforcompfor|Cifcompif->pr_compifcompifandpr_compif(_,expr,compiter_opt)=pr_string"if ";pr_exprexpr;pr_opt(funcompiter->pr_space();pr_compitercompiter)compiter_optandpr_compfor(_,(exprs,expr,compiter_opt),async)=ifasyncthenpr_string"async ";pr_string"for ";pr_exprsexprs;pr_string" in ";pr_exprexpr;pr_opt(funcompiter->pr_space();pr_compitercompiter)compiter_optandpr_augop=function|AaddEq->pr_string"+="|AsubEq->pr_string"-="|AmulEq->pr_string"*="|AdivEq->pr_string"/="|AmodEq->pr_string"%="|AandEq->pr_string"&="|AorEq->pr_string"|="|AxorEq->pr_string"^="|AshiftLEq->pr_string"<<="|AshiftREq->pr_string">>="|ApowEq->pr_string"**="|AfdivEq->pr_string"//="andpr_bop=function|Bmul->pr_string"*"|Bdiv->pr_string"/"|Bfdiv->pr_string"//"|Bmod->pr_string"%"|Badd->pr_string"+"|Bsub->pr_string"-"|BshiftL->pr_string"<<"|BshiftR->pr_string">>"|Beq->pr_string"=="|Bneq->pr_string"!="|Blt->pr_string"<"|Bgt->pr_string">"|Ble->pr_string"<="|Bge->pr_string">="|BbitAnd->pr_string"&"|BbitOr->pr_string"|"|BbitXor->pr_string"^"|Band->pr_string" and "|Bor->pr_string" or "|Bis->pr_string" is "|BisNot->pr_string" is not "|Bin->pr_string" in "|BnotIn->pr_string" not in "andpr_uop=function|Upositive->pr_string"+"|Unegative->pr_string"-"|Ucomplement->pr_string"~"|Unot->pr_string"not "