Skip to content

Commit

Permalink
Improve printing of nested expressions
Browse files Browse the repository at this point in the history
Specifically, make it better at eliding redundant parenthesis. We
do so by changing the code so that the PrintPrecedence is reset to
0 whenever a expression is print that is not a unary or binary op,
and then restored afterwards. For "leave" expressions such as
integer literals this has no effect. But for expression that can
have further subexpressions, such as function expressions, list
expression, permutation expressions etc., this allows us to avoid
redundant parenthesis.
  • Loading branch information
fingolfin committed Jan 27, 2025
1 parent c026978 commit 1a04cec
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 43 deletions.
80 changes: 38 additions & 42 deletions src/exprs.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,37 @@
#include "hpc/aobjects.h"
#endif

struct ExprsState {

/****************************************************************************
**
*V PrintPrecedence . . . . . . . . . . . . . . . . current precedence level
**
** 'PrintPrecedence' contains the current precedence level, i.e., an integer
** indicating the binding power of the currently printed operator. If one of
** the operands is an operation that has lower binding power it is printed
** in parenthesis. If the right operand has the same binding power it is put
** in parenthesis, since all the operations are left associative.
** Precedence: 14: ^; 12: mod,/,*; 10: -,+; 8: in,=; 6: not; 4: and; 2: or.
** This sometimes puts in superfluous parenthesis: 2 * f( (3 + 4) ), since it
** doesn't know that a function call adds automatically parenthesis.
*/
UInt PrintPrecedence;

UInt OldPrintPrecedence;

};

static ModuleStateOffset ExprsStateOffset = -1;

extern inline struct ExprsState * ExprsState(void)
{
return (struct ExprsState *)StateSlotsAtOffset(ExprsStateOffset);
}

#define PrintPrecedence ExprsState()->PrintPrecedence
#define OldPrintPrecedence ExprsState()->OldPrintPrecedence

/****************************************************************************
**
*V EvalExprFuncs[<type>] . . . . . evaluator for expressions of type <type>
Expand Down Expand Up @@ -1224,7 +1255,10 @@ void InstallPrintExprFunc(unsigned int pos, PrintExprFunc f)
*/
void PrintExpr(Expr expr)
{
UInt oldPrec = OldPrintPrecedence = PrintPrecedence;
PrintPrecedence = 0;
(*PrintExprFuncs[TNUM_EXPR(expr)])(expr);
PrintPrecedence = oldPrec;
}


Expand All @@ -1244,34 +1278,6 @@ static void PrintUnknownExpr(Expr expr)
}


struct ExprsState {

/****************************************************************************
**
*V PrintPrecedence . . . . . . . . . . . . . . . . current precedence level
**
** 'PrintPrecedence' contains the current precedence level, i.e., an integer
** indicating the binding power of the currently printed operator. If one of
** the operands is an operation that has lower binding power it is printed
** in parenthesis. If the right operand has the same binding power it is put
** in parenthesis, since all the operations are left associative.
** Precedence: 14: ^; 12: mod,/,*; 10: -,+; 8: in,=; 6: not; 4: and; 2: or.
** This sometimes puts in superfluous parenthesis: 2 * f( (3 + 4) ), since it
** doesn't know that a function call adds automatically parenthesis.
*/
UInt PrintPrecedence;

};

static ModuleStateOffset ExprsStateOffset = -1;

extern inline struct ExprsState * ExprsState(void)
{
return (struct ExprsState *)StateSlotsAtOffset(ExprsStateOffset);
}

#define PrintPrecedence ExprsState()->PrintPrecedence

/****************************************************************************
**
*F PrintNot(<expr>) . . . . . . . . . . . . . print a boolean not operator
Expand All @@ -1280,9 +1286,7 @@ extern inline struct ExprsState * ExprsState(void)
*/
static void PrintNot(Expr expr)
{
UInt oldPrec;

oldPrec = PrintPrecedence;
UInt oldPrec = OldPrintPrecedence;
PrintPrecedence = 6;

// if necessary print the opening parenthesis
Expand All @@ -1296,8 +1300,6 @@ static void PrintNot(Expr expr)
// if necessary print the closing parenthesis
if ( oldPrec >= PrintPrecedence ) Pr("%2<)", 0, 0);
else Pr("%2<", 0, 0);

PrintPrecedence = oldPrec;
}


Expand All @@ -1310,9 +1312,7 @@ static void PrintNot(Expr expr)
*/
static void PrintAInv(Expr expr)
{
UInt oldPrec;

oldPrec = PrintPrecedence;
UInt oldPrec = OldPrintPrecedence;
PrintPrecedence = 11;

// if necessary print the opening parenthesis
Expand All @@ -1332,11 +1332,10 @@ static void PrintAInv(Expr expr)

static void PrintBinop(Expr expr)
{
UInt oldPrec; // old precedence level
const Char * op; // operand
BOOL printEqPrec = FALSE; // Print() at equal precedence
// remember the current precedence level
oldPrec = PrintPrecedence;

UInt oldPrec = OldPrintPrecedence;

// select the new precedence level
switch ( TNUM_EXPR(expr) ) {
Expand Down Expand Up @@ -1396,9 +1395,6 @@ static void PrintBinop(Expr expr)
(oldPrec == PrintPrecedence && printEqPrec))
Pr("%2<)", 0, 0);
else Pr("%2<", 0, 0);

// restore the old precedence level
PrintPrecedence = oldPrec;
}


Expand Down
20 changes: 19 additions & 1 deletion tst/testinstall/kernel/exprs.tst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,25 @@ function ( x )
end
gap> Display( x -> 2 * f( 3 + 4 ));
function ( x )
return 2 * f( (3 + 4) );
return 2 * f( 3 + 4 );
end
gap> Display({}->1^(1,2,2*(4-1)));
function ( )
return 1 ^ (1,2,2 * (4 - 1));
end
gap> Display({}->1-[1-1]);
function ( )
return 1 - [ 1 - 1 ];
end
gap> Display(function ( )
> return 1 - function ( )
> return 1 - 1;
> end( );
> end);
function ( )
return 1 - function ( )
return 1 - 1;
end( );
end

# PrintTildeExpr, EvalTildeExpr
Expand Down

0 comments on commit 1a04cec

Please sign in to comment.