Skip to content

Commit b09729d

Browse files
authored
Merge pull request #942 from boriel-basic/fix/shr_and_shl_bool
fix: using SHL or SHR with boolean expressions
2 parents 9e08bd0 + 0b8dc9f commit b09729d

19 files changed

Lines changed: 168 additions & 67 deletions

File tree

src/arch/z80/visitor/translator_inst_visitor.py

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -52,31 +52,31 @@ def ic_aaddr(self, t1, t2) -> None:
5252
self.emit("aaddr", t1, t2)
5353

5454
def ic_abs(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
55-
self.emit("abs" + self.TSUFFIX(type_), t1, t2)
55+
self.emit(f"abs{self.TSUFFIX(type_)}", t1, t2)
5656

5757
def ic_add(self, type_: TYPE | sym.BASICTYPE, t1, t2, t3) -> None:
58-
self.emit("add" + self.TSUFFIX(type_), t1, t2, t3)
58+
self.emit(f"add{self.TSUFFIX(type_)}", t1, t2, t3)
5959

6060
def ic_aload(self, type_: TYPE | sym.BASICTYPE, t1, mangle: str) -> None:
61-
self.emit("aload" + self.TSUFFIX(type_), t1, mangle)
61+
self.emit(f"aload{self.TSUFFIX(type_)}", t1, mangle)
6262

6363
def ic_and(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
6464
self.emit(f"and{self._no_bool(type_)}", t, t1, t2)
6565

6666
def ic_astore(self, type_: TYPE | sym.BASICTYPE, addr: str, t) -> None:
67-
self.emit("astore" + self.TSUFFIX(type_), addr, t)
67+
self.emit(f"astore{self.TSUFFIX(type_)}", addr, t)
6868

6969
def ic_band(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
70-
self.emit("band" + self.TSUFFIX(type_), t, t1, t2)
70+
self.emit(f"band{self.TSUFFIX(type_)}", t, t1, t2)
7171

7272
def ic_bnot(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
73-
self.emit("bnot" + self.TSUFFIX(type_), t1, t2)
73+
self.emit(f"bnot{self.TSUFFIX(type_)}", t1, t2)
7474

7575
def ic_bor(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
76-
self.emit("bor" + self.TSUFFIX(type_), t, t1, t2)
76+
self.emit(f"bor{self.TSUFFIX(type_)}", t, t1, t2)
7777

7878
def ic_bxor(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
79-
self.emit("bxor" + self.TSUFFIX(type_), t, t1, t2)
79+
self.emit(f"bxor{self.TSUFFIX(type_)}", t, t1, t2)
8080

8181
def ic_call(self, label: str, num: int) -> None:
8282
self.emit("call", label, num)
@@ -91,7 +91,7 @@ def ic_deflabel(self, label: str, t) -> None:
9191
self.emit("deflabel", label, t)
9292

9393
def ic_div(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
94-
self.emit("div" + self.TSUFFIX(type_), t, t1, t2)
94+
self.emit(f"div{self.TSUFFIX(type_)}", t, t1, t2)
9595

9696
def ic_end(self, t) -> None:
9797
self.emit("end", t)
@@ -100,7 +100,7 @@ def ic_enter(self, arg) -> None:
100100
self.emit("enter", arg)
101101

102102
def ic_eq(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
103-
self.emit("eq" + self.TSUFFIX(type_), t, t1, t2)
103+
self.emit(f"eq{self.TSUFFIX(type_)}", t, t1, t2)
104104

105105
def ic_exchg(self) -> None:
106106
self.emit("exchg")
@@ -109,13 +109,13 @@ def ic_fparam(self, type_: TYPE | sym.BASICTYPE, t) -> None:
109109
self.emit(f"fparam{self._no_bool(type_)}", t)
110110

111111
def ic_fpload(self, type_: TYPE | sym.BASICTYPE, t, offset) -> None:
112-
self.emit("fpload" + self.TSUFFIX(type_), t, offset)
112+
self.emit(f"fpload{self.TSUFFIX(type_)}", t, offset)
113113

114114
def ic_ge(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
115-
self.emit("ge" + self.TSUFFIX(type_), t, t1, t2)
115+
self.emit(f"ge{self.TSUFFIX(type_)}", t, t1, t2)
116116

117117
def ic_gt(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
118-
self.emit("gt" + self.TSUFFIX(type_), t, t1, t2)
118+
self.emit(f"gt{self.TSUFFIX(type_)}", t, t1, t2)
119119

120120
def ic_in(self, t) -> None:
121121
self.emit("in", t)
@@ -142,7 +142,7 @@ def ic_larrd(self, offset, arg1, size, arg2, bound_ptrs) -> None:
142142
self.emit("larrd", offset, arg1, size, arg2, bound_ptrs)
143143

144144
def ic_le(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
145-
self.emit("le" + self.TSUFFIX(type_), t, t1, t2)
145+
self.emit(f"le{self.TSUFFIX(type_)}", t, t1, t2)
146146

147147
def ic_leave(self, convention: str) -> None:
148148
self.emit("leave", convention)
@@ -151,10 +151,10 @@ def ic_lenstr(self, t1, t2) -> None:
151151
self.emit("lenstr", t1, t2)
152152

153153
def ic_load(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
154-
self.emit("load" + self.TSUFFIX(type_), t1, t2)
154+
self.emit(f"load{self.TSUFFIX(type_)}", t1, t2)
155155

156156
def ic_lt(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
157-
self.emit("lt" + self.TSUFFIX(type_), t, t1, t2)
157+
self.emit(f"lt{self.TSUFFIX(type_)}", t, t1, t2)
158158

159159
def ic_lvard(self, offset, default_value: list) -> None:
160160
self.emit("lvard", offset, default_value)
@@ -166,16 +166,16 @@ def ic_memcopy(self, t1, t2, t3) -> None:
166166
self.emit("memcopy", t1, t2, t3)
167167

168168
def ic_mod(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
169-
self.emit("mod" + self.TSUFFIX(type_), t, t1, t2)
169+
self.emit(f"mod{self.TSUFFIX(type_)}", t, t1, t2)
170170

171171
def ic_mul(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
172-
self.emit("mul" + self.TSUFFIX(type_), t, t1, t2)
172+
self.emit(f"mul{self.TSUFFIX(type_)}", t, t1, t2)
173173

174174
def ic_ne(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
175-
self.emit("ne" + self.TSUFFIX(type_), t, t1, t2)
175+
self.emit(f"ne{self.TSUFFIX(type_)}", t, t1, t2)
176176

177177
def ic_neg(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
178-
self.emit("neg" + self.TSUFFIX(type_), t1, t2)
178+
self.emit(f"neg{self.TSUFFIX(type_)}", t1, t2)
179179

180180
def ic_nop(self) -> None:
181181
self.emit("nop")
@@ -186,9 +186,6 @@ def ic_not(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
186186
def ic_or(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
187187
self.emit(f"or{self._no_bool(type_)}", t, t1, t2)
188188

189-
def ic_org(self, type_: TYPE | sym.BASICTYPE) -> None:
190-
self.emit("org" + self.TSUFFIX(type_))
191-
192189
def ic_out(self, t1, t2) -> None:
193190
self.emit("out", t1, t2)
194191

@@ -199,40 +196,40 @@ def ic_paddr(self, t1, t2) -> None:
199196
self.emit("paddr", t1, t2)
200197

201198
def ic_paload(self, type_: TYPE | sym.BASICTYPE, t, offset: int) -> None:
202-
self.emit("paload" + self.TSUFFIX(type_), t, offset)
199+
self.emit(f"paload{self.TSUFFIX(type_)}", t, offset)
203200

204201
def ic_param(self, type_: TYPE | sym.BASICTYPE, t) -> None:
205-
self.emit("param" + self.TSUFFIX(type_), t)
202+
self.emit(f"param{self.TSUFFIX(type_)}", t)
206203

207204
def ic_pastore(self, type_: TYPE | sym.BASICTYPE, offset, t) -> None:
208-
self.emit("pastore" + self.TSUFFIX(type_), offset, t)
205+
self.emit(f"pastore{self.TSUFFIX(type_)}", offset, t)
209206

210207
def ic_pload(self, type_: TYPE | sym.BASICTYPE, t1, offset) -> None:
211-
self.emit("pload" + self.TSUFFIX(type_), t1, offset)
208+
self.emit(f"pload{self.TSUFFIX(type_)}", t1, offset)
212209

213210
def ic_pow(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
214-
self.emit("pow" + self.TSUFFIX(type_), t, t1, t2)
211+
self.emit(f"pow{self.TSUFFIX(type_)}", t, t1, t2)
215212

216213
def ic_pstore(self, type_: TYPE | sym.BASICTYPE, offset, t) -> None:
217-
self.emit("pstore" + self.TSUFFIX(type_), offset, t)
214+
self.emit(f"pstore{self.TSUFFIX(type_)}", offset, t)
218215

219216
def ic_ret(self, type_: TYPE | sym.BASICTYPE, t, addr) -> None:
220-
self.emit("ret" + self.TSUFFIX(type_), t, addr)
217+
self.emit(f"ret{self.TSUFFIX(type_)}", t, addr)
221218

222219
def ic_return(self, addr) -> None:
223220
self.emit("ret", addr)
224221

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

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

231228
def ic_store(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
232-
self.emit("store" + self.TSUFFIX(type_), t1, t2)
229+
self.emit(f"store{self.TSUFFIX(type_)}", t1, t2)
233230

234231
def ic_sub(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
235-
self.emit("sub" + self.TSUFFIX(type_), t, t1, t2)
232+
self.emit(f"sub{self.TSUFFIX(type_)}", t, t1, t2)
236233

237234
def ic_var(self, name: str, size_) -> None:
238235
self.emit("var", name, size_)

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/divu8.asm

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ _b:
5151
ld hl, (_a - 1)
5252
call .core.__DIVU8_FAST
5353
ld (_b), a
54+
ld hl, (_a - 1)
55+
ld a, (_a)
56+
sub h
57+
sub 1
58+
sbc a, a
59+
neg
60+
push af
61+
ld hl, (_a - 1)
62+
ld a, (_a)
63+
sub h
64+
sub 1
65+
sbc a, a
66+
neg
67+
ld h, a
68+
pop af
69+
call .core.__DIVU8_FAST
70+
ld (_b), a
5471
ld hl, 0
5572
ld b, h
5673
ld c, l
@@ -66,7 +83,7 @@ _b:
6683
ei
6784
ret
6885
;; --- end of user code ---
69-
#line 1 "/zxbasic/src/arch/zx48k/library-asm/div8.asm"
86+
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm"
7087
; --------------------------------
7188
push namespace core
7289
__DIVU8: ; 8 bit unsigned integer division
@@ -131,5 +148,5 @@ __MODI8_FAST: ; __FASTCALL__ entry
131148
ld a, l ; remainder
132149
ret ; a = Modulus
133150
pop namespace
134-
#line 44 "divu8.bas"
151+
#line 61 "arch/zx48k/divu8.bas"
135152
END

tests/functional/arch/zx48k/divu8.bas

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ b = 1 / a
1111
b = 2 / a
1212
b = 4 / a
1313
b = a / a
14+
b = (a = a) / (a = a)
15+

tests/functional/arch/zx48k/mul8.asm

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ _b:
5252
ld a, (_a)
5353
call .core.__MUL8_FAST
5454
ld (_b), a
55+
ld hl, (_a - 1)
56+
ld a, (_a)
57+
sub h
58+
sub 1
59+
sbc a, a
60+
neg
61+
push af
62+
ld hl, (_a - 1)
63+
ld a, (_a)
64+
sub h
65+
sub 1
66+
sbc a, a
67+
neg
68+
ld h, a
69+
pop af
70+
call .core.__MUL8_FAST
71+
ld (_b), a
5572
ld hl, 0
5673
ld b, h
5774
ld c, l
@@ -67,7 +84,7 @@ _b:
6784
ei
6885
ret
6986
;; --- end of user code ---
70-
#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul8.asm"
87+
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul8.asm"
7188
push namespace core
7289
__MUL8: ; Performs 8bit x 8bit multiplication
7390
PROC
@@ -113,5 +130,5 @@ __MUL8B:
113130
ret ; result = HL
114131
ENDP
115132
pop namespace
116-
#line 45 "mul8.bas"
133+
#line 62 "arch/zx48k/mul8.bas"
117134
END

tests/functional/arch/zx48k/mul8.bas

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ b = 1 * a
1212
b = 2 * a
1313
b = 4 * a
1414
b = a * a
15+
b = (a = a) * (a = a)
16+

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

0 commit comments

Comments
 (0)