s = n->nname->sym;
on = s->oname;
+ // check for same types
+ if(on != N) {
+ if(eqtype(n->type, on->type, 0)) {
+ if(!eqargs(n->type, on->type))
+ yyerror("foreward declarations not the same: %S", s);
+ } else
+ yyerror("redeclare of function: %S", s);
+ }
+
// check for foreward declaration
if(on == N || !eqtype(n->type, on->type, 0)) {
// initial declaration or redeclaration
dump("gen: unknown op", n);
break;
- case ODCLTYPE:
- break;
-
case OLIST:
gen(n->left);
n = n->right;
cgen_asop(n->left, n->right, n->kaka);
break;
- case ODCLVAR:
- case OCOLAS:
case OAS:
cgen_as(n->left, n->right, n->op, n->kaka);
break;
gopcode(PCONV, PTNIL, nod(OCONV, n->type, nl->type));
break;
+ case OINDEXPTRSTR:
+ nl = n->left;
+ nr = n->right;
+ if(nl->addable) {
+ cgen(nr);
+ cgen(nl);
+ gopcode(PLOADI, PTADDR, N);
+ gopcodet(PINDEXZ, nr->type, N);
+ break;
+ }
+fatal("xxx");
+ break;
+
case OINDEXSTR:
nl = n->left;
nr = n->right;
gopcodet(PINDEXZ, nr->type, r);
break;
- case OSLICE:
+ case OSLICESTR:
+ case OSLICEPTRSTR:
nl = n->left; // name
nr = n->right;
} else
gopcode(PLOAD, PTADDR, nl);
+ if(n->op == OSLICEPTRSTR)
+ gopcode(PLOADI, PTADDR, N);
+
// offset in int reg
cgen(nr->left);
default:
fatal("cgen_as: unknown op %O", op);
- case ODCLVAR:
+ case OAS:
if(nr == N && nl->op == OLIST) {
kaka = PAS_SINGLE;
cgen_as(nl->left, nr, op, kaka);
nl = nl->right;
goto loop;
}
-
- case OCOLAS:
- case OAS:
switch(kaka) {
default:
yyerror("cgen_as: unknown param %d %d", kaka, PAS_CALLM);
ONAME,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
- ODCLFUNC, ODCLCONST, ODCLVAR,
- ODCLTYPE, ODCLFIELD, ODCLARG,
+ ODCLFUNC, ODCLFIELD, ODCLARG,
OLIST,
OPTR, OARRAY,
ORETURN, OFOR, OIF, OSWITCH,
- OAS, OASOP, OCOLAS, OCASE, OXCASE, OFALL, OXFALL,
+ OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL,
OGOTO, OPROC, ONEW, OPANIC, OPRINT, OEMPTY,
OOROR,
OADDR,
OIND,
OCALL, OCALLPTR, OCALLMETH, OCALLINTER,
- OINDEX, OINDEXPTR, OINDEXSTR, OINDEXMAP, OINDEXPTRMAP,
- OSLICE,
+ OINDEX, OINDEXSTR, OINDEXMAP,
+ OINDEXPTR, OINDEXPTRSTR, OINDEXPTRMAP,
+ OSLICE, OSLICESTR, OSLICEPTRSTR,
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
OLITERAL,
OCONV,
int isinter(Node*);
int isbytearray(Node*);
int eqtype(Node*, Node*, int);
+int eqargs(Node*, Node*);
ulong typehash(Node*, int);
void frame(int);
Node* literal(long);
%type <node> name name_name new_name new_name_list_r
%type <node> type new_type
%type <node> vardcl_list_r vardcl
-%type <node> constdcl_list_r constdcl
-%type <node> typedcl_list_r typedcl
%type <node> interfacedcl_list_r interfacedcl
%type <node> structdcl_list_r structdcl
%type <node> export_list_r export
}
| LCONST constdcl
{
- $$ = $2;
+ $$ = N;
iota = 0;
}
| LCONST '(' constdcl_list_r osemi ')'
{
- $$ = rev($3);
+ $$ = N;
iota = 0;
}
| LTYPE typedcl
{
- $$ = $2;
+ $$ = N;
}
| LTYPE '(' typedcl_list_r osemi ')'
{
- $$ = rev($3);
+ $$ = N;
}
vardcl:
$$ = rev($1);
dodclvar($$, $2);
- $$ = nod(ODCLVAR, $$, N);
- $$->type = $2;
+ $$ = nod(OAS, $$, N);
}
| new_name_list_r type '=' oexpr_list
{
$$ = rev($1);
dodclvar($$, $2);
- $$ = nod(ODCLVAR, $$, $4);
- $$->type = $2;
+ $$ = nod(OAS, $$, $4);
}
| new_name '=' expr
{
defaultlit($3);
dodclvar($1, $3->type);
- $$ = nod(ODCLVAR, $1, $3);
- $$->type = $3->type;
+ $$ = nod(OAS, $1, $3);
}
constdcl:
{
walktype($3, 0);
dodclconst($1, $3);
-
- $$ = nod(ODCLCONST, $1, $3);
iota += 1;
}
| new_name type '=' expr
walktype($4, 0);
convlit($4, $2);
dodclconst($1, $4);
-
- $$ = nod(ODCLCONST, $1, $4);
iota += 1;
}
new_type type
{
dodcltype($1, $2);
-
- $$ = nod(ODCLTYPE, $1, N);
- $$->type = $2;
}
/*
walktype($3, 0); // this is a little harry
defaultlit($3);
dodclvar($1, $3->type);
- $$ = nod(OCOLAS, $1, $3);
+
+ $$ = nod(OAS, $1, $3);
}
complex_stmt:
constdcl_list_r:
constdcl
| constdcl_list_r ';' constdcl
- {
- $$ = nod(OLIST, $1, $3);
- }
typedcl_list_r:
typedcl
| typedcl_list_r ';' typedcl
- {
- $$ = nod(OLIST, $1, $3);
- }
structdcl_list_r:
structdcl
[OXCASE] = "XCASE",
[OFALL] = "FALL",
[OCONV] = "CONV",
- [OCOLAS] = "COLAS",
[OCOM] = "COM",
[OCONST] = "CONST",
[OCONTINUE] = "CONTINUE",
[ODCLARG] = "DCLARG",
- [ODCLCONST] = "DCLCONST",
[ODCLFIELD] = "DCLFIELD",
[ODCLFUNC] = "DCLFUNC",
- [ODCLTYPE] = "DCLTYPE",
- [ODCLVAR] = "DCLVAR",
[ODIV] = "DIV",
[ODOT] = "DOT",
[ODOTPTR] = "DOTPTR",
[OINDEX] = "INDEX",
[OINDEXPTR] = "INDEXPTR",
[OINDEXSTR] = "INDEXSTR",
+ [OINDEXPTRSTR] = "INDEXPTRSTR",
[OINDEXMAP] = "INDEXMAP",
[OINDEXPTRMAP] = "INDEXPTRMAP",
[OIND] = "IND",
[ORETURN] = "RETURN",
[ORSH] = "RSH",
[OSLICE] = "SLICE",
+ [OSLICESTR] = "SLICESTR",
+ [OSLICEPTRSTR] = "SLICEPTRSTR",
[OSUB] = "SUB",
[OSWITCH] = "SWITCH",
[OTYPE] = "TYPE",
if(t1->nname != N && t1->nname->sym != S) {
if(t2->nname == N || t2->nname->sym == S)
return 0;
- if(strcmp(t1->nname->sym->name, t2->nname->sym->name) != 0)
- return 0;
+ if(strcmp(t1->nname->sym->name, t2->nname->sym->name) != 0) {
+ // assigned names dont count
+ if(t1->nname->sym->name[0] != '_' ||
+ t2->nname->sym->name[0] != '_')
+ return 0;
+ }
}
t1 = t1->down;
t2 = t2->down;
return eqtype(t1->type, t2->type, d+1);
}
+/*
+ * are the arg names of two
+ * functions the same. we know
+ * that eqtype has been called
+ * and has returned true.
+ */
+int
+eqargs(Node *t1, Node *t2)
+{
+ if(t1 == t2)
+ return 1;
+ if(t1 == N || t2 == N)
+ return 0;
+ if(t1->op != OTYPE || t2->op != OTYPE)
+ fatal("eqargs: oops %O %O", t1->op, t2->op);
+
+ if(t1->etype != t2->etype)
+ return 0;
+
+ if(t1->etype != TFUNC)
+ fatal("eqargs: oops %E", t1->etype);
+
+ t1 = t1->type;
+ t2 = t2->type;
+ for(;;) {
+ if(t1 == t2)
+ break;
+ if(!eqtype(t1, t2, 0))
+ return 0;
+ t1 = t1->down;
+ t2 = t2->down;
+ }
+ return 1;
+}
+
ulong
typehash(Node *at, int d)
{
fatal("walktype: switch 1 unknown op %N", n);
goto ret;
- case ODCLTYPE:
- goto ret;
-
case OPANIC:
case OPRINT:
walktype(n->left, 0);
ascompatte(n->op, getinarg(t), &n->right);
goto ret;
- case OCOLAS:
- case ODCLVAR:
case OAS:
if(!top)
goto nottop;
goto ret;
}
+ // left side is ptr to string
+ if(isptrto(t, TPTR) && isptrto(t->type, TSTRING)) {
+ n->op = OINDEXPTRSTR;
+ n->type = types[TUINT8];
+ goto ret;
+ }
+
// left side is array
if(t->etype == TPTR) {
t = t->type;
if(n->left == N || n->right == N)
return;
- walktype(n->left, 0);
- if(!isptrto(n->left->type, TSTRING)) {
- badtype(OSLICE, n->left->type, N);
- return;
- }
if(n->right->op != OLIST)
fatal("slice not a list");
+ walktype(n->left, 0);
+ if(isptrto(n->left->type, TSTRING)) {
+ n->op = OSLICESTR;
+ goto ok;
+ }
+ if(isptrto(n->left->type->type, TPTR) && isptrto(n->left->type->type, TSTRING)) {
+ n->op = OSLICEPTRSTR;
+ goto ok;
+ }
+
+ badtype(OSLICE, n->left->type, N);
+ return;
+
+ok:
// check for type errors
walktype(n->right, 0);
l = n->right->left;