mirror of
https://github.com/golang/go
synced 2024-11-21 21:34:40 -07:00
gc: clean up printing.
Got rid of all the magic mystery globals. Now for %N, %T, and %S, the flags +,- and # set a sticky debug, sym and export mode, only visible in the new fmt.c. Default is error mode. Handle h and l flags consistently with the least side effects, so we can now change things without worrying about unrelated things breaking. fixes #2361 R=rsc CC=golang-dev https://golang.org/cl/5316043
This commit is contained in:
parent
5842336089
commit
50110c9f83
@ -24,6 +24,7 @@ OFILES=\
|
||||
dcl.$O\
|
||||
esc.$O\
|
||||
export.$O\
|
||||
fmt.$O\
|
||||
gen.$O\
|
||||
init.$O\
|
||||
lex.$O\
|
||||
@ -32,7 +33,6 @@ OFILES=\
|
||||
mparith2.$O\
|
||||
mparith3.$O\
|
||||
obj.$O\
|
||||
print.$O\
|
||||
range.$O\
|
||||
reflect.$O\
|
||||
select.$O\
|
||||
@ -62,7 +62,7 @@ subr.$O: yerr.h
|
||||
builtin.c: builtin.c.boot
|
||||
cp builtin.c.boot builtin.c
|
||||
|
||||
subr.$O: opnames.h
|
||||
fmt.$O: opnames.h
|
||||
|
||||
opnames.h: mkopnames go.h
|
||||
./mkopnames go.h >opnames.h
|
||||
|
@ -108,7 +108,7 @@ convlit1(Node **np, Type *t, int explicit)
|
||||
if(t != T && t->etype == TIDEAL && n->val.ctype != CTINT)
|
||||
n->val = toint(n->val);
|
||||
if(t != T && !isint[t->etype]) {
|
||||
yyerror("invalid operation: %#N (shift of type %T)", n, t);
|
||||
yyerror("invalid operation: %N (shift of type %T)", n, t);
|
||||
t = T;
|
||||
}
|
||||
n->type = t;
|
||||
@ -224,7 +224,7 @@ convlit1(Node **np, Type *t, int explicit)
|
||||
|
||||
bad:
|
||||
if(!n->diag) {
|
||||
yyerror("cannot convert %#N to type %T", n, t);
|
||||
yyerror("cannot convert %N to type %T", n, t);
|
||||
n->diag = 1;
|
||||
}
|
||||
if(isideal(n->type)) {
|
||||
@ -939,7 +939,7 @@ defaultlit(Node **np, Type *t)
|
||||
defaultlit(&n->left, t);
|
||||
t = n->left->type;
|
||||
if(t != T && !isint[t->etype]) {
|
||||
yyerror("invalid operation: %#N (shift of type %T)", n, t);
|
||||
yyerror("invalid operation: %N (shift of type %T)", n, t);
|
||||
t = T;
|
||||
}
|
||||
n->type = t;
|
||||
@ -991,7 +991,7 @@ defaultlit(Node **np, Type *t)
|
||||
n->type = types[TSTRING];
|
||||
break;
|
||||
}
|
||||
yyerror("defaultlit: unknown literal: %#N", n);
|
||||
yyerror("defaultlit: unknown literal: %N", n);
|
||||
break;
|
||||
case CTBOOL:
|
||||
n->type = types[TBOOL];
|
||||
|
@ -473,7 +473,7 @@ colasdefn(NodeList *left, Node *defn)
|
||||
if(isblank(n))
|
||||
continue;
|
||||
if(!colasname(n)) {
|
||||
yyerror("non-name %#N on left side of :=", n);
|
||||
yyerror("non-name %N on left side of :=", n);
|
||||
nerr++;
|
||||
continue;
|
||||
}
|
||||
@ -1086,10 +1086,11 @@ methodsym(Sym *nsym, Type *t0, int iface)
|
||||
suffix = "·i";
|
||||
}
|
||||
if(t0->sym == S && isptr[t0->etype])
|
||||
p = smprint("(%#hT).%s%s", t0, nsym->name, suffix);
|
||||
p = smprint("(%-hT).%s%s", t0, nsym->name, suffix);
|
||||
else
|
||||
p = smprint("%#hT.%s%s", t0, nsym->name, suffix);
|
||||
p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
|
||||
s = pkglookup(p, s->pkg);
|
||||
//print("methodsym:%s -> %+S\n", p, s);
|
||||
free(p);
|
||||
return s;
|
||||
|
||||
|
@ -88,7 +88,7 @@ escapes(void)
|
||||
if(debug['m']) {
|
||||
for(l=noesc; l; l=l->next)
|
||||
if(l->n->esc == EscNone)
|
||||
warnl(l->n->lineno, "%S %#hN does not escape",
|
||||
warnl(l->n->lineno, "%S %hN does not escape",
|
||||
(l->n->curfn && l->n->curfn->nname) ? l->n->curfn->nname->sym : S,
|
||||
l->n);
|
||||
}
|
||||
@ -178,7 +178,7 @@ esc(Node *n)
|
||||
loopdepth--;
|
||||
|
||||
if(debug['m'] > 1)
|
||||
print("%L:[%d] %#S esc: %#N\n", lineno, loopdepth,
|
||||
print("%L:[%d] %S esc: %N\n", lineno, loopdepth,
|
||||
(curfn && curfn->nname) ? curfn->nname->sym : S, n);
|
||||
|
||||
switch(n->op) {
|
||||
@ -331,7 +331,7 @@ escassign(Node *dst, Node *src)
|
||||
return;
|
||||
|
||||
if(debug['m'] > 1)
|
||||
print("%L:[%d] %#S escassign: %hN = %hN\n", lineno, loopdepth,
|
||||
print("%L:[%d] %S escassign: %hN = %hN\n", lineno, loopdepth,
|
||||
(curfn && curfn->nname) ? curfn->nname->sym : S, dst, src);
|
||||
|
||||
setlineno(dst);
|
||||
@ -609,7 +609,7 @@ escflood(Node *dst)
|
||||
}
|
||||
|
||||
if(debug['m']>1)
|
||||
print("\nescflood:%d: dst %hN scope:%#S[%d]\n", walkgen, dst,
|
||||
print("\nescflood:%d: dst %hN scope:%S[%d]\n", walkgen, dst,
|
||||
(dst->curfn && dst->curfn->nname) ? dst->curfn->nname->sym : S,
|
||||
dst->escloopdepth);
|
||||
|
||||
@ -630,7 +630,7 @@ escwalk(int level, Node *dst, Node *src)
|
||||
src->walkgen = walkgen;
|
||||
|
||||
if(debug['m']>1)
|
||||
print("escwalk: level:%d depth:%d %.*s %hN scope:%#S[%d]\n",
|
||||
print("escwalk: level:%d depth:%d %.*s %hN scope:%S[%d]\n",
|
||||
level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src,
|
||||
(src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
|
||||
|
||||
@ -643,7 +643,7 @@ escwalk(int level, Node *dst, Node *src)
|
||||
if(src->class == PPARAM && leaks && src->esc == EscNone) {
|
||||
src->esc = EscScope;
|
||||
if(debug['m'])
|
||||
warnl(src->lineno, "leaking param: %#hN", src);
|
||||
warnl(src->lineno, "leaking param: %hN", src);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -652,7 +652,7 @@ escwalk(int level, Node *dst, Node *src)
|
||||
src->esc = EscHeap;
|
||||
addrescapes(src->left);
|
||||
if(debug['m'])
|
||||
warnl(src->lineno, "%#hN escapes to heap", src);
|
||||
warnl(src->lineno, "%hN escapes to heap", src);
|
||||
}
|
||||
escwalk(level-1, dst, src->left);
|
||||
break;
|
||||
@ -671,7 +671,7 @@ escwalk(int level, Node *dst, Node *src)
|
||||
if(leaks) {
|
||||
src->esc = EscHeap;
|
||||
if(debug['m'])
|
||||
warnl(src->lineno, "%#hN escapes to heap", src);
|
||||
warnl(src->lineno, "%hN escapes to heap", src);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "y.tab.h"
|
||||
|
||||
static void dumpsym(Sym*);
|
||||
static void dumpexporttype(Sym*);
|
||||
static void dumpexporttype(Type*);
|
||||
static void dumpexportvar(Sym*);
|
||||
static void dumpexportconst(Sym*);
|
||||
|
||||
@ -89,25 +89,7 @@ dumppkg(Pkg *p)
|
||||
}
|
||||
|
||||
static void
|
||||
dumpprereq(Type *t)
|
||||
{
|
||||
if(t == T)
|
||||
return;
|
||||
|
||||
if(t->printed || t == types[t->etype] || t == bytetype || t == runetype)
|
||||
return;
|
||||
t->printed = 1;
|
||||
|
||||
if(t->sym != S) {
|
||||
dumppkg(t->sym->pkg);
|
||||
if(t->etype != TFIELD)
|
||||
dumpsym(t->sym);
|
||||
}
|
||||
dumpprereq(t->type);
|
||||
dumpprereq(t->down);
|
||||
}
|
||||
|
||||
static void
|
||||
dumpexportconst(Sym *s)
|
||||
{
|
||||
Node *n;
|
||||
@ -119,37 +101,12 @@ dumpexportconst(Sym *s)
|
||||
fatal("dumpexportconst: oconst nil: %S", s);
|
||||
|
||||
t = n->type; // may or may not be specified
|
||||
if(t != T)
|
||||
dumpprereq(t);
|
||||
dumpexporttype(t);
|
||||
|
||||
Bprint(bout, "\t");
|
||||
Bprint(bout, "const %#S", s);
|
||||
if(t != T && !isideal(t))
|
||||
Bprint(bout, " %#T", t);
|
||||
Bprint(bout, " = ");
|
||||
|
||||
switch(n->val.ctype) {
|
||||
default:
|
||||
fatal("dumpexportconst: unknown ctype: %S %d", s, n->val.ctype);
|
||||
case CTINT:
|
||||
Bprint(bout, "%B\n", n->val.u.xval);
|
||||
break;
|
||||
case CTBOOL:
|
||||
if(n->val.u.bval)
|
||||
Bprint(bout, "true\n");
|
||||
Bprint(bout, "\tconst %#S %#T = %#V\n", s, t, &n->val);
|
||||
else
|
||||
Bprint(bout, "false\n");
|
||||
break;
|
||||
case CTFLT:
|
||||
Bprint(bout, "%F\n", n->val.u.fval);
|
||||
break;
|
||||
case CTCPLX:
|
||||
Bprint(bout, "(%F+%F)\n", &n->val.u.cval->real, &n->val.u.cval->imag);
|
||||
break;
|
||||
case CTSTR:
|
||||
Bprint(bout, "\"%Z\"\n", n->val.u.sval);
|
||||
break;
|
||||
}
|
||||
Bprint(bout, "\tconst %#S = %#V\n", s, &n->val);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -166,31 +123,12 @@ dumpexportvar(Sym *s)
|
||||
}
|
||||
|
||||
t = n->type;
|
||||
dumpprereq(t);
|
||||
dumpexporttype(t);
|
||||
|
||||
Bprint(bout, "\t");
|
||||
if(t->etype == TFUNC && n->class == PFUNC)
|
||||
Bprint(bout, "func %#S %#hhT", s, t);
|
||||
Bprint(bout, "\tfunc %#S%#hT\n", s, t);
|
||||
else
|
||||
Bprint(bout, "var %#S %#T", s, t);
|
||||
Bprint(bout, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dumpexporttype(Sym *s)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = s->def->type;
|
||||
dumpprereq(t);
|
||||
Bprint(bout, "\t");
|
||||
switch (t->etype) {
|
||||
case TFORW:
|
||||
yyerror("export of incomplete type %T", t);
|
||||
return;
|
||||
}
|
||||
if(Bprint(bout, "type %#T %l#T\n", t, t) < 0)
|
||||
fatal("Bprint failed for %T", t);
|
||||
Bprint(bout, "\tvar %#S %#T\n", s, t);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -204,12 +142,50 @@ methcmp(const void *va, const void *vb)
|
||||
}
|
||||
|
||||
static void
|
||||
dumpsym(Sym *s)
|
||||
dumpexporttype(Type *t)
|
||||
{
|
||||
Type *f, *t;
|
||||
Type *f;
|
||||
Type **m;
|
||||
int i, n;
|
||||
|
||||
if(t == T)
|
||||
return;
|
||||
|
||||
if(t->printed || t == types[t->etype] || t == bytetype || t == runetype)
|
||||
return;
|
||||
t->printed = 1;
|
||||
|
||||
if(t->sym != S && t->etype != TFIELD)
|
||||
dumppkg(t->sym->pkg);
|
||||
|
||||
dumpexporttype(t->type);
|
||||
dumpexporttype(t->down);
|
||||
|
||||
if (t->sym == S || t->etype == TFIELD)
|
||||
return;
|
||||
|
||||
n = 0;
|
||||
for(f=t->method; f!=T; f=f->down) {
|
||||
dumpexporttype(f);
|
||||
n++;
|
||||
}
|
||||
|
||||
m = mal(n*sizeof m[0]);
|
||||
i = 0;
|
||||
for(f=t->method; f!=T; f=f->down)
|
||||
m[i++] = f;
|
||||
qsort(m, n, sizeof m[0], methcmp);
|
||||
|
||||
Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
|
||||
for(i=0; i<n; i++) {
|
||||
f = m[i];
|
||||
Bprint(bout, "\tfunc (%#T) %#hS%#hT\n", getthisx(f->type)->type, f->sym, f->type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dumpsym(Sym *s)
|
||||
{
|
||||
if(s->flags & SymExported)
|
||||
return;
|
||||
s->flags |= SymExported;
|
||||
@ -229,24 +205,10 @@ dumpsym(Sym *s)
|
||||
dumpexportconst(s);
|
||||
break;
|
||||
case OTYPE:
|
||||
t = s->def->type;
|
||||
n = 0;
|
||||
for(f=t->method; f!=T; f=f->down) {
|
||||
dumpprereq(f);
|
||||
n++;
|
||||
}
|
||||
m = mal(n*sizeof m[0]);
|
||||
i = 0;
|
||||
for(f=t->method; f!=T; f=f->down)
|
||||
m[i++] = f;
|
||||
qsort(m, n, sizeof m[0], methcmp);
|
||||
|
||||
dumpexporttype(s);
|
||||
for(i=0; i<n; i++) {
|
||||
f = m[i];
|
||||
Bprint(bout, "\tfunc (%#T) %hS %#hhT\n",
|
||||
f->type->type->type, f->sym, f->type);
|
||||
}
|
||||
if(s->def->type->etype == TFORW)
|
||||
yyerror("export of incomplete type %S", s);
|
||||
else
|
||||
dumpexporttype(s->def->type);
|
||||
break;
|
||||
case ONAME:
|
||||
dumpexportvar(s);
|
||||
@ -254,20 +216,6 @@ dumpsym(Sym *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dumptype(Type *t)
|
||||
{
|
||||
// no need to re-dump type if already exported
|
||||
if(t->printed)
|
||||
return;
|
||||
|
||||
// no need to dump type if it's not ours (was imported)
|
||||
if(t->sym != S && t->sym->def == typenod(t) && !t->local)
|
||||
return;
|
||||
|
||||
Bprint(bout, "type %#T %l#T\n", t, t);
|
||||
}
|
||||
|
||||
void
|
||||
dumpexport(void)
|
||||
{
|
||||
@ -277,10 +225,7 @@ dumpexport(void)
|
||||
|
||||
lno = lineno;
|
||||
|
||||
packagequotes = 1;
|
||||
Bprint(bout, "\n$$ // exports\n");
|
||||
|
||||
Bprint(bout, " package %s", localpkg->name);
|
||||
Bprint(bout, "\n$$ // exports\n package %s", localpkg->name);
|
||||
if(safemode)
|
||||
Bprint(bout, " safe");
|
||||
Bprint(bout, "\n");
|
||||
@ -295,15 +240,7 @@ dumpexport(void)
|
||||
dumpsym(l->n->sym);
|
||||
}
|
||||
|
||||
Bprint(bout, "\n$$ // local types\n");
|
||||
|
||||
for(l=typelist; l; l=l->next) {
|
||||
lineno = l->n->lineno;
|
||||
dumptype(l->n->type);
|
||||
}
|
||||
|
||||
Bprint(bout, "\n$$\n");
|
||||
packagequotes = 0;
|
||||
Bprint(bout, "\n$$ // local types\n\n$$\n"); // 6l expects this. (see ld/go.c)
|
||||
|
||||
lineno = lno;
|
||||
}
|
||||
@ -346,7 +283,7 @@ pkgtype(Sym *s)
|
||||
s->def = typenod(t);
|
||||
}
|
||||
if(s->def->type == T)
|
||||
yyerror("pkgtype %lS", s);
|
||||
yyerror("pkgtype %S", s);
|
||||
return s->def->type;
|
||||
}
|
||||
|
||||
@ -400,8 +337,7 @@ importvar(Sym *s, Type *t, int ctxt)
|
||||
if(s->def != N && s->def->op == ONAME) {
|
||||
if(eqtype(t, s->def->type))
|
||||
return;
|
||||
yyerror("inconsistent definition for var %S during import\n\t%T\n\t%T",
|
||||
s, s->def->type, t);
|
||||
yyerror("inconsistent definition for var %S during import\n\t%T\n\t%T", s, s->def->type, t);
|
||||
}
|
||||
n = newname(s);
|
||||
n->type = t;
|
||||
|
1519
src/cmd/gc/fmt.c
Normal file
1519
src/cmd/gc/fmt.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -94,7 +94,7 @@ addrescapes(Node *n)
|
||||
if(!debug['s'])
|
||||
n->esc = EscHeap;
|
||||
if(debug['m'])
|
||||
print("%L: moved to heap: %#hN\n", n->lineno, n);
|
||||
print("%L: moved to heap: %N\n", n->lineno, n);
|
||||
curfn = oldfn;
|
||||
break;
|
||||
}
|
||||
|
@ -846,14 +846,8 @@ EXTERN char* hunk;
|
||||
EXTERN int32 nhunk;
|
||||
EXTERN int32 thunk;
|
||||
|
||||
EXTERN int exporting;
|
||||
EXTERN int erroring;
|
||||
EXTERN int noargnames;
|
||||
|
||||
EXTERN int funcdepth;
|
||||
EXTERN int typecheckok;
|
||||
EXTERN int packagequotes;
|
||||
EXTERN int longsymnames;
|
||||
EXTERN int compiling_runtime;
|
||||
|
||||
EXTERN int rune32;
|
||||
@ -986,6 +980,13 @@ void importtype(Type *pt, Type *t);
|
||||
void importvar(Sym *s, Type *t, int ctxt);
|
||||
Type* pkgtype(Sym *s);
|
||||
|
||||
/*
|
||||
* fmt.c
|
||||
*/
|
||||
void fmtinstallgo(void);
|
||||
void dump(char *s, Node *n);
|
||||
void dumplist(char *s, NodeList *l);
|
||||
|
||||
/*
|
||||
* gen.c
|
||||
*/
|
||||
@ -1095,12 +1096,6 @@ void dumpobj(void);
|
||||
void ieeedtod(uint64 *ieee, double native);
|
||||
Sym* stringsym(char*, int);
|
||||
|
||||
/*
|
||||
* print.c
|
||||
*/
|
||||
void exprfmt(Fmt *f, Node *n, int prec);
|
||||
void exprlistfmt(Fmt *f, NodeList *l);
|
||||
|
||||
/*
|
||||
* range.c
|
||||
*/
|
||||
@ -1134,15 +1129,6 @@ int stataddr(Node *nam, Node *n);
|
||||
/*
|
||||
* subr.c
|
||||
*/
|
||||
int Econv(Fmt *fp);
|
||||
int Jconv(Fmt *fp);
|
||||
int Lconv(Fmt *fp);
|
||||
int Nconv(Fmt *fp);
|
||||
int Oconv(Fmt *fp);
|
||||
int Sconv(Fmt *fp);
|
||||
int Tconv(Fmt *fp);
|
||||
int Vconv(Fmt *fp);
|
||||
int Zconv(Fmt *fp);
|
||||
Node* adddot(Node *n);
|
||||
int adddot1(Sym *s, Type *t, int d, Type **save, int ignorecase);
|
||||
Type* aindex(Node *b, Type *t);
|
||||
@ -1157,8 +1143,6 @@ NodeList* concat(NodeList *a, NodeList *b);
|
||||
int convertop(Type *src, Type *dst, char **why);
|
||||
int count(NodeList *l);
|
||||
int cplxsubtype(int et);
|
||||
void dump(char *s, Node *n);
|
||||
void dumplist(char *s, NodeList *l);
|
||||
int eqtype(Type *t1, Type *t2);
|
||||
int eqtypenoname(Type *t1, Type *t2);
|
||||
void errorexit(void);
|
||||
@ -1347,6 +1331,7 @@ void zname(Biobuf *b, Sym *s, int t);
|
||||
#pragma varargck type "lD" Addr*
|
||||
#pragma varargck type "E" int
|
||||
#pragma varargck type "F" Mpflt*
|
||||
#pragma varargck type "H" NodeList*
|
||||
#pragma varargck type "J" Node*
|
||||
#pragma varargck type "L" int
|
||||
#pragma varargck type "L" uint
|
||||
|
@ -426,7 +426,7 @@ simple_stmt:
|
||||
if($1->next != nil)
|
||||
yyerror("argument count mismatch: %d = %d", count($1), 1);
|
||||
else if($1->n->op != ONAME && $1->n->op != OTYPE && $1->n->op != ONONAME)
|
||||
yyerror("invalid variable name %#N in type switch", $1->n);
|
||||
yyerror("invalid variable name %N in type switch", $1->n);
|
||||
else
|
||||
n = $1->n;
|
||||
$$ = nod(OTYPESW, n, $3->n->right);
|
||||
|
@ -253,18 +253,7 @@ main(int argc, char *argv[])
|
||||
*p = '/';
|
||||
}
|
||||
|
||||
fmtinstall('O', Oconv); // node opcodes
|
||||
fmtinstall('E', Econv); // etype opcodes
|
||||
fmtinstall('J', Jconv); // all the node flags
|
||||
fmtinstall('S', Sconv); // sym pointer
|
||||
fmtinstall('T', Tconv); // type pointer
|
||||
fmtinstall('V', Vconv); // Val pointer
|
||||
fmtinstall('N', Nconv); // node pointer
|
||||
fmtinstall('Z', Zconv); // escaped string
|
||||
fmtinstall('L', Lconv); // line number
|
||||
fmtinstall('B', Bconv); // big numbers
|
||||
fmtinstall('F', Fconv); // big float numbers
|
||||
|
||||
fmtinstallgo();
|
||||
betypeinit();
|
||||
if(widthptr == 0)
|
||||
fatal("betypeinit failed");
|
||||
|
@ -52,7 +52,7 @@ dumpglobls(void)
|
||||
continue;
|
||||
|
||||
if(n->type == T)
|
||||
fatal("external %#N nil type\n", n);
|
||||
fatal("external %N nil type\n", n);
|
||||
if(n->class == PFUNC)
|
||||
continue;
|
||||
if(n->sym->pkg != localpkg)
|
||||
|
@ -1,625 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "go.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PFIXME = 0,
|
||||
};
|
||||
|
||||
void
|
||||
exprlistfmt(Fmt *f, NodeList *l)
|
||||
{
|
||||
for(; l; l=l->next) {
|
||||
exprfmt(f, l->n, 0);
|
||||
if(l->next)
|
||||
fmtprint(f, ", ");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
stmtlistfmt(Fmt *f, NodeList *l)
|
||||
{
|
||||
for(; l; l=l->next) {
|
||||
fmtprint(f, " %#N", l->n);
|
||||
if(l->next)
|
||||
fmtprint(f, ";");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exprfmt(Fmt *f, Node *n, int prec)
|
||||
{
|
||||
int nprec;
|
||||
char *p;
|
||||
NodeList *l;
|
||||
|
||||
nprec = 0;
|
||||
if(n == nil) {
|
||||
fmtprint(f, "<nil>");
|
||||
return;
|
||||
}
|
||||
|
||||
if(n->implicit) {
|
||||
exprfmt(f, n->left, prec);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(n->op) {
|
||||
case OAPPEND:
|
||||
case ONAME:
|
||||
case ONONAME:
|
||||
case OPACK:
|
||||
case OLITERAL:
|
||||
case ODOT:
|
||||
case ODOTPTR:
|
||||
case ODOTINTER:
|
||||
case ODOTMETH:
|
||||
case ODOTTYPE:
|
||||
case ODOTTYPE2:
|
||||
case OXDOT:
|
||||
case OARRAYBYTESTR:
|
||||
case OCAP:
|
||||
case OCLOSE:
|
||||
case OCOPY:
|
||||
case OLEN:
|
||||
case OMAKE:
|
||||
case ONEW:
|
||||
case OPANIC:
|
||||
case OPRINT:
|
||||
case OPRINTN:
|
||||
case OCALL:
|
||||
case OCALLMETH:
|
||||
case OCALLINTER:
|
||||
case OCALLFUNC:
|
||||
case OCONV:
|
||||
case OCONVNOP:
|
||||
case OMAKESLICE:
|
||||
case ORUNESTR:
|
||||
case OADDR:
|
||||
case OCOM:
|
||||
case OIND:
|
||||
case OMINUS:
|
||||
case ONOT:
|
||||
case OPLUS:
|
||||
case ORECV:
|
||||
case OCONVIFACE:
|
||||
case OTPAREN:
|
||||
case OINDEX:
|
||||
case OINDEXMAP:
|
||||
case OPAREN:
|
||||
nprec = 7;
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case ODIV:
|
||||
case OMOD:
|
||||
case OLSH:
|
||||
case ORSH:
|
||||
case OAND:
|
||||
case OANDNOT:
|
||||
nprec = 6;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OSUB:
|
||||
case OOR:
|
||||
case OXOR:
|
||||
nprec = 5;
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
case OLT:
|
||||
case OLE:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case ONE:
|
||||
case OCMPSTR:
|
||||
nprec = 4;
|
||||
break;
|
||||
|
||||
case OSEND:
|
||||
nprec = 3;
|
||||
break;
|
||||
|
||||
case OANDAND:
|
||||
nprec = 2;
|
||||
break;
|
||||
|
||||
case OOROR:
|
||||
nprec = 1;
|
||||
break;
|
||||
|
||||
case OTYPE:
|
||||
if(n->sym != S)
|
||||
nprec = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
if(prec > nprec)
|
||||
fmtprint(f, "(");
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
bad:
|
||||
fmtprint(f, "(node %O)", n->op);
|
||||
break;
|
||||
|
||||
case OPAREN:
|
||||
fmtprint(f, "(%#N)", n->left);
|
||||
break;
|
||||
|
||||
case ODDDARG:
|
||||
fmtprint(f, "... argument");
|
||||
break;
|
||||
|
||||
case OREGISTER:
|
||||
fmtprint(f, "%R", n->val.u.reg);
|
||||
break;
|
||||
|
||||
case OLITERAL:
|
||||
if(n->sym != S) {
|
||||
fmtprint(f, "%S", n->sym);
|
||||
break;
|
||||
}
|
||||
switch(n->val.ctype) {
|
||||
default:
|
||||
goto bad;
|
||||
case CTINT:
|
||||
fmtprint(f, "%B", n->val.u.xval);
|
||||
break;
|
||||
case CTBOOL:
|
||||
if(n->val.u.bval)
|
||||
fmtprint(f, "true");
|
||||
else
|
||||
fmtprint(f, "false");
|
||||
break;
|
||||
case CTCPLX:
|
||||
fmtprint(f, "%.17g+%.17gi",
|
||||
mpgetflt(&n->val.u.cval->real),
|
||||
mpgetflt(&n->val.u.cval->imag));
|
||||
break;
|
||||
case CTFLT:
|
||||
fmtprint(f, "%.17g", mpgetflt(n->val.u.fval));
|
||||
break;
|
||||
case CTSTR:
|
||||
fmtprint(f, "\"%Z\"", n->val.u.sval);
|
||||
break;
|
||||
case CTNIL:
|
||||
fmtprint(f, "nil");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ONAME:
|
||||
case OPACK:
|
||||
case ONONAME:
|
||||
fmtprint(f, "%S", n->sym);
|
||||
break;
|
||||
|
||||
case OTYPE:
|
||||
if(n->type == T && n->sym != S) {
|
||||
fmtprint(f, "%S", n->sym);
|
||||
break;
|
||||
}
|
||||
fmtprint(f, "%T", n->type);
|
||||
break;
|
||||
|
||||
case OTARRAY:
|
||||
fmtprint(f, "[]");
|
||||
exprfmt(f, n->left, PFIXME);
|
||||
break;
|
||||
|
||||
case OTPAREN:
|
||||
fmtprint(f, "(");
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OTMAP:
|
||||
fmtprint(f, "map[");
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, "] ");
|
||||
exprfmt(f, n->right, 0);
|
||||
break;
|
||||
|
||||
case OTCHAN:
|
||||
if(n->etype == Crecv)
|
||||
fmtprint(f, "<-");
|
||||
fmtprint(f, "chan");
|
||||
if(n->etype == Csend) {
|
||||
fmtprint(f, "<- ");
|
||||
exprfmt(f, n->left, 0);
|
||||
} else {
|
||||
fmtprint(f, " ");
|
||||
if(n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv) {
|
||||
fmtprint(f, "(");
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, ")");
|
||||
} else
|
||||
exprfmt(f, n->left, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case OTSTRUCT:
|
||||
fmtprint(f, "<struct>");
|
||||
break;
|
||||
|
||||
case OTINTER:
|
||||
fmtprint(f, "<inter>");
|
||||
break;
|
||||
|
||||
case OTFUNC:
|
||||
fmtprint(f, "<func>");
|
||||
break;
|
||||
|
||||
case OAS:
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, " = ");
|
||||
exprfmt(f, n->right, 0);
|
||||
break;
|
||||
|
||||
case OASOP:
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, " %#O= ", n->etype);
|
||||
exprfmt(f, n->right, 0);
|
||||
break;
|
||||
|
||||
case OAS2:
|
||||
case OAS2DOTTYPE:
|
||||
case OAS2FUNC:
|
||||
case OAS2MAPR:
|
||||
case OAS2MAPW:
|
||||
case OAS2RECV:
|
||||
exprlistfmt(f, n->list);
|
||||
fmtprint(f, " = ");
|
||||
exprlistfmt(f, n->rlist);
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OADDSTR:
|
||||
case OAND:
|
||||
case OANDAND:
|
||||
case OANDNOT:
|
||||
case ODIV:
|
||||
case OEQ:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OLE:
|
||||
case OLT:
|
||||
case OLSH:
|
||||
case OMOD:
|
||||
case OMUL:
|
||||
case ONE:
|
||||
case OOR:
|
||||
case OOROR:
|
||||
case ORSH:
|
||||
case OSEND:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
exprfmt(f, n->left, nprec);
|
||||
fmtprint(f, " %#O ", n->op);
|
||||
exprfmt(f, n->right, nprec+1);
|
||||
break;
|
||||
|
||||
case OCMPSTR:
|
||||
exprfmt(f, n->left, nprec);
|
||||
fmtprint(f, " %#O ", n->etype);
|
||||
exprfmt(f, n->right, nprec+1);
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
case OCOM:
|
||||
case OIND:
|
||||
case OMINUS:
|
||||
case ONOT:
|
||||
case OPLUS:
|
||||
case ORECV:
|
||||
fmtprint(f, "%#O", n->op);
|
||||
if((n->op == OMINUS || n->op == OPLUS) && n->left->op == n->op)
|
||||
fmtprint(f, " ");
|
||||
exprfmt(f, n->left, 0);
|
||||
break;
|
||||
|
||||
case OCLOSURE:
|
||||
if(f->flags & FmtShort) {
|
||||
fmtprint(f, "func literal", n->type);
|
||||
} else {
|
||||
fmtprint(f, "func %hhT {", n->type);
|
||||
stmtlistfmt(f, n->nbody);
|
||||
fmtprint(f, " }");
|
||||
}
|
||||
break;
|
||||
|
||||
case OCOMPLIT:
|
||||
fmtprint(f, "composite literal");
|
||||
break;
|
||||
|
||||
case OARRAYLIT:
|
||||
case OMAPLIT:
|
||||
case OSTRUCTLIT:
|
||||
if(f->flags & FmtShort) {
|
||||
fmtprint(f, "%#hhT literal", n->type);
|
||||
} else {
|
||||
fmtprint(f, "%#hhT{", n->type);
|
||||
for (l=n->list; l; l=l->next) {
|
||||
fmtprint(f, " %#N:%#N", l->n->left, l->n->right);
|
||||
if (l->next) fmtprint(f, ",");
|
||||
}
|
||||
fmtprint(f, " }");
|
||||
}
|
||||
break;
|
||||
|
||||
case OXDOT:
|
||||
case ODOT:
|
||||
case ODOTPTR:
|
||||
case ODOTINTER:
|
||||
case ODOTMETH:
|
||||
exprfmt(f, n->left, 7);
|
||||
if(n->right == N || n->right->sym == S)
|
||||
fmtprint(f, ".<nil>");
|
||||
else {
|
||||
// skip leading type· in method name
|
||||
p = utfrrune(n->right->sym->name, 0xb7);
|
||||
if(p)
|
||||
p+=2;
|
||||
else
|
||||
p = n->right->sym->name;
|
||||
fmtprint(f, ".%s", p);
|
||||
}
|
||||
break;
|
||||
|
||||
case ODOTTYPE:
|
||||
case ODOTTYPE2:
|
||||
exprfmt(f, n->left, 7);
|
||||
fmtprint(f, ".(");
|
||||
if(n->right != N)
|
||||
exprfmt(f, n->right, 0);
|
||||
else
|
||||
fmtprint(f, "%T", n->type);
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OINDEX:
|
||||
case OINDEXMAP:
|
||||
exprfmt(f, n->left, 7);
|
||||
fmtprint(f, "[");
|
||||
exprfmt(f, n->right, 0);
|
||||
fmtprint(f, "]");
|
||||
break;
|
||||
|
||||
case OSLICE:
|
||||
case OSLICESTR:
|
||||
case OSLICEARR:
|
||||
exprfmt(f, n->left, 7);
|
||||
fmtprint(f, "[");
|
||||
if(n->right->left != N)
|
||||
exprfmt(f, n->right->left, 0);
|
||||
fmtprint(f, ":");
|
||||
if(n->right->right != N)
|
||||
exprfmt(f, n->right->right, 0);
|
||||
fmtprint(f, "]");
|
||||
break;
|
||||
|
||||
case OCALL:
|
||||
case OCALLFUNC:
|
||||
case OCALLINTER:
|
||||
case OCALLMETH:
|
||||
exprfmt(f, n->left, 7);
|
||||
fmtprint(f, "(");
|
||||
exprlistfmt(f, n->list);
|
||||
if(n->isddd)
|
||||
fmtprint(f, "...");
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OCOMPLEX:
|
||||
fmtprint(f, "complex(");
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, ", ");
|
||||
exprfmt(f, n->right, 0);
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OREAL:
|
||||
fmtprint(f, "real(");
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OIMAG:
|
||||
fmtprint(f, "imag(");
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OCONV:
|
||||
case OCONVIFACE:
|
||||
case OCONVNOP:
|
||||
case OARRAYBYTESTR:
|
||||
case OSTRARRAYBYTE:
|
||||
case ORUNESTR:
|
||||
if(n->type == T || n->type->sym == S)
|
||||
fmtprint(f, "(%T)(", n->type);
|
||||
else
|
||||
fmtprint(f, "%T(", n->type);
|
||||
if(n->left == N)
|
||||
exprlistfmt(f, n->list);
|
||||
else
|
||||
exprfmt(f, n->left, 0);
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OAPPEND:
|
||||
case OCAP:
|
||||
case OCLOSE:
|
||||
case OLEN:
|
||||
case OCOPY:
|
||||
case OMAKE:
|
||||
case ONEW:
|
||||
case OPANIC:
|
||||
case OPRINT:
|
||||
case OPRINTN:
|
||||
fmtprint(f, "%#O(", n->op);
|
||||
if(n->left)
|
||||
exprfmt(f, n->left, 0);
|
||||
else
|
||||
exprlistfmt(f, n->list);
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OMAKESLICE:
|
||||
fmtprint(f, "make(%#T, ", n->type);
|
||||
exprfmt(f, n->left, 0);
|
||||
if(count(n->list) > 2) {
|
||||
fmtprint(f, ", ");
|
||||
exprfmt(f, n->right, 0);
|
||||
}
|
||||
fmtprint(f, ")");
|
||||
break;
|
||||
|
||||
case OMAKEMAP:
|
||||
case OMAKECHAN:
|
||||
fmtprint(f, "make(%#T)", n->type);
|
||||
break;
|
||||
|
||||
// Some statements
|
||||
|
||||
case ODCL:
|
||||
fmtprint(f, "var %S %#T", n->left->sym, n->left->type);
|
||||
break;
|
||||
|
||||
case ORETURN:
|
||||
fmtprint(f, "return ");
|
||||
exprlistfmt(f, n->list);
|
||||
break;
|
||||
|
||||
case OPROC:
|
||||
fmtprint(f, "go %#N", n->left);
|
||||
break;
|
||||
|
||||
case ODEFER:
|
||||
fmtprint(f, "defer %#N", n->left);
|
||||
break;
|
||||
|
||||
case OIF:
|
||||
if (n->ninit && n->ninit->next) {
|
||||
fmtprint(f, "{");
|
||||
stmtlistfmt(f, n->ninit);
|
||||
fmtprint(f, "; ");
|
||||
}
|
||||
fmtstrcpy(f, "if ");
|
||||
if (n->ninit && !n->ninit->next)
|
||||
fmtprint(f, "%#N; ", n->ninit->n);
|
||||
fmtprint(f, "%#N {", n->ntest);
|
||||
stmtlistfmt(f, n->nbody);
|
||||
if (n->nelse) {
|
||||
fmtprint(f, "} else {");
|
||||
stmtlistfmt(f, n->nelse);
|
||||
}
|
||||
fmtprint(f, "}");
|
||||
if (n->ninit && n->ninit->next)
|
||||
fmtprint(f, "}");
|
||||
break;
|
||||
|
||||
case OFOR:
|
||||
if (n->ninit && n->ninit->next) {
|
||||
fmtprint(f, "{");
|
||||
stmtlistfmt(f, n->ninit);
|
||||
fmtprint(f, "; ");
|
||||
}
|
||||
fmtstrcpy(f, "for");
|
||||
if (n->ninit && !n->ninit->next)
|
||||
fmtprint(f, " %#N;", n->ninit->n);
|
||||
else if (n->ntest || n->nincr)
|
||||
fmtstrcpy(f, " ;");
|
||||
if (n->ntest)
|
||||
fmtprint(f, "%#N", n->ntest);
|
||||
if (n->nincr)
|
||||
fmtprint(f, "; %#N", n->nincr);
|
||||
else if (n->ninit && !n->ninit->next)
|
||||
fmtstrcpy(f, " ;");
|
||||
fmtstrcpy(f, " {");
|
||||
stmtlistfmt(f, n->nbody);
|
||||
fmtprint(f, "}");
|
||||
if (n->ninit && n->ninit->next)
|
||||
fmtprint(f, "}");
|
||||
break;
|
||||
|
||||
case ORANGE:
|
||||
if (n->ninit) {
|
||||
fmtprint(f, "{");
|
||||
stmtlistfmt(f, n->ninit);
|
||||
fmtprint(f, "; ");
|
||||
}
|
||||
fmtprint(f, "for ");
|
||||
exprlistfmt(f, n->list);
|
||||
fmtprint(f, " = range %#N {", n->right);
|
||||
stmtlistfmt(f, n->nbody);
|
||||
fmtprint(f, "}");
|
||||
if (n->ninit)
|
||||
fmtprint(f, "}");
|
||||
break;
|
||||
|
||||
case OSWITCH:
|
||||
if (n->ninit && n->ninit->next) {
|
||||
fmtprint(f, "{");
|
||||
stmtlistfmt(f, n->ninit);
|
||||
fmtprint(f, "; ");
|
||||
}
|
||||
fmtstrcpy(f, "select");
|
||||
if (n->ninit && !n->ninit->next)
|
||||
fmtprint(f, " %#N;", n->ninit->n);
|
||||
if (n->ntest)
|
||||
fmtprint(f, "%#N", n->ntest);
|
||||
fmtstrcpy(f, " {");
|
||||
for(l=n->list; l; l=l->next) {
|
||||
if (l->n->list) {
|
||||
fmtprint(f, " case ");
|
||||
exprlistfmt(f, l->n->list);
|
||||
} else {
|
||||
fmtprint(f, " default");
|
||||
}
|
||||
fmtstrcpy(f, ":");
|
||||
stmtlistfmt(f, l->n->nbody);
|
||||
if (l->next)
|
||||
fmtprint(f, ";");
|
||||
}
|
||||
fmtprint(f, " }");
|
||||
if (n->ninit)
|
||||
fmtprint(f, "}");
|
||||
break;
|
||||
|
||||
|
||||
case OSELECT:
|
||||
if (n->ninit) {
|
||||
fmtprint(f, "{");
|
||||
stmtlistfmt(f, n->ninit);
|
||||
fmtprint(f, "; ");
|
||||
}
|
||||
fmtstrcpy(f, "select {");
|
||||
for(l=n->list; l; l=l->next) {
|
||||
if (l->n->list) {
|
||||
fmtprint(f, " case ");
|
||||
exprlistfmt(f, l->n->list);
|
||||
} else {
|
||||
fmtprint(f, " default");
|
||||
}
|
||||
fmtstrcpy(f, ":");
|
||||
stmtlistfmt(f, l->n->nbody);
|
||||
if (l->next)
|
||||
fmtprint(f, ";");
|
||||
}
|
||||
fmtprint(f, " }");
|
||||
if (n->ninit)
|
||||
fmtprint(f, "}");
|
||||
break;
|
||||
}
|
||||
|
||||
if(prec > nprec)
|
||||
fmtprint(f, ")");
|
||||
}
|
@ -32,7 +32,7 @@ typecheckrange(Node *n)
|
||||
|
||||
switch(t->etype) {
|
||||
default:
|
||||
yyerror("cannot range over %+N", n->right);
|
||||
yyerror("cannot range over %lN", n->right);
|
||||
goto out;
|
||||
|
||||
case TARRAY:
|
||||
@ -71,12 +71,12 @@ typecheckrange(Node *n)
|
||||
if(v1->defn == n)
|
||||
v1->type = t1;
|
||||
else if(v1->type != T && assignop(t1, v1->type, &why) == 0)
|
||||
yyerror("cannot assign type %T to %+N in range%s", t1, v1, why);
|
||||
yyerror("cannot assign type %T to %lN in range%s", t1, v1, why);
|
||||
if(v2) {
|
||||
if(v2->defn == n)
|
||||
v2->type = t2;
|
||||
else if(v2->type != T && assignop(t2, v2->type, &why) == 0)
|
||||
yyerror("cannot assign type %T to %+N in range%s", t2, v2, why);
|
||||
yyerror("cannot assign type %T to %lN in range%s", t2, v2, why);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -592,9 +592,8 @@ dcommontype(Sym *s, int ot, Type *t)
|
||||
if(!haspointers(t))
|
||||
i |= KindNoPointers;
|
||||
ot = duint8(s, ot, i); // kind
|
||||
longsymnames = 1;
|
||||
p = smprint("%-T", t);
|
||||
longsymnames = 0;
|
||||
p = smprint("%-uT", t);
|
||||
//print("dcommontype: %s\n", p);
|
||||
ot = dgostringptr(s, ot, p); // string
|
||||
free(p);
|
||||
|
||||
@ -614,8 +613,9 @@ typesym(Type *t)
|
||||
char *p;
|
||||
Sym *s;
|
||||
|
||||
p = smprint("%#-T", t);
|
||||
p = smprint("%-T", t);
|
||||
s = pkglookup(p, typepkg);
|
||||
//print("typesym: %s -> %+S\n", p, s);
|
||||
free(p);
|
||||
return s;
|
||||
}
|
||||
@ -662,8 +662,9 @@ weaktypesym(Type *t)
|
||||
weak->prefix = "weak.type"; // not weak%2etype
|
||||
}
|
||||
|
||||
p = smprint("%#-T", t);
|
||||
p = smprint("%-T", t);
|
||||
s = pkglookup(p, weak);
|
||||
//print("weaktypesym: %s -> %+S\n", p, s);
|
||||
free(p);
|
||||
return s;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -153,7 +153,7 @@ typecheck(Node **np, int top)
|
||||
}
|
||||
|
||||
if(n->typecheck == 2) {
|
||||
yyerror("typechecking loop involving %#N", n);
|
||||
yyerror("typechecking loop involving %N", n);
|
||||
lineno = lno;
|
||||
return n;
|
||||
}
|
||||
@ -260,7 +260,7 @@ reswitch:
|
||||
v = toint(l->val);
|
||||
break;
|
||||
default:
|
||||
yyerror("invalid array bound %#N", l);
|
||||
yyerror("invalid array bound %N", l);
|
||||
goto error;
|
||||
}
|
||||
t->bound = mpgetfix(v.u.xval);
|
||||
@ -351,7 +351,7 @@ reswitch:
|
||||
goto ret;
|
||||
}
|
||||
if(!isptr[t->etype]) {
|
||||
yyerror("invalid indirect of %+N", n->left);
|
||||
yyerror("invalid indirect of %lN", n->left);
|
||||
goto error;
|
||||
}
|
||||
ok |= Erv;
|
||||
@ -433,12 +433,12 @@ reswitch:
|
||||
}
|
||||
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
|
||||
defaultlit2(&l, &r, 1);
|
||||
yyerror("invalid operation: %#N (mismatched types %T and %T)", n, l->type, r->type);
|
||||
yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
|
||||
goto error;
|
||||
}
|
||||
if(!okfor[op][et]) {
|
||||
notokfor:
|
||||
yyerror("invalid operation: %#N (operator %#O not defined on %s)", n, op, typekind(et));
|
||||
yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(et));
|
||||
goto error;
|
||||
}
|
||||
// okfor allows any array == array;
|
||||
@ -448,7 +448,7 @@ reswitch:
|
||||
if(r->type->etype == TARRAY && !isslice(r->type))
|
||||
goto notokfor;
|
||||
if(isslice(l->type) && !isnil(l) && !isnil(r)) {
|
||||
yyerror("invalid operation: %#N (slice can only be compared to nil)", n);
|
||||
yyerror("invalid operation: %N (slice can only be compared to nil)", n);
|
||||
goto error;
|
||||
}
|
||||
t = l->type;
|
||||
@ -488,12 +488,12 @@ reswitch:
|
||||
n->right = r;
|
||||
t = r->type;
|
||||
if(!isint[t->etype] || issigned[t->etype]) {
|
||||
yyerror("invalid operation: %#N (shift count type %T, must be unsigned integer)", n, r->type);
|
||||
yyerror("invalid operation: %N (shift count type %T, must be unsigned integer)", n, r->type);
|
||||
goto error;
|
||||
}
|
||||
t = l->type;
|
||||
if(t != T && t->etype != TIDEAL && !isint[t->etype]) {
|
||||
yyerror("invalid operation: %#N (shift of type %T)", n, t);
|
||||
yyerror("invalid operation: %N (shift of type %T)", n, t);
|
||||
goto error;
|
||||
}
|
||||
// no defaultlit for left
|
||||
@ -510,7 +510,7 @@ reswitch:
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
if(!okfor[n->op][t->etype]) {
|
||||
yyerror("invalid operation: %#O %T", n->op, t);
|
||||
yyerror("invalid operation: %O %T", n->op, t);
|
||||
goto error;
|
||||
}
|
||||
n->type = t;
|
||||
@ -571,9 +571,9 @@ reswitch:
|
||||
if(l->op == OTYPE) {
|
||||
if(!looktypedot(n, t, 0)) {
|
||||
if(looktypedot(n, t, 1))
|
||||
yyerror("%#N undefined (cannot refer to unexported method %S)", n, n->right->sym);
|
||||
yyerror("%N undefined (cannot refer to unexported method %S)", n, n->right->sym);
|
||||
else
|
||||
yyerror("%#N undefined (type %T has no method %S)", n, t, n->right->sym);
|
||||
yyerror("%N undefined (type %T has no method %S)", n, t, n->right->sym);
|
||||
goto error;
|
||||
}
|
||||
if(n->type->etype != TFUNC || n->type->thistuple != 1) {
|
||||
@ -599,9 +599,9 @@ reswitch:
|
||||
}
|
||||
if(!lookdot(n, t, 0)) {
|
||||
if(lookdot(n, t, 1))
|
||||
yyerror("%#N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
|
||||
yyerror("%N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
|
||||
else
|
||||
yyerror("%#N undefined (type %T has no field or method %S)", n, tp, n->right->sym);
|
||||
yyerror("%N undefined (type %T has no field or method %S)", n, tp, n->right->sym);
|
||||
goto error;
|
||||
}
|
||||
switch(n->op) {
|
||||
@ -623,7 +623,7 @@ reswitch:
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
if(!isinter(t)) {
|
||||
yyerror("invalid type assertion: %#N (non-interface type %T on left)", n, t);
|
||||
yyerror("invalid type assertion: %N (non-interface type %T on left)", n, t);
|
||||
goto error;
|
||||
}
|
||||
if(n->right != N) {
|
||||
@ -636,12 +636,12 @@ reswitch:
|
||||
if(n->type != T && n->type->etype != TINTER)
|
||||
if(!implements(n->type, t, &missing, &have, &ptr)) {
|
||||
if(have)
|
||||
yyerror("impossible type assertion: %+N cannot have dynamic type %T"
|
||||
" (wrong type for %S method)\n\thave %S%hhT\n\twant %S%hhT",
|
||||
yyerror("impossible type assertion: %lN cannot have dynamic type %T"
|
||||
" (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
|
||||
l, n->type, missing->sym, have->sym, have->type,
|
||||
missing->sym, missing->type);
|
||||
else
|
||||
yyerror("impossible type assertion: %+N cannot have dynamic type %T"
|
||||
yyerror("impossible type assertion: %lN cannot have dynamic type %T"
|
||||
" (missing %S method)", l, n->type, missing->sym);
|
||||
goto error;
|
||||
}
|
||||
@ -659,13 +659,13 @@ reswitch:
|
||||
goto error;
|
||||
switch(t->etype) {
|
||||
default:
|
||||
yyerror("invalid operation: %#N (index of type %T)", n, t);
|
||||
yyerror("invalid operation: %N (index of type %T)", n, t);
|
||||
goto error;
|
||||
|
||||
case TARRAY:
|
||||
defaultlit(&n->right, T);
|
||||
if(n->right->type != T && !isint[n->right->type->etype])
|
||||
yyerror("non-integer array index %#N", n->right);
|
||||
yyerror("non-integer array index %N", n->right);
|
||||
n->type = t->type;
|
||||
break;
|
||||
|
||||
@ -681,7 +681,7 @@ reswitch:
|
||||
case TSTRING:
|
||||
defaultlit(&n->right, types[TUINT]);
|
||||
if(n->right->type != T && !isint[n->right->type->etype])
|
||||
yyerror("non-integer string index %#N", n->right);
|
||||
yyerror("non-integer string index %N", n->right);
|
||||
n->type = types[TUINT8];
|
||||
break;
|
||||
}
|
||||
@ -695,11 +695,11 @@ reswitch:
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
if(t->etype != TCHAN) {
|
||||
yyerror("invalid operation: %#N (receive from non-chan type %T)", n, t);
|
||||
yyerror("invalid operation: %N (receive from non-chan type %T)", n, t);
|
||||
goto error;
|
||||
}
|
||||
if(!(t->chan & Crecv)) {
|
||||
yyerror("invalid operation: %#N (receive from send-only type %T)", n, t);
|
||||
yyerror("invalid operation: %N (receive from send-only type %T)", n, t);
|
||||
goto error;
|
||||
}
|
||||
n->type = t->type;
|
||||
@ -707,7 +707,7 @@ reswitch:
|
||||
|
||||
case OSEND:
|
||||
if(top & Erv) {
|
||||
yyerror("send statement %#N used as value; use select for non-blocking send", n);
|
||||
yyerror("send statement %N used as value; use select for non-blocking send", n);
|
||||
goto error;
|
||||
}
|
||||
ok |= Etop | Erv;
|
||||
@ -718,11 +718,11 @@ reswitch:
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
if(t->etype != TCHAN) {
|
||||
yyerror("invalid operation: %#N (send to non-chan type %T)", n, t);
|
||||
yyerror("invalid operation: %N (send to non-chan type %T)", n, t);
|
||||
goto error;
|
||||
}
|
||||
if(!(t->chan & Csend)) {
|
||||
yyerror("invalid operation: %#N (send to receive-only type %T)", n, t);
|
||||
yyerror("invalid operation: %N (send to receive-only type %T)", n, t);
|
||||
goto error;
|
||||
}
|
||||
defaultlit(&n->right, t->type);
|
||||
@ -751,7 +751,7 @@ reswitch:
|
||||
if((t = n->right->left->type) == T)
|
||||
goto error;
|
||||
if(!isint[t->etype]) {
|
||||
yyerror("invalid slice index %#N (type %T)", n->right->left, t);
|
||||
yyerror("invalid slice index %N (type %T)", n->right->left, t);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -759,7 +759,7 @@ reswitch:
|
||||
if((t = n->right->right->type) == T)
|
||||
goto error;
|
||||
if(!isint[t->etype]) {
|
||||
yyerror("invalid slice index %#N (type %T)", n->right->right, t);
|
||||
yyerror("invalid slice index %N (type %T)", n->right->right, t);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -783,7 +783,7 @@ reswitch:
|
||||
n->type = t;
|
||||
goto ret;
|
||||
}
|
||||
yyerror("cannot slice %#N (type %T)", l, t);
|
||||
yyerror("cannot slice %N (type %T)", l, t);
|
||||
goto error;
|
||||
|
||||
/*
|
||||
@ -793,7 +793,7 @@ reswitch:
|
||||
l = n->left;
|
||||
if(l->op == ONAME && (r = unsafenmagic(n)) != N) {
|
||||
if(n->isddd)
|
||||
yyerror("invalid use of ... with builtin %#N", l);
|
||||
yyerror("invalid use of ... with builtin %N", l);
|
||||
n = r;
|
||||
goto reswitch;
|
||||
}
|
||||
@ -801,7 +801,7 @@ reswitch:
|
||||
l = n->left;
|
||||
if(l->op == ONAME && l->etype != 0) {
|
||||
if(n->isddd && l->etype != OAPPEND)
|
||||
yyerror("invalid use of ... with builtin %#N", l);
|
||||
yyerror("invalid use of ... with builtin %N", l);
|
||||
// builtin: OLEN, OCAP, etc.
|
||||
n->op = l->etype;
|
||||
n->left = n->right;
|
||||
@ -851,7 +851,7 @@ reswitch:
|
||||
default:
|
||||
n->op = OCALLFUNC;
|
||||
if(t->etype != TFUNC) {
|
||||
yyerror("cannot call non-function %#N (type %T)", l, t);
|
||||
yyerror("cannot call non-function %N (type %T)", l, t);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
@ -872,7 +872,7 @@ reswitch:
|
||||
}
|
||||
// multiple return
|
||||
if(!(top & (Efnstruct | Etop))) {
|
||||
yyerror("multiple-value %#N() in single-value context", l);
|
||||
yyerror("multiple-value %N() in single-value context", l);
|
||||
goto ret;
|
||||
}
|
||||
n->type = getoutargx(l->type);
|
||||
@ -883,7 +883,7 @@ reswitch:
|
||||
case OREAL:
|
||||
case OIMAG:
|
||||
ok |= Erv;
|
||||
if(onearg(n, "%#O", n->op) < 0)
|
||||
if(onearg(n, "%O", n->op) < 0)
|
||||
goto error;
|
||||
typecheck(&n->left, Erv);
|
||||
defaultlit(&n->left, T);
|
||||
@ -949,7 +949,7 @@ reswitch:
|
||||
n->right = r;
|
||||
if(l->type->etype != r->type->etype) {
|
||||
badcmplx:
|
||||
yyerror("invalid operation: %#N (complex of types %T, %T)", n, l->type, r->type);
|
||||
yyerror("invalid operation: %N (complex of types %T, %T)", n, l->type, r->type);
|
||||
goto error;
|
||||
}
|
||||
switch(l->type->etype) {
|
||||
@ -973,7 +973,7 @@ reswitch:
|
||||
goto ret;
|
||||
|
||||
case OCLOSE:
|
||||
if(onearg(n, "%#O", n->op) < 0)
|
||||
if(onearg(n, "%O", n->op) < 0)
|
||||
goto error;
|
||||
typecheck(&n->left, Erv);
|
||||
defaultlit(&n->left, T);
|
||||
@ -981,7 +981,7 @@ reswitch:
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
if(t->etype != TCHAN) {
|
||||
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
|
||||
yyerror("invalid operation: %N (non-chan type %T)", n, t);
|
||||
goto error;
|
||||
}
|
||||
if(!(t->chan & Csend)) {
|
||||
@ -1107,7 +1107,7 @@ reswitch:
|
||||
if((t = n->left->type) == T || n->type == T)
|
||||
goto error;
|
||||
if((n->op = convertop(t, n->type, &why)) == 0) {
|
||||
yyerror("cannot convert %+N to type %T%s", n->left, n->type, why);
|
||||
yyerror("cannot convert %lN to type %T%s", n->left, n->type, why);
|
||||
n->op = OCONV;
|
||||
}
|
||||
switch(n->op) {
|
||||
@ -1311,7 +1311,7 @@ reswitch:
|
||||
typechecklist(n->ninit, Etop);
|
||||
typecheck(&n->ntest, Erv);
|
||||
if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
|
||||
yyerror("non-bool %+N used as for condition", n->ntest);
|
||||
yyerror("non-bool %lN used as for condition", n->ntest);
|
||||
typecheck(&n->nincr, Etop);
|
||||
typechecklist(n->nbody, Etop);
|
||||
goto ret;
|
||||
@ -1321,7 +1321,7 @@ reswitch:
|
||||
typechecklist(n->ninit, Etop);
|
||||
typecheck(&n->ntest, Erv);
|
||||
if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
|
||||
yyerror("non-bool %+N used as if condition", n->ntest);
|
||||
yyerror("non-bool %lN used as if condition", n->ntest);
|
||||
typechecklist(n->nbody, Etop);
|
||||
typechecklist(n->nelse, Etop);
|
||||
goto ret;
|
||||
@ -1408,21 +1408,21 @@ ret:
|
||||
goto error;
|
||||
}
|
||||
if((top & (Erv|Etype)) == Etype && n->op != OTYPE) {
|
||||
yyerror("%#N is not a type", n);
|
||||
yyerror("%N is not a type", n);
|
||||
goto error;
|
||||
}
|
||||
if((ok & Ecall) && !(top & Ecall)) {
|
||||
yyerror("method %#N is not an expression, must be called", n);
|
||||
yyerror("method %N is not an expression, must be called", n);
|
||||
goto error;
|
||||
}
|
||||
// TODO(rsc): simplify
|
||||
if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) {
|
||||
yyerror("%#N used as value", n);
|
||||
yyerror("%N used as value", n);
|
||||
goto error;
|
||||
}
|
||||
if((top & Etop) && !(top & (Ecall|Erv|Etype)) && !(ok & Etop)) {
|
||||
if(n->diag == 0) {
|
||||
yyerror("%#N not used", n);
|
||||
yyerror("%N not used", n);
|
||||
n->diag = 1;
|
||||
}
|
||||
goto error;
|
||||
@ -1435,7 +1435,7 @@ ret:
|
||||
goto out;
|
||||
|
||||
badcall1:
|
||||
yyerror("invalid argument %#N (type %T) for %#O", n->left, n->left->type, n->op);
|
||||
yyerror("invalid argument %lN for %O", n->left, n->op);
|
||||
goto error;
|
||||
|
||||
error:
|
||||
@ -1481,14 +1481,14 @@ onearg(Node *n, char *f, ...)
|
||||
va_start(arg, f);
|
||||
p = vsmprint(f, arg);
|
||||
va_end(arg);
|
||||
yyerror("missing argument to %s: %#N", p, n);
|
||||
yyerror("missing argument to %s: %N", p, n);
|
||||
return -1;
|
||||
}
|
||||
if(n->list->next != nil) {
|
||||
va_start(arg, f);
|
||||
p = vsmprint(f, arg);
|
||||
va_end(arg);
|
||||
yyerror("too many arguments to %s: %#N", p, n);
|
||||
yyerror("too many arguments to %s: %N", p, n);
|
||||
n->left = n->list->n;
|
||||
n->list = nil;
|
||||
return -1;
|
||||
@ -1504,17 +1504,17 @@ twoarg(Node *n)
|
||||
if(n->left != N)
|
||||
return 0;
|
||||
if(n->list == nil) {
|
||||
yyerror("missing argument to %#O - %#N", n->op, n);
|
||||
yyerror("missing argument to %O - %N", n->op, n);
|
||||
return -1;
|
||||
}
|
||||
n->left = n->list->n;
|
||||
if(n->list->next == nil) {
|
||||
yyerror("missing argument to %#O - %#N", n->op, n);
|
||||
yyerror("missing argument to %O - %N", n->op, n);
|
||||
n->list = nil;
|
||||
return -1;
|
||||
}
|
||||
if(n->list->next->next != nil) {
|
||||
yyerror("too many arguments to %#O - %#N", n->op, n);
|
||||
yyerror("too many arguments to %O - %N", n->op, n);
|
||||
n->list = nil;
|
||||
return -1;
|
||||
}
|
||||
@ -1583,7 +1583,7 @@ looktypedot(Node *n, Type *t, int dostrcmp)
|
||||
&& !isptr[t->etype]
|
||||
&& f2->embedded != 2
|
||||
&& !isifacemethod(f2->type)) {
|
||||
yyerror("invalid method expression %#N (needs pointer receiver: (*%T).%s)", n, t, f2->sym->name);
|
||||
yyerror("invalid method expression %N (needs pointer receiver: (*%T).%hS)", n, t, f2->sym);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1700,9 +1700,9 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
|
||||
exportassignok(tn->type, desc);
|
||||
if(assignop(tn->type, tl->type->type, &why) == 0) {
|
||||
if(call != N)
|
||||
yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type->type, call, why);
|
||||
yyerror("cannot use %T as type %T in argument to %N%s", tn->type, tl->type, call, why);
|
||||
else
|
||||
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type->type, desc, why);
|
||||
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
@ -1712,7 +1712,7 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
|
||||
exportassignok(tn->type, desc);
|
||||
if(assignop(tn->type, tl->type, &why) == 0) {
|
||||
if(call != N)
|
||||
yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type, call, why);
|
||||
yyerror("cannot use %T as type %T in argument to %N%s", tn->type, tl->type, call, why);
|
||||
else
|
||||
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
|
||||
}
|
||||
@ -1757,9 +1757,9 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
|
||||
goto toomany;
|
||||
if(isddd) {
|
||||
if(call != N)
|
||||
yyerror("invalid use of ... in call to %#N", call);
|
||||
yyerror("invalid use of ... in call to %N", call);
|
||||
else
|
||||
yyerror("invalid use of ... in %#O", op);
|
||||
yyerror("invalid use of ... in %O", op);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -1768,16 +1768,16 @@ out:
|
||||
|
||||
notenough:
|
||||
if(call != N)
|
||||
yyerror("not enough arguments in call to %#N", call);
|
||||
yyerror("not enough arguments in call to %N", call);
|
||||
else
|
||||
yyerror("not enough arguments to %#O", op);
|
||||
yyerror("not enough arguments to %O", op);
|
||||
goto out;
|
||||
|
||||
toomany:
|
||||
if(call != N)
|
||||
yyerror("too many arguments in call to %#N", call);
|
||||
yyerror("too many arguments in call to %N", call);
|
||||
else
|
||||
yyerror("too many arguments to %#O", op);
|
||||
yyerror("too many arguments to %O", op);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2159,7 +2159,7 @@ typecheckcomplit(Node **np)
|
||||
}
|
||||
s = l->left->sym;
|
||||
if(s == S) {
|
||||
yyerror("invalid field name %#N in struct initializer", l->left);
|
||||
yyerror("invalid field name %N in struct initializer", l->left);
|
||||
typecheck(&l->right, Erv);
|
||||
continue;
|
||||
}
|
||||
@ -2229,7 +2229,7 @@ static void
|
||||
checklvalue(Node *n, char *verb)
|
||||
{
|
||||
if(!islvalue(n))
|
||||
yyerror("cannot %s %#N", verb, n);
|
||||
yyerror("cannot %s %N", verb, n);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2241,7 +2241,7 @@ checkassign(Node *n)
|
||||
n->etype = 1;
|
||||
return;
|
||||
}
|
||||
yyerror("cannot assign to %#N", n);
|
||||
yyerror("cannot assign to %N", n);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2298,7 +2298,7 @@ checkassignto(Type *src, Node *dst)
|
||||
char *why;
|
||||
|
||||
if(assignop(src, dst->type, &why) == 0) {
|
||||
yyerror("cannot assign %T to %+N in multiple assignment%s", src, dst, why);
|
||||
yyerror("cannot assign %T to %lN in multiple assignment%s", src, dst, why);
|
||||
return;
|
||||
}
|
||||
exportassignok(dst->type, "multiple assignment");
|
||||
@ -2731,7 +2731,7 @@ typecheckdef(Node *n)
|
||||
goto ret;
|
||||
}
|
||||
if(!isideal(e->type) && !eqtype(t, e->type)) {
|
||||
yyerror("cannot use %+N as type %T in const initializer", e, t);
|
||||
yyerror("cannot use %lN as type %T in const initializer", e, t);
|
||||
goto ret;
|
||||
}
|
||||
convlit(&e, t);
|
||||
|
@ -80,7 +80,7 @@ no:
|
||||
return N;
|
||||
|
||||
bad:
|
||||
yyerror("invalid expression %#N", nn);
|
||||
yyerror("invalid expression %N", nn);
|
||||
v = 0;
|
||||
goto ret;
|
||||
|
||||
|
@ -284,7 +284,7 @@ walkstmt(Node **np)
|
||||
// OAS2FUNC in disguise
|
||||
f = n->list->n;
|
||||
if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER)
|
||||
fatal("expected return of call, have %#N", f);
|
||||
fatal("expected return of call, have %N", f);
|
||||
n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit));
|
||||
break;
|
||||
}
|
||||
@ -2189,7 +2189,7 @@ vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
|
||||
NodeList *args;
|
||||
|
||||
if(fn->type == T || fn->type->etype != TFUNC)
|
||||
fatal("mkcall %#N %T", fn, fn->type);
|
||||
fatal("mkcall %N %T", fn, fn->type);
|
||||
|
||||
args = nil;
|
||||
n = fn->type->intuple;
|
||||
|
@ -15,7 +15,7 @@ var (
|
||||
_ = sum()
|
||||
_ = sum(1.0, 2.0)
|
||||
_ = sum(1.5) // ERROR "integer"
|
||||
_ = sum("hello") // ERROR ".hello. .type string. as type int|incompatible"
|
||||
_ = sum("hello") // ERROR ".hello. .type ideal string. as type int|incompatible"
|
||||
_ = sum([]int{1}) // ERROR "\[\]int literal.*as type int|incompatible"
|
||||
)
|
||||
|
||||
|
@ -37,7 +37,7 @@ func main() {
|
||||
asBool(true)
|
||||
asBool(*&b)
|
||||
asBool(Bool(true))
|
||||
asBool(1 != 2) // ERROR "cannot use.*type bool.*as type Bool"
|
||||
asBool(1 != 2) // ERROR "cannot use.*type ideal bool.*as type Bool"
|
||||
asBool(i < j) // ERROR "cannot use.*type bool.*as type Bool"
|
||||
|
||||
_, b = m[2] // ERROR "cannot .* bool.*type Bool"
|
||||
|
Loading…
Reference in New Issue
Block a user