Skip to content

Commit c0c14c6

Browse files
committed
fix: using SHL or SHR with boolean expressions
Reverted last changes and uses a different approach, since doing something like (a = b) SHL 1 sometimes rendered wrong results (boolean not normalized).
1 parent 9e08bd0 commit c0c14c6

13 files changed

Lines changed: 78 additions & 31 deletions

File tree

src/arch/z80/visitor/translator_inst_visitor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,10 @@ def ic_return(self, addr) -> None:
223223
self.emit("ret", addr)
224224

225225
def ic_shl(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
226-
self.emit(f"shl{self._no_bool(type_)}", t, t1, t2)
226+
self.emit(f"shl{self.TSUFFIX(type_)}", t, t1, t2)
227227

228228
def ic_shr(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
229-
self.emit(f"shr{self._no_bool(type_)}", t, t1, t2)
229+
self.emit(f"shr{self.TSUFFIX(type_)}", t, t1, t2)
230230

231231
def ic_store(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
232232
self.emit("store" + self.TSUFFIX(type_), t1, t2)

src/symbols/binary.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,31 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
7272
return None
7373

7474
a, b = left, right # short form names
75+
if operator in {
76+
"BAND",
77+
"BOR",
78+
"BXOR",
79+
"AND",
80+
"OR",
81+
"XOR",
82+
"MINUS",
83+
"MULT",
84+
"DIV",
85+
"SHL",
86+
"SHR",
87+
} and not check.is_numeric(a, b):
88+
errmsg.error(lineno, f"Operator {operator} cannot be used with strings")
89+
return None
90+
91+
if operator not in {"AND", "OR", "XOR"}:
92+
# Non-boolean operators use always numeric operands.
93+
# We ensure operands are correctly converted to 0|1 values if they're boolean
94+
if a.type_ == TYPE.boolean:
95+
a = SymbolTYPECAST.make_node(TYPE.ubyte, a, lineno)
96+
97+
if b.type_ == TYPE.boolean:
98+
b = SymbolTYPECAST.make_node(TYPE.ubyte, b, lineno)
99+
75100
# Check for constant non-numeric operations
76101
c_type = check.common_type(a, b) # Resulting operation type or None
77102
if TYPE.is_numeric(c_type): # there must be a common type for a and b
@@ -90,31 +115,13 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
90115
b = SymbolTYPECAST.make_node(c_type, b, lineno) # ensure type
91116
return SymbolCONSTEXPR(cls(operator, a, b, lineno, type_=type_, func=func), lineno=lineno)
92117

93-
if operator in {
94-
"BNOT",
95-
"BAND",
96-
"BOR",
97-
"BXOR",
98-
"NOT",
99-
"AND",
100-
"OR",
101-
"XOR",
102-
"MINUS",
103-
"MULT",
104-
"DIV",
105-
"SHL",
106-
"SHR",
107-
} and not check.is_numeric(a, b):
108-
errmsg.error(lineno, "Operator %s cannot be used with STRINGS" % operator)
109-
return None
110-
111118
if check.is_string(a, b) and func is not None: # Are they STRING Constants?
112119
if operator == "PLUS":
113120
return SymbolSTRING(func(a.value, b.value), lineno)
114121

115122
return SymbolNUMBER(int(func(a.text, b.text)), type_=TYPE.ubyte, lineno=lineno) # Convert to u8 (boolean)
116123

117-
if operator in ("BNOT", "BAND", "BOR", "BXOR"):
124+
if operator in {"BNOT", "BAND", "BOR", "BXOR"}:
118125
if TYPE.is_decimal(c_type):
119126
c_type = TYPE.long_
120127

@@ -129,7 +136,7 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
129136
return None
130137

131138
if type_ is None:
132-
if operator in ("LT", "GT", "EQ", "LE", "GE", "NE", "AND", "OR", "XOR", "NOT"):
139+
if operator in {"LT", "GT", "EQ", "LE", "GE", "NE", "AND", "OR", "XOR"}:
133140
type_ = TYPE.boolean
134141
else:
135142
type_ = c_type

tests/functional/arch/zx48k/add8.asm

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,23 @@ _b:
3838
ld a, (_a)
3939
add a, h
4040
ld (_b), a
41+
ld hl, (_a - 1)
42+
ld a, (_a)
43+
sub h
44+
sub 1
45+
sbc a, a
46+
neg
47+
push af
48+
ld hl, (_a - 1)
49+
ld a, (_a)
50+
sub h
51+
sub 1
52+
sbc a, a
53+
neg
54+
ld h, a
55+
pop af
56+
add a, h
57+
ld (_b), a
4158
ld hl, 0
4259
ld b, h
4360
ld c, l

tests/functional/arch/zx48k/add8.bas

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ b = a + 1
88
b = 0 + a
99
b = 1 + a
1010
b = a + a
11+
b = (a = a) + (a = a)
12+

tests/functional/arch/zx48k/shlu16.asm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ _b:
4646
ld de, (_a)
4747
ld hl, (_a)
4848
call .core.__EQ16
49+
sub 1
50+
sbc a, a
51+
inc a
4952
push af
5053
ld a, (_b)
5154
pop hl
@@ -100,5 +103,5 @@ __EQ16: ; Test if 16bit values HL == DE
100103
inc a
101104
ret
102105
pop namespace
103-
#line 68 "arch/zx48k/shlu16.bas"
106+
#line 71 "arch/zx48k/shlu16.bas"
104107
END

tests/functional/arch/zx48k/shlu32.asm

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ _b:
6060
ld hl, (_a)
6161
ld de, (_a + 2)
6262
call .core.__EQ32
63+
sub 1
64+
sbc a, a
65+
inc a
6366
push af
6467
ld a, (_b)
6568
pop hl
@@ -118,7 +121,7 @@ __SHL32: ; Left Logical Shift 32 bits
118121
rl d
119122
ret
120123
pop namespace
121-
#line 87 "arch/zx48k/shlu32.bas"
124+
#line 90 "arch/zx48k/shlu32.bas"
122125
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/eq32.asm"
123126
push namespace core
124127
__EQ32: ; Test if 32bit value HLDE equals top of the stack
@@ -144,5 +147,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack
144147
xor a
145148
ret
146149
pop namespace
147-
#line 88 "arch/zx48k/shlu32.bas"
150+
#line 91 "arch/zx48k/shlu32.bas"
148151
END

tests/functional/arch/zx48k/shlu8.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ _b:
4646
sub h
4747
sub 1
4848
sbc a, a
49+
neg
4950
push af
5051
ld a, (_b)
5152
pop hl

tests/functional/arch/zx48k/shri16.asm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ _b:
4848
ld de, (_a)
4949
ld hl, (_a)
5050
call .core.__EQ16
51+
sub 1
52+
sbc a, a
53+
inc a
5154
push af
5255
ld a, (_b)
5356
pop hl
@@ -103,5 +106,5 @@ __EQ16: ; Test if 16bit values HL == DE
103106
inc a
104107
ret
105108
pop namespace
106-
#line 71 "arch/zx48k/shri16.bas"
109+
#line 74 "arch/zx48k/shri16.bas"
107110
END

tests/functional/arch/zx48k/shri32.asm

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ _b:
6060
ld hl, (_a)
6161
ld de, (_a + 2)
6262
call .core.__EQ32
63+
sub 1
64+
sbc a, a
65+
inc a
6366
push af
6467
ld a, (_b)
6568
pop hl
@@ -122,7 +125,7 @@ __SHRA32: ; Right Arithmetical Shift 32 bits
122125
rr l
123126
ret
124127
pop namespace
125-
#line 91 "arch/zx48k/shri32.bas"
128+
#line 94 "arch/zx48k/shri32.bas"
126129
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/eq32.asm"
127130
push namespace core
128131
__EQ32: ; Test if 32bit value HLDE equals top of the stack
@@ -148,5 +151,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack
148151
xor a
149152
ret
150153
pop namespace
151-
#line 92 "arch/zx48k/shri32.bas"
154+
#line 95 "arch/zx48k/shri32.bas"
152155
END

tests/functional/arch/zx48k/shri8.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ _b:
4646
sub h
4747
sub 1
4848
sbc a, a
49+
neg
4950
push af
5051
ld a, (_b)
5152
pop hl

0 commit comments

Comments
 (0)