2025-01-22 16:18:30 +01:00
/ *
* Copyright ( C ) 2005 - 2019 Haxe Foundation
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " S o f t w a r e " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , s u b j e c t t o t h e f o l l o w i n g c o n d i t i o n s :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " A S I S " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
* /
package haxe . macro ;
import haxe . macro . Expr ;
using Lambda ;
using StringTools ;
/ * *
This class p r o v i d e s s o m e u t i l i t y m e t h o d s t o c o n v e r t e l e m e n t s f r o m t h e
macro context to a human - readable String representation .
* /
class Printer {
var tabs: String ;
var tabString: String ;
public function n e w ( ? tabString = " \t " ) {
tabs = " " ;
this . tabString = tabString ;
}
public function printUnop ( op : Unop )
return switch ( op ) {
c ase OpIncrement : " + + " ;
c ase OpDecrement : " - - " ;
c ase OpNot : " ! " ;
c ase OpNeg : " - " ;
c ase OpNegBits : " ~ " ;
c ase OpSpread : " . . . " ;
}
public function printBinop ( op : Binop )
return switch ( op ) {
c ase OpAdd : " + " ;
c ase OpMult : " * " ;
c ase OpDiv : " / " ;
c ase OpSub : " - " ;
c ase OpAssign : " = " ;
c ase OpEq : " = = " ;
c ase OpNotEq : " ! = " ;
c ase OpGt : " > " ;
c ase OpGte : " > = " ;
c ase OpLt : " < " ;
c ase OpLte : " < = " ;
c ase OpAnd : " & " ;
c ase OpOr : " | " ;
c ase OpXor : " ^ " ;
c ase OpBoolAnd : " & & " ;
c ase OpBoolOr : " | | " ;
c ase OpShl : " < < " ;
c ase OpShr : " > > " ;
c ase OpUShr : " > > > " ;
c ase OpMod : " % " ;
c ase OpInterval : " . . . " ;
c ase OpArrow : " = > " ;
c ase OpIn : " i n " ;
2026-05-21 23:40:20 -07:00
c ase OpNullCoal : " ? ? " ;
2025-01-22 16:18:30 +01:00
c ase OpAssignOp ( op ) :
printBinop ( op ) + " = " ;
}
function escapeString ( s : String , delim : String ) {
return delim
2026-05-21 23:40:20 -07:00
+ s . replace ( ' \\ ' , ' \\ \\ ' )
. replace ( " \n " , " \\ n " )
2025-01-22 16:18:30 +01:00
. replace ( " \t " , " \\ t " )
. replace ( " \r " , " \\ r " )
. replace ( " ' " , " \\ ' " )
. replace ( ' " ' , " \\ \" " ) #if sys . replace ( " \x 0 0 " , " \\ x 0 0 " ) #end + delim ;
}
public function printFormatString ( s : String ) {
return escapeString ( s , " ' " ) ;
}
public function printString ( s : String ) {
return escapeString ( s , ' " ' ) ;
}
public function printConstant ( c : Constant )
return switch ( c ) {
c ase CString ( s , SingleQuotes ) : printFormatString ( s ) ;
c ase CString ( s , _ ) : printString ( s ) ;
2026-05-21 23:40:20 -07:00
c ase CIdent ( s ) , CInt ( s , null ) , CFloat ( s , null ) :
2025-01-22 16:18:30 +01:00
s ;
2026-05-21 23:40:20 -07:00
c ase CInt ( s , suffix ) , CFloat ( s , suffix ) :
s + suffix ;
2025-01-22 16:18:30 +01:00
c ase CRegexp ( s , opt ) : ' ~ / $ s / $ opt ' ;
}
public function printTypeParam ( param : TypeParam )
return switch ( param ) {
c ase TPType ( ct ) : printComplexType ( ct ) ;
c ase TPExpr ( e ) : printExpr ( e ) ;
}
public function printTypePath ( tp : TypePath )
return ( tp . pack . length > 0 ? tp . pack . join ( " . " ) + " . " : " " )
+ tp . name
+ ( tp . sub != null ? ' . ${ tp . sub } ' : " " )
+ ( tp . params == null ? " " : tp . params . length > 0 ? " < " + tp . params . map ( printTypeParam ) . join ( " , " ) + " > " : " " ) ;
// TODO: check if this can cause loops
public function printComplexType ( ct : ComplexType )
return switch ( ct ) {
c ase TPath ( tp ) : printTypePath ( tp ) ;
c ase TFunction ( args , ret ) :
var wrapArgumentsInParentheses = switch args {
// type `:(a:X) -> Y` has args as [TParent(TNamed(...))], i.e `a:X` gets wrapped in `TParent()`. We don't add parentheses to avoid printing `:((a:X)) -> Y`
c ase [ TParent ( t ) ] : false ;
// this case catches a single argument that's a type-path, so that `X -> Y` prints `X -> Y` not `(X) -> Y`
c ase [ TPath ( _ ) | TOptional ( TPath ( _ ) ) ] : false ;
d efault : true ;
}
var argStr = args . map ( printComplexType ) . join ( " , " ) ;
( wrapArgumentsInParentheses ? ' ( $ argStr ) ' : argStr ) + " - > " + ( switch ret {
// wrap return type in parentheses if it's also a function
c ase TFunction ( _ ) : ' ( ${ printComplexType ( ret ) } ) ' ;
d efault : ( printComplexType ( ret ) : String ) ;
} ) ;
c ase TAnonymous ( fields ) : " { " + [ for ( f in fields ) printField ( f ) + " ; " ] . join ( " " ) + " } " ;
c ase TParent ( ct ) : " ( " + printComplexType ( ct ) + " ) " ;
c ase TOptional ( ct ) : " ? " + printComplexType ( ct ) ;
c ase TNamed ( n , ct ) : n + " : " + printComplexType ( ct ) ;
c ase TExtend ( tpl , fields ) :
var types = [ for ( t in tpl ) " > " + printTypePath ( t ) + " , " ] . join ( " " ) ;
var fields = [ for ( f in fields ) printField ( f ) + " ; " ] . join ( " " ) ;
' { ${ types } ${ fields } } ' ;
c ase TIntersection ( tl ) : tl . map ( printComplexType ) . join ( " & " ) ;
}
public function printMetadata ( meta : MetadataEntry )
return ' @ ${ meta . name } ' + ( ( meta . params != null && meta . params . length > 0 ) ? ' ( ${ printExprs ( meta . params , " , " ) } ) ' : " " ) ;
public function printAccess ( access : Access )
return switch ( access ) {
c ase AStatic : " s t a t i c " ;
c ase APublic : " p u b l i c " ;
c ase APrivate : " p r i v a t e " ;
c ase AOverride : " o v e r r i d e " ;
c ase AInline : " i n l i n e " ;
c ase ADynamic : " d y n a m i c " ;
c ase AMacro : " m a c r o " ;
c ase AFinal : " f i n a l " ;
c ase AExtern : " e x t e r n " ;
c ase AAbstract : " a b s t r a c t " ;
c ase AOverload : " o v e r l o a d " ;
}
public function printField ( field : Field ) {
inline function orderAccess ( access : Array < Access > ) {
// final should always be printed last
// (does not modify input array)
return access . has ( AFinal ) ? access . filter ( a - > ! a . match ( AFinal ) ) . concat ( [ AFinal ] ) : access ;
}
return ( field . doc != null
& & field . doc != " " ? " / * * \n "
+ tabs
+ tabString
+ StringTools . replace ( field . doc , " \n " , " \n " + tabs + tabString )
+ " \n "
+ tabs
+ " * * / \n "
+ tabs : " " )
+ ( field . meta != null && field . meta . length > 0 ? field . meta . map ( printMetadata ) . join ( ' \n $ tabs ' ) + ' \n $ tabs ' : " " )
+ ( field . access != null && field . access . length > 0 ? orderAccess ( field . access ) . map ( printAccess ) . join ( " " ) + " " : " " )
+ switch ( field . kind ) {
c ase FVar ( t , eo ) : ( ( field . access != null && field . access . has ( AFinal ) ) ? ' ' : ' v a r ' ) + ' ${ field . name } ' + opt ( t , printComplexType , " : " ) + opt ( eo , printExpr , " = " ) ;
c ase FProp ( get , set , t , eo ) : ' v a r ${ field . name } ( $ get , $ set ) ' + opt ( t , printComplexType , " : " ) + opt ( eo , printExpr , " = " ) ;
c ase FFun ( func ) : ' f u n c t i o n ${ field . name } ' + printFunction ( func ) ;
}
}
public function printTypeParamDecl ( tpd : TypeParamDecl )
return ( tpd . meta != null && tpd . meta . length > 0 ? tpd . meta . map ( printMetadata ) . join ( " " ) + " " : " " )
+ tpd . name
+ ( tpd . params != null && tpd . params . length > 0 ? " < " + tpd . params . map ( printTypeParamDecl ) . join ( " , " ) + " > " : " " )
2026-05-21 23:40:20 -07:00
+ ( tpd . constraints != null && tpd . constraints . length > 0 ? " : ( " + tpd . constraints . map ( printComplexType ) . join ( " , " ) + " ) " : " " )
+ ( tpd . defaultType != null ? " = " + printComplexType ( tpd . defaultType ) : " " ) ;
2025-01-22 16:18:30 +01:00
public function printFunctionArg ( arg : FunctionArg )
return ( arg . opt ? " ? " : " " ) + arg . name + opt ( arg . type , printComplexType , " : " ) + opt ( arg . value , printExpr , " = " ) ;
public function printFunction ( func : Function , ? kind : FunctionKind ) {
var skipParentheses = switch func . args {
c ase [ { type : null } ] : kind == FArrow ;
c ase _ : false ;
}
return ( func . params == null ? " " : func . params . length > 0 ? " < " + func . params . map ( printTypeParamDecl ) . join ( " , " ) + " > " : " " )
+ ( skipParentheses ? " " : " ( " )
+ func . args . map ( printFunctionArg ) . join ( " , " )
+ ( skipParentheses ? " " : " ) " )
+ ( kind == FArrow ? " - > " : " " )
+ opt ( func . ret , printComplexType , " : " )
+ opt ( func . expr , printExpr , " " ) ;
}
public function printVar ( v : Var ) {
var s = v . name + opt ( v . type , printComplexType , " : " ) + opt ( v . expr , printExpr , " = " ) ;
return switch v . meta {
c ase null | [ ] : s ;
c ase meta : meta . map ( printMetadata ) . join ( " " ) + " " + s ;
}
}
public function printObjectFieldKey ( of : ObjectField ) {
return switch ( of . quotes ) {
c ase null | Unquoted : of . field ;
c ase Quoted : ' " ${ of . field } " ' ; // TODO: Have to escape that?
}
}
public function printObjectField ( of : ObjectField ) {
return ' ${ printObjectFieldKey ( of ) } : ${ printExpr ( of . expr ) } ' ;
}
public function printExpr ( e : Expr )
return e == null ? " # N U L L " : switch ( e . expr ) {
c ase EConst ( c ) : printConstant ( c ) ;
c ase EArray ( e1 , e2 ) : ' ${ printExpr ( e1 ) } [ ${ printExpr ( e2 ) } ] ' ;
c ase EBinop ( op , e1 , e2 ) : ' ${ printExpr ( e1 ) } ${ printBinop ( op ) } ${ printExpr ( e2 ) } ' ;
2026-05-21 23:40:20 -07:00
c ase EField ( e1 , n , kind ) : kind == Safe ? ' ${ printExpr ( e1 ) } ? . $ n ' : ' ${ printExpr ( e1 ) } . $ n ' ;
2025-01-22 16:18:30 +01:00
c ase EParenthesis ( e1 ) : ' ( ${ printExpr ( e1 ) } ) ' ;
c ase EObjectDecl ( fl ) :
" { " + fl . map ( function ( fld ) return printObjectField ( fld ) ) . join ( " , " ) + " } " ;
c ase EArrayDecl ( el ) : ' [ ${ printExprs ( el , " , " ) } ] ' ;
c ase ECall ( e1 , el ) : ' ${ printExpr ( e1 ) } ( ${ printExprs ( el , " , " ) } ) ' ;
c ase ENew ( tp , el ) : ' n e w ${ printTypePath ( tp ) } ( ${ printExprs ( el , " , " ) } ) ' ;
c ase EUnop ( op , true , e1 ) : printExpr ( e1 ) + printUnop ( op ) ;
c ase EUnop ( op , false , e1 ) : printUnop ( op ) + printExpr ( e1 ) ;
c ase EFunction ( FNamed ( no , inlined ) , func ) : ( inlined ? ' i n l i n e ' : ' ' ) + ' f u n c t i o n $ no ' + printFunction ( func ) ;
c ase EFunction ( kind , func ) : ( kind != FArrow ? " f u n c t i o n " : " " ) + printFunction ( func , kind ) ;
2026-05-21 23:40:20 -07:00
c ase EVars ( [ ] ) : " v a r " ;
c ase EVars ( vl ) : ( ( vl [ 0 ] . isStatic ) ? " s t a t i c " : " " ) + ( ( vl [ 0 ] . isFinal ) ? " f i n a l " : " v a r " ) + vl . map ( printVar ) . join ( " , " ) ;
2025-01-22 16:18:30 +01:00
c ase EBlock ( [ ] ) : ' { } ' ;
c ase EBlock ( el ) :
var old = tabs ;
tabs += tabString ;
var s = ' { \n $ tabs ' + printExprs ( el , ' ; \n $ tabs ' ) ;
tabs = old ;
s + ' ; \n $ tabs } ' ;
c ase EFor ( e1 , e2 ) : ' f o r ( ${ printExpr ( e1 ) } ) ${ printExpr ( e2 ) } ' ;
c ase EIf ( econd , eif , null ) : ' i f ( ${ printExpr ( econd ) } ) ${ printExpr ( eif ) } ' ;
c ase EIf ( econd , eif , eelse ) : ' i f ( ${ printExpr ( econd ) } ) ${ printExpr ( eif ) } e l s e ${ printExpr ( eelse ) } ' ;
c ase EWhile ( econd , e1 , true ) : ' w h i l e ( ${ printExpr ( econd ) } ) ${ printExpr ( e1 ) } ' ;
c ase EWhile ( econd , e1 , false ) : ' d o ${ printExpr ( e1 ) } w h i l e ( ${ printExpr ( econd ) } ) ' ;
c ase ESwitch ( e1 , cl , edef ) :
var old = tabs ;
tabs += tabString ;
var s = ' s w i t c h ${ printExpr ( e1 ) } { \n $ tabs '
+ cl . map ( function ( c ) return ' c a s e ${ printExprs ( c . values , " , " ) } ' + ( c . guard != null ? ' i f ( ${ printExpr ( c . guard ) } ) : ' : " : " )
+ ( c . expr != null ? ( opt ( c . expr , printExpr ) ) + " ; " : " " ) )
. join ( ' \n $ tabs ' ) ;
if ( edef != null )
s += ' \n ${ tabs } d e f a u l t : ' + ( edef . expr == null ? " " : printExpr ( edef ) + " ; " ) ;
tabs = old ;
s + ' \n $ tabs } ' ;
c ase ETry ( e1 , cl ) :
' t r y ${ printExpr ( e1 ) } ' + cl . map ( function ( c ) return ' c a t c h ( ${ c . name } ${ c . type == null ? ' ' : ( ' : ' + printComplexType ( c . type ) ) } ) ${ printExpr ( c . expr ) } ' ) . join ( " " ) ;
c ase EReturn ( eo ) : " r e t u r n " + opt ( eo , printExpr , " " ) ;
c ase EBreak : " b r e a k " ;
c ase EContinue : " c o n t i n u e " ;
c ase EUntyped ( e1 ) : " u n t y p e d " + printExpr ( e1 ) ;
c ase EThrow ( e1 ) : " t h r o w " + printExpr ( e1 ) ;
c ase ECast ( e1 , cto ) if ( cto != null ) : ' c a s t ( ${ printExpr ( e1 ) } , ${ printComplexType ( cto ) } ) ' ;
c ase ECast ( e1 , _ ) : " c a s t " + printExpr ( e1 ) ;
c ase EIs ( e1 , ct ) : ' ${ printExpr ( e1 ) } i s ${ printComplexType ( ct ) } ' ;
c ase EDisplay ( e1 , _ ) : ' # D I S P L A Y ( ${ printExpr ( e1 ) } ) ' ;
c ase ETernary ( econd , eif , eelse ) : ' ${ printExpr ( econd ) } ? ${ printExpr ( eif ) } : ${ printExpr ( eelse ) } ' ;
c ase ECheckType ( e1 , ct ) : ' ( ${ printExpr ( e1 ) } : ${ printComplexType ( ct ) } ) ' ;
c ase EMeta ( { name : " : i m p l i c i t R e t u r n " } , { expr : EReturn ( e1 ) } ) : printExpr ( e1 ) ;
c ase EMeta ( meta , e1 ) : printMetadata ( meta ) + " " + printExpr ( e1 ) ;
}
public function printExprs ( el : Array < Expr > , sep : String ) {
return el . map ( printExpr ) . join ( sep ) ;
}
function printExtension ( tpl : Array < TypePath > , fields : Array < Field > ) {
return ' { \n $ tabs > '
+ tpl . map ( printTypePath ) . join ( ' , \n $ tabs > ' )
+ " , "
+ ( fields . length > 0 ? ( ' \n $ tabs ' + fields . map ( printField ) . join ( ' ; \n $ tabs ' ) + " ; \n } " ) : ( " \n } " ) ) ;
}
function printStructure ( fields : Array < Field > ) {
return fields . length == 0 ? " { } " : ' { \n $ tabs ' + fields . map ( printField ) . join ( ' ; \n $ tabs ' ) + " ; \n } " ;
}
public function printTypeDefinition ( t : TypeDefinition , printPackage = true ) : String {
var old = tabs ;
tabs = tabString ;
var str = t == null ? " # N U L L " : ( printPackage && t . pack . length > 0 && t . pack [ 0 ] != " " ? " p a c k a g e " + t . pack . join ( " . " ) + " ; \n " : " " )
+ ( t . doc != null && t . doc != " " ? " / * * \n " + tabString + StringTools . replace ( t . doc , " \n " , " \n " + tabString ) + " \n * * / \n " : " " )
+ ( t . meta != null && t . meta . length > 0 ? t . meta . map ( printMetadata ) . join ( " " ) + " " : " " )
+ ( t . isExtern ? " e x t e r n " : " " )
+ switch ( t . kind ) {
c ase TDEnum :
" e n u m "
+ t . name
+ ( ( t . params != null && t . params . length > 0 ) ? " < " + t . params . map ( printTypeParamDecl ) . join ( " , " ) + " > " : " " )
+ " { \n "
+ [
for ( field in t . fields )
tabs
+ ( field . doc != null
& & field . doc != " " ? " / * * \n "
+ tabs
+ tabString
+ StringTools . replace ( field . doc , " \n " , " \n " + tabs + tabString )
+ " \n "
+ tabs
+ " * * / \n "
+ tabs : " " )
+ ( field . meta != null && field . meta . length > 0 ? field . meta . map ( printMetadata ) . join ( " " ) + " " : " " )
+ ( switch ( field . kind ) {
c ase FVar ( t , _ ) : field . name + opt ( t , printComplexType , " : " ) ;
c ase FProp ( _ , _ , _ , _ ) : throw " F P r o p i s i n v a l i d f o r T D E n u m . " ;
c ase FFun ( func ) : field . name + printFunction ( func ) ;
} )
+ " ; " ] . join ( " \n " )
+ " \n } " ;
c ase TDStructure :
" t y p e d e f "
+ t . name
+ ( ( t . params != null && t . params . length > 0 ) ? " < " + t . params . map ( printTypeParamDecl ) . join ( " , " ) + " > " : " " )
+ " = { \n "
+ [
for ( f in t . fields ) {
tabs + printField ( f ) + " ; " ;
}
] . join ( " \n " )
+ " \n } " ;
c ase TDClass ( superClass , interfaces , isInterface , isFinal , isAbstract ) :
( isFinal ? " f i n a l " : " " )
+ ( isAbstract ? " a b s t r a c t " : " " )
+ ( isInterface ? " i n t e r f a c e " : " c l a s s " )
+ t . name
+ ( t . params != null && t . params . length > 0 ? " < " + t . params . map ( printTypeParamDecl ) . join ( " , " ) + " > " : " " )
+ ( superClass != null ? " e x t e n d s " + printTypePath ( superClass ) : " " )
+ ( interfaces != null ? ( isInterface ? [ for ( tp in interfaces ) " e x t e n d s " + printTypePath ( tp ) ] : [
for ( tp in interfaces )
" i m p l e m e n t s " + printTypePath ( tp )
] ) . join ( " " ) : " " )
+ " { \n "
+ [
for ( f in t . fields ) {
tabs + printFieldWithDelimiter ( f ) ;
}
] . join ( " \n " )
+ " \n } " ;
c ase TDAlias ( ct ) :
" t y p e d e f "
+ t . name
+ ( ( t . params != null && t . params . length > 0 ) ? " < " + t . params . map ( printTypeParamDecl ) . join ( " , " ) + " > " : " " )
+ " = "
+ ( switch ( ct ) {
c ase TExtend ( tpl , fields ) : printExtension ( tpl , fields ) ;
c ase TAnonymous ( fields ) : printStructure ( fields ) ;
c ase _ : printComplexType ( ct ) ;
} )
+ " ; " ;
2026-05-21 23:40:20 -07:00
c ase TDAbstract ( tthis , tflags , from , to ) :
var from = from == null ? [ ] : from . copy ( ) ;
var to = to == null ? [ ] : to . copy ( ) ;
var isEnum = false ;
if ( tflags != null ) {
for ( flag in tflags ) {
switch ( flag ) {
c ase AbEnum : isEnum = true ;
c ase AbFrom ( ct ) : from . push ( ct ) ;
c ase AbTo ( ct ) : to . push ( ct ) ;
}
}
}
( isEnum ? " e n u m " : " " )
+ " a b s t r a c t "
2025-01-22 16:18:30 +01:00
+ t . name
+ ( ( t . params != null && t . params . length > 0 ) ? " < " + t . params . map ( printTypeParamDecl ) . join ( " , " ) + " > " : " " )
+ ( tthis == null ? " " : " ( " + printComplexType ( tthis ) + " ) " )
2026-05-21 23:40:20 -07:00
+ [ for ( f in from ) " f r o m " + printComplexType ( f ) ] . join ( " " )
+ [ for ( f in to ) " t o " + printComplexType ( f ) ] . join ( " " )
2025-01-22 16:18:30 +01:00
+ " { \n "
+ [
for ( f in t . fields ) {
tabs + printFieldWithDelimiter ( f ) ;
}
] . join ( " \n " )
+ " \n } " ;
c ase TDField ( kind , access ) :
tabs = old ;
( access != null && access . length > 0 ? access . map ( printAccess ) . join ( " " ) + " " : " " )
+ switch ( kind ) {
c ase FVar ( type , eo ) : ( ( access != null && access . has ( AFinal ) ) ? ' ' : ' v a r ' ) + ' ${ t . name } ' + opt ( type , printComplexType , " : " ) + opt ( eo , printExpr , " = " ) + " ; " ;
c ase FProp ( get , set , type , eo ) : ' v a r ${ t . name } ( $ get , $ set ) ' + opt ( type , printComplexType , " : " ) + opt ( eo , printExpr , " = " ) + " ; " ;
c ase FFun ( func ) : ' f u n c t i o n ${ t . name } ' + printFunction ( func ) + switch func . expr { case { expr : EBlock ( _ ) } : " " ; case _ : " ; " ; } ;
}
} tabs = old ;
return str ;
}
function printFieldWithDelimiter ( f : Field ) : String {
return printField ( f ) + switch ( f . kind ) {
c ase FVar ( _ , _ ) , FProp ( _ , _ , _ , _ ) : " ; " ;
c ase FFun ( { expr : null } ) : " ; " ;
c ase FFun ( { expr : { expr : EBlock ( _ ) } } ) : " " ;
c ase FFun ( _ ) : " ; " ;
c ase _ : " " ;
} ;
}
function opt < T > ( v : T , f : T -> String , prefix = " " )
return v == null ? " " : ( prefix + f ( v ) ) ;
public function printExprWithPositions ( e : Expr ) {
var buffer = new StringBuf ( ) ;
function format4 ( i : Int ) {
return StringTools . lpad ( Std . string ( i ) , " " , 4 ) ;
}
function loop ( tabs : String , e : Expr ) {
function add ( s : String , ? p = null ) {
if ( p == null ) {
p = e . pos ;
}
var p = #if macro haxe . macro . Context . getPosInfos ( p ) #else e . pos #end ;
buffer . add ( ' ${ format4 ( p . min ) } - ${ format4 ( p . max ) } $ tabs $ s \n ' ) ;
}
function loopI ( e : Expr )
loop ( tabs + tabString , e ) ;
switch ( e . expr ) {
c ase EConst ( c ) :
add ( printConstant ( c ) ) ;
c ase EArray ( e1 , e2 ) :
add ( " E A r r a y " ) ;
loopI ( e1 ) ;
loopI ( e2 ) ;
c ase EBinop ( op , e1 , e2 ) :
add ( " E B i n o p " + printBinop ( op ) ) ;
loopI ( e1 ) ;
loopI ( e2 ) ;
2026-05-21 23:40:20 -07:00
c ase EField ( e , field , kind ) :
if ( kind == null ) kind = Normal ;
add ( ' E F i e l d $ field ( ${ kind . getName ( ) } ) ' ) ;
2025-01-22 16:18:30 +01:00
loopI ( e ) ;
c ase EParenthesis ( e ) :
add ( " E P a r e n t h e s i s " ) ;
loopI ( e ) ;
c ase EObjectDecl ( fields ) :
add ( " E O b j e c t D e c l " ) ;
for ( field in fields ) {
add ( field . field ) ; // TODO: we don't have the field pos?
loopI ( field . expr ) ;
}
c ase EArrayDecl ( values ) :
add ( " E A r r a y D e c l " ) ;
values . iter ( loopI ) ;
c ase ECall ( e , params ) :
add ( " E C a l l " ) ;
loopI ( e ) ;
params . iter ( loopI ) ;
c ase ENew ( tp , params ) :
add ( " E N e w " + printTypePath ( tp ) ) ;
params . iter ( loopI ) ;
c ase EUnop ( op , postFix , e ) :
add ( " E U n o p " + printUnop ( op ) ) ;
loopI ( e ) ;
c ase EVars ( vars ) :
add ( " E V a r s " ) ;
for ( v in vars ) {
if ( v . expr != null ) {
add ( v . name ) ;
loopI ( v . expr ) ;
}
}
c ase EFunction ( _ , f ) :
add ( " E F u n c t i o n " ) ;
if ( f . expr != null ) {
loopI ( f . expr ) ;
}
c ase EBlock ( exprs ) :
add ( " E B l o c k " ) ;
exprs . iter ( loopI ) ;
c ase EFor ( it , expr ) :
add ( " E F o r " ) ;
loopI ( it ) ;
loopI ( expr ) ;
c ase EIf ( econd , eif , eelse ) :
add ( " E I f " ) ;
loopI ( econd ) ;
loopI ( eif ) ;
if ( eelse != null ) {
loopI ( eelse ) ;
}
c ase EWhile ( econd , e , normalWhile ) :
add ( " E W h i l e " ) ;
loopI ( econd ) ;
loopI ( e ) ;
c ase ESwitch ( e , cases , edef ) :
add ( " E S w i t c h " ) ;
loopI ( e ) ;
for ( c in cases ) {
for ( pat in c . values ) {
loop ( tabs + tabString + tabString , pat ) ;
}
if ( c . expr != null ) {
loop ( tabs + tabString + tabString + tabString , c . expr ) ;
}
}
if ( edef != null ) {
loop ( tabs + tabString + tabString + tabString , edef ) ;
}
c ase ETry ( e , catches ) :
add ( " E T r y " ) ;
loopI ( e ) ;
for ( c in catches ) {
loop ( tabs + tabString + tabString , c . expr ) ;
}
c ase EReturn ( e ) :
add ( " E R e t u r n " ) ;
if ( e != null ) {
loopI ( e ) ;
}
c ase EBreak :
add ( " E B r e a k " ) ;
c ase EContinue :
add ( " E C o n t i n u e " ) ;
c ase EUntyped ( e ) :
add ( " E U n t y p e d " ) ;
loopI ( e ) ;
c ase EThrow ( e ) :
add ( " E T h r o w " ) ;
loopI ( e ) ;
c ase ECast ( e , t ) :
add ( " E C a s t " ) ;
loopI ( e ) ;
c ase EIs ( e , t ) :
add ( " E I s " ) ;
loopI ( e ) ;
c ase EDisplay ( e , displayKind ) :
add ( " E D i s p l a y " ) ;
loopI ( e ) ;
c ase ETernary ( econd , eif , eelse ) :
add ( " E T e r n a r y " ) ;
loopI ( econd ) ;
loopI ( eif ) ;
loopI ( eelse ) ;
c ase ECheckType ( e , t ) :
add ( " E C h e c k T y p e " ) ;
loopI ( e ) ;
c ase EMeta ( s , e ) :
add ( " E M e t a " + printMetadata ( s ) ) ;
loopI ( e ) ;
}
}
loop ( " " , e ) ;
return buffer . toString ( ) ;
}
}