jokinen@tucos.UUCP (Matti Jokinen) (05/17/88)
Description: If one or more tags are missing in a tagcase statement and
there is no others-arm, the compiler reports the error but does not list
the missing tags. It is often rather tedious to find out which tags are
missing.
Repeat-by: Run the following shell script:
cat > main.clu << 'EOF'
start_up = proc()
t = oneof[a,b: null]
x: t := t$make_a(nil)
tagcase x
tag a:
end
end start_up
EOF
clu main
Fix: The error message comes from the procedure c_tagcase in the
file ~CLU/cmp/cstmt2.clu. Replace it with the following code:
c_tagcase = proc (e: c_env, ts: tagstmt)
at: typespec := c_expr(e, ts.obj)
specs: fieldspeclist := c_oneof_specs(e, at)
except when abstract: c_tag_sugar(e, at, ts)
return
end
used: flaglist := c_tagarms(e, ts.arms, specs)
tagcase ts.others_
tag body (mb: body):
all_used: bool
for all_used in flaglist$elements(used) do
if ~all_used then break end
end
if all_used cand ~fieldspeclist$empty(specs)
then c_env$err1(e, "others arm not allowed - all selectors present")
end
c_body(e, mb)
tag none:
miss: as := as$new()
for i: int in fieldspeclist$indexes(specs) do
if ~ used[i]
then as$addh(miss, specs[i].sel) end
end
count: int := as$size(miss)
if count > 0
then message: as := as$["others arm required - ",
int$unparse(count),
" ",
"selectors",
" missing: "]
if count = 1
then message[4] := "selector" end
for i: int in as$indexes(miss) do
if i > 1
then as$addh(message, ", ") end
as$addh(message,miss[i]) end
c_env$err(e, qs$a2s(message))
end
end
end c_tagcase
If you want long lists to be folded on more than one line, replace the
procedure cenv$output in ~CLU/cmp/cenv.clu with the following routine pair:
output = proc (e: rep, msg: qs)
st: stream := e.errst
l: int := e.line
begin
if l > 0
then stream$puts(st, int$unparse(e.line))
stream$putc(st, ':')
end
for s: str in lines(msg) do
stream$putc(st, '\t')
stream$putl(st, s)
end
end except others: end
end output
lines = iter(msg: qs) yields(str)
maxlength = 72
s: str := ""
for t: str in qs$elements(msg) do
s := s || t
while str$size(s) > maxlength do
i: int := maxlength
while true do
if s[i+1] = ' '
then yield(str$substr(s,1,i))
s := str$rest(s,i+2)
break
elseif s[i] = ','
then yield(str$substr(s,1,i))
s := str$rest(s,i+1)
break
else i := i - 1 end
end except when bounds:
yield(string$substr(s,1,maxlength))
s := string$rest(s,maxlength+1)
end
end
end
yield(s)
end lines