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 ();
|
NextTok ();
|
||||||
break;
|
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:
|
case TOK_PLUS:
|
||||||
NextTok ();
|
NextTok ();
|
||||||
N = Factor ();
|
N = Factor ();
|
||||||
@@ -1159,7 +1171,7 @@ static ExprNode* Factor (void)
|
|||||||
|
|
||||||
case TOK_LPAREN:
|
case TOK_LPAREN:
|
||||||
NextTok ();
|
NextTok ();
|
||||||
N = Expr0 ();
|
N = Expr1 ();
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
break;
|
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)
|
ExprNode* Expression (void)
|
||||||
/* Evaluate an expression, build the expression tree on the heap and return
|
/* Evaluate an expression, build the expression tree on the heap and return
|
||||||
** a pointer to the root of the tree.
|
** 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