Merge pull request #2863 from kugelfuhr/kugelfuhr/fix-2859
Fix broken boolean not operator in ca65
This commit is contained in:
@@ -146,7 +146,7 @@ static void FreeExprNode (ExprNode* E)
|
||||
|
||||
|
||||
|
||||
static ExprNode* Expr0 (void);
|
||||
static ExprNode* Expr1 (void);
|
||||
|
||||
|
||||
|
||||
@@ -1106,6 +1106,18 @@ static ExprNode* Factor (void)
|
||||
NextTok ();
|
||||
break;
|
||||
|
||||
case TOK_BOOLNOT:
|
||||
NextTok ();
|
||||
L = Expr1 ();
|
||||
if (IsEasyConst (L, &Val)) {
|
||||
FreeExpr (L);
|
||||
N = GenLiteralExpr (!Val);
|
||||
} else {
|
||||
N = NewExprNode (EXPR_BOOLNOT);
|
||||
N->Left = L;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_PLUS:
|
||||
NextTok ();
|
||||
N = Factor ();
|
||||
@@ -1159,7 +1171,7 @@ static ExprNode* Factor (void)
|
||||
|
||||
case TOK_LPAREN:
|
||||
NextTok ();
|
||||
N = Expr0 ();
|
||||
N = Expr1 ();
|
||||
ConsumeRParen ();
|
||||
break;
|
||||
|
||||
@@ -1652,51 +1664,12 @@ static ExprNode* Expr1 (void)
|
||||
|
||||
|
||||
|
||||
static ExprNode* Expr0 (void)
|
||||
/* Boolean operators: NOT */
|
||||
{
|
||||
ExprNode* Root;
|
||||
|
||||
/* Handle booleans */
|
||||
if (CurTok.Tok == TOK_BOOLNOT) {
|
||||
|
||||
long Val;
|
||||
ExprNode* Left;
|
||||
|
||||
/* Skip the operator token */
|
||||
NextTok ();
|
||||
|
||||
/* Read the argument */
|
||||
Left = Expr0 ();
|
||||
|
||||
/* If the argument is const, evaluate it directly */
|
||||
if (IsEasyConst (Left, &Val)) {
|
||||
FreeExpr (Left);
|
||||
Root = GenLiteralExpr (!Val);
|
||||
} else {
|
||||
Root = NewExprNode (EXPR_BOOLNOT);
|
||||
Root->Left = Left;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Read left hand side */
|
||||
Root = Expr1 ();
|
||||
|
||||
}
|
||||
|
||||
/* Return the expression tree we've created */
|
||||
return Root;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExprNode* Expression (void)
|
||||
/* Evaluate an expression, build the expression tree on the heap and return
|
||||
** a pointer to the root of the tree.
|
||||
*/
|
||||
{
|
||||
return Expr0 ();
|
||||
return Expr1 ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
33
test/asm/val/bug2859.s
Normal file
33
test/asm/val/bug2859.s
Normal file
@@ -0,0 +1,33 @@
|
||||
; Tests for the bug reported in #2859. Boolean not had the correct precedence
|
||||
; (as specified in the docs) but worked only correctly at the start of a full
|
||||
; expression.
|
||||
|
||||
; This one assembles ok since ! is at the start
|
||||
.if !.defined(__DOCART__) && .defined(__C64__)
|
||||
.byte 1
|
||||
.endif
|
||||
|
||||
; This one assembles too since a parenthesis restarts a full expression
|
||||
.if .defined(__C64__) && (!.defined(__DOCART__))
|
||||
.byte 2
|
||||
.endif
|
||||
|
||||
; This one doesn't work since ! is somewhere in between
|
||||
.if .defined(__C64__) && !.defined(__DOCART__)
|
||||
.byte 3
|
||||
.endif
|
||||
|
||||
|
||||
.import _exit
|
||||
.export _main
|
||||
|
||||
|
||||
; The following code is an indirect test for the precedence of .not.
|
||||
; .not has the lowest precedence, so the expression that is loaded into A
|
||||
; evaluates to zero. This has of course to be changed when the precedence
|
||||
; of .not is changed.
|
||||
_main:
|
||||
lda #.not 0 + 1 ; Means: .not (0 + 1)
|
||||
ldx #0
|
||||
jmp _exit
|
||||
|
||||
Reference in New Issue
Block a user