Commit 66a603c9 authored by Ken Thompson's avatar Ken Thompson

arrays

R=r
OCL=14603
CL=14603
parent 30fd44cf
...@@ -157,12 +157,14 @@ dowidth(Type *t) ...@@ -157,12 +157,14 @@ dowidth(Type *t)
case TSTRING: // implemented as pointer case TSTRING: // implemented as pointer
w = wptr; w = wptr;
break; break;
case TARRAY:
case TDARRAY: case TDARRAY:
fatal("width of a dynamic array");
case TARRAY:
if(t->type == T) if(t->type == T)
break; break;
dowidth(t->type); dowidth(t->type);
w = t->bound * t->type->width; w = t->bound * t->type->width
;// + offsetof(Array, b[0]);
break; break;
case TSTRUCT: case TSTRUCT:
......
...@@ -136,6 +136,20 @@ cgen(Node *n, Node *res) ...@@ -136,6 +136,20 @@ cgen(Node *n, Node *res)
} }
regalloc(&n1, nl->type, res); regalloc(&n1, nl->type, res);
cgen(nl, &n1); cgen(nl, &n1);
if(isptrto(n->type, TARRAY) && isptrto(nl->type, TDARRAY)) {
// convert dynamic array to static array
n2 = n1;
n2.op = OINDREG;
n2.xoffset = offsetof(Array,array);
n2.type = types[tptr];
gins(AMOVQ, &n2, &n1);
}
if(isptrto(n->type, TDARRAY) && isptrto(nl->type, TARRAY)) {
// conver static array to dynamic array
// it is assumed that the dope is just before the array
nodconst(&n2, types[tptr], offsetof(Array,b));
gins(ASUBQ, &n2, &n1);
}
gmove(&n1, res); gmove(&n1, res);
regfree(&n1); regfree(&n1);
break; break;
...@@ -173,9 +187,33 @@ cgen(Node *n, Node *res) ...@@ -173,9 +187,33 @@ cgen(Node *n, Node *res)
regfree(&n1); regfree(&n1);
break; break;
} }
if(isptrto(nl->type, TDARRAY)) {
regalloc(&n1, types[tptr], res);
cgen(nl, &n1);
n1.op = OINDREG;
n1.type = types[TUINT32];
n1.xoffset = offsetof(Array,nel);
gmove(&n1, res);
regfree(&n1);
break;
}
fatal("cgen: OLEN: unknown type %lT", nl->type); fatal("cgen: OLEN: unknown type %lT", nl->type);
break; break;
case OCAP:
if(isptrto(nl->type, TDARRAY)) {
regalloc(&n1, types[tptr], res);
cgen(nl, &n1);
n1.op = OINDREG;
n1.type = types[TUINT32];
n1.xoffset = offsetof(Array,cap);
gmove(&n1, res);
regfree(&n1);
break;
}
fatal("cgen: OCAP: unknown type %lT", nl->type);
break;
case OADDR: case OADDR:
agen(nl, res); agen(nl, res);
break; break;
...@@ -253,6 +291,7 @@ agen(Node *n, Node *res) ...@@ -253,6 +291,7 @@ agen(Node *n, Node *res)
{ {
Node *nl, *nr; Node *nl, *nr;
Node n1, n2, n3, tmp; Node n1, n2, n3, tmp;
Prog *p1;
uint32 w; uint32 w;
Type *t; Type *t;
...@@ -347,15 +386,60 @@ agen(Node *n, Node *res) ...@@ -347,15 +386,60 @@ agen(Node *n, Node *res)
// &a is in res // &a is in res
// i is in &n1 // i is in &n1
// w is width // w is width
nodconst(&n3, types[TINT64], w); // w/tint64
if(isptrto(nl->type, TDARRAY)) {
regalloc(&n2, types[tptr], res);
gmove(res, &n2);
if(!debug['B']) {
// check bounds
n3 = n2;
n3.op = OINDREG;
n3.type = types[tptr];
n3.xoffset = offsetof(Array, nel);
gins(optoas(OCMP, types[TUINT32]), &n1, &n3);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
nodconst(&n3, types[TUINT8], 5); // 5 is range trap
gins(AINT, &n3, N);
patch(p1, pc);
}
// fetch array base from dope
n3 = n2;
n3.op = OINDREG;
n3.type = types[tptr];
n3.xoffset = offsetof(Array, array);
gins(AMOVQ, &n3, &n2);
gmove(&n2, res);
regfree(&n2);
} else
if(!debug['B']) {
// check bounds
nodconst(&n3, types[TUINT32], nl->type->bound);
if(isptrto(nl->type, TARRAY))
nodconst(&n3, types[TUINT32], nl->type->type->bound);
gins(optoas(OCMP, types[TUINT32]), &n1, &n3);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
nodconst(&n3, types[TUINT8], 5); // 5 is range trap
gins(AINT, &n3, N);
patch(p1, pc);
}
t = types[TUINT64];
if(issigned[n1.type->etype]) if(issigned[n1.type->etype])
regalloc(&n2, types[TINT64], &n1); // i/int64 t = types[TINT64];
else
regalloc(&n2, types[TUINT64], &n1); // i/uint64 regalloc(&n2, t, &n1); // i
gmove(&n1, &n2); gmove(&n1, &n2);
gins(optoas(OMUL, types[TINT64]), &n3, &n2);
gins(optoas(OADD, types[tptr]), &n2, res);
regfree(&n1); regfree(&n1);
nodconst(&n3, t, w); // w
gins(optoas(OMUL, t), &n3, &n2);
gins(optoas(OADD, types[tptr]), &n2, res);
regfree(&n2); regfree(&n2);
break; break;
......
...@@ -147,12 +147,17 @@ dumpexporttype(Sym *s) ...@@ -147,12 +147,17 @@ dumpexporttype(Sym *s)
break; break;
case TARRAY: case TARRAY:
case TDARRAY:
reexport(t->type); reexport(t->type);
/* type 2 */ /* type 2 */
Bprint(bout, "\ttype "); Bprint(bout, "\ttype ");
if(s->export != 0) if(s->export != 0)
Bprint(bout, "!"); Bprint(bout, "!");
if(et == TDARRAY) {
Bprint(bout, "%lS [] %lS\n", s, t->type->sym);
break;
}
Bprint(bout, "%lS [%lud] %lS\n", s, t->bound, t->type->sym); Bprint(bout, "%lS [%lud] %lS\n", s, t->bound, t->type->sym);
break; break;
...@@ -517,8 +522,13 @@ doimport2(Node *ss, Val *b, Node *st) ...@@ -517,8 +522,13 @@ doimport2(Node *ss, Val *b, Node *st)
Type *t; Type *t;
Sym *s; Sym *s;
t = typ(TARRAY); if(b == nil) {
t->bound = mpgetfix(b->u.xval); t = typ(TDARRAY);
t->dbound = N;
} else {
t = typ(TARRAY);
t->bound = mpgetfix(b->u.xval);
}
s = pkglookup(st->sym->name, st->psym->name); s = pkglookup(st->sym->name, st->psym->name);
t->type = s->otype; t->type = s->otype;
......
...@@ -3,11 +3,6 @@ ...@@ -3,11 +3,6 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
/* /*
todo:
1. dyn arrays
2. multi
tothinkabout:
2. argument in import
*/ */
#include <u.h> #include <u.h>
...@@ -55,6 +50,21 @@ struct String ...@@ -55,6 +50,21 @@ struct String
char s[3]; // variable char s[3]; // variable
}; };
/*
* note this is the runtime representation
* of the compilers arrays. it is probably
* insafe to use it this way, but it puts
* all the changes in one place.
*/
typedef struct Array Array;
struct Array
{ // must not move anything
uchar array[8]; // pointer to data
uint32 nel; // number of elements
uint32 cap; // allocated number of elements
uchar b; // actual array - may not be contig
};
enum enum
{ {
Mpscale = 29, /* safely smaller than bits in a long */ Mpscale = 29, /* safely smaller than bits in a long */
...@@ -131,6 +141,7 @@ struct Type ...@@ -131,6 +141,7 @@ struct Type
// TARRAY // TARRAY
int32 bound; int32 bound;
Node* dbound;
}; };
#define T ((Type*)0) #define T ((Type*)0)
...@@ -251,7 +262,7 @@ enum ...@@ -251,7 +262,7 @@ enum
ORETURN, OFOR, OIF, OSWITCH, OI2S, OS2I, OI2I, ORETURN, OFOR, OIF, OSWITCH, OI2S, OS2I, OI2I,
OAS, OASOP, OCASE, OXCASE, OSCASE, OFALL, OXFALL, OAS, OASOP, OCASE, OXCASE, OSCASE, OFALL, OXFALL,
OGOTO, OPROC, ONEW, OEMPTY, OSELECT, OGOTO, OPROC, ONEW, OEMPTY, OSELECT,
OLEN, OPANIC, OPRINT, OTYPEOF, OLEN, OCAP, OPANIC, OPRINT, OTYPEOF,
OOROR, OOROR,
OANDAND, OANDAND,
...@@ -669,6 +680,7 @@ Type* fixmap(Type*); ...@@ -669,6 +680,7 @@ Type* fixmap(Type*);
Node* mapop(Node*, int); Node* mapop(Node*, int);
Type* fixchan(Type*); Type* fixchan(Type*);
Node* chanop(Node*, int); Node* chanop(Node*, int);
Node* arrayop(Node*, int);
Node* isandss(Type*, Node*); Node* isandss(Type*, Node*);
Node* convas(Node*); Node* convas(Node*);
void arrayconv(Type*, Node*); void arrayconv(Type*, Node*);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
%token <sym> LPACKAGE LIMPORT LEXPORT %token <sym> LPACKAGE LIMPORT LEXPORT
%token <sym> LMAP LCHAN LINTERFACE LFUNC LSTRUCT %token <sym> LMAP LCHAN LINTERFACE LFUNC LSTRUCT
%token <sym> LCOLAS LFALL LRETURN %token <sym> LCOLAS LFALL LRETURN
%token <sym> LNEW LLEN LTYPEOF LPANIC LPRINT %token <sym> LNEW LLEN LCAP LTYPEOF LPANIC LPRINT
%token <sym> LVAR LTYPE LCONST LCONVERT LSELECT %token <sym> LVAR LTYPE LCONST LCONVERT LSELECT
%token <sym> LFOR LIF LELSE LSWITCH LCASE LDEFAULT %token <sym> LFOR LIF LELSE LSWITCH LCASE LDEFAULT
%token <sym> LBREAK LCONTINUE LGO LGOTO LRANGE %token <sym> LBREAK LCONTINUE LGO LGOTO LRANGE
...@@ -733,6 +733,10 @@ pexpr: ...@@ -733,6 +733,10 @@ pexpr:
{ {
$$ = nod(OLEN, $3, N); $$ = nod(OLEN, $3, N);
} }
| LCAP '(' expr ')'
{
$$ = nod(OCAP, $3, N);
}
| LTYPEOF '(' type ')' | LTYPEOF '(' type ')'
{ {
$$ = nod(OTYPEOF, N, N); $$ = nod(OTYPEOF, N, N);
...@@ -852,6 +856,7 @@ key: ...@@ -852,6 +856,7 @@ key:
| LFALSE | LFALSE
| LIOTA | LIOTA
| LLEN | LLEN
| LCAP
| LPANIC | LPANIC
| LPRINT | LPRINT
| LNEW | LNEW
...@@ -1519,6 +1524,11 @@ hidden_import: ...@@ -1519,6 +1524,11 @@ hidden_import:
// type array // type array
doimport2($2, &$4, $6); doimport2($2, &$4, $6);
} }
| LTYPE hidden_importsym '[' ']' hidden_importsym
{
// type array
doimport2($2, nil, $5);
}
| LTYPE hidden_importsym '(' ohidden_importsym_list ')' | LTYPE hidden_importsym '(' ohidden_importsym_list ')'
{ {
// type function // type function
......
...@@ -998,6 +998,7 @@ static struct ...@@ -998,6 +998,7 @@ static struct
"map", LMAP, Txxx, "map", LMAP, Txxx,
"new", LNEW, Txxx, "new", LNEW, Txxx,
"len", LLEN, Txxx, "len", LLEN, Txxx,
"cap", LCAP, Txxx,
"nil", LNIL, Txxx, "nil", LNIL, Txxx,
"package", LPACKAGE, Txxx, "package", LPACKAGE, Txxx,
"panic", LPANIC, Txxx, "panic", LPANIC, Txxx,
......
...@@ -374,27 +374,39 @@ Type* ...@@ -374,27 +374,39 @@ Type*
aindex(Node *b, Type *t) aindex(Node *b, Type *t)
{ {
Type *r; Type *r;
int bound;
r = typ(TARRAY);
r->type = t;
if(t->etype == TDARRAY)
yyerror("dynamic array type cannot be a dynamic array");
walktype(b, Erv); walktype(b, Erv);
switch(whatis(b)) { switch(whatis(b)) {
default: default: // variable bound
yyerror("array bound must be a constant integer expression"); walktype(b, Erv);
if(b->type != T && isint[b->type->etype])
goto dyn;
yyerror("array bound must be an integer expression");
bound = 0;
break; break;
case Wnil: // default zero lb case Wnil: // open bound
r->bound = 0; goto dyn;
break;
case Wlitint: // fixed lb case Wlitint: // fixed bound
r->bound = mpgetfix(b->val.u.xval); bound = mpgetfix(b->val.u.xval);
break; break;
} }
// fixed array
r = typ(TARRAY);
r->type = t;
r->dbound = b;
r->bound = bound;
return r;
dyn:
// dynamic array
r = typ(TDARRAY);
r->type = t;
r->dbound = b;
r->bound = 0;
return r; return r;
} }
...@@ -641,6 +653,7 @@ opnames[] = ...@@ -641,6 +653,7 @@ opnames[] =
[OLABEL] = "LABEL", [OLABEL] = "LABEL",
[OLE] = "LE", [OLE] = "LE",
[OLEN] = "LEN", [OLEN] = "LEN",
[OCAP] = "CAP",
[OLIST] = "LIST", [OLIST] = "LIST",
[OLITERAL] = "LITERAL", [OLITERAL] = "LITERAL",
[OLSH] = "LSH", [OLSH] = "LSH",
...@@ -1001,6 +1014,8 @@ Tconv(Fmt *fp) ...@@ -1001,6 +1014,8 @@ Tconv(Fmt *fp)
case TDARRAY: case TDARRAY:
snprint(buf1, sizeof(buf1), "[]%T", t->type); snprint(buf1, sizeof(buf1), "[]%T", t->type);
if(t->dbound != N)
snprint(buf1, sizeof(buf1), "[<expr>]%T", t->type);
strncat(buf, buf1, sizeof(buf)); strncat(buf, buf1, sizeof(buf));
break; break;
...@@ -1229,7 +1244,6 @@ eqtype(Type *t1, Type *t2, int d) ...@@ -1229,7 +1244,6 @@ eqtype(Type *t1, Type *t2, int d)
{ {
if(d >= 10) if(d >= 10)
return 1; return 1;
if(t1 == t2) if(t1 == t2)
return 1; return 1;
if(t1 == T || t2 == T) if(t1 == T || t2 == T)
...@@ -1279,6 +1293,11 @@ eqtype(Type *t1, Type *t2, int d) ...@@ -1279,6 +1293,11 @@ eqtype(Type *t1, Type *t2, int d)
t2 = t2->down; t2 = t2->down;
} }
return 1; return 1;
case TARRAY:
if(t1->bound == t2->bound)
break;
return 0;
} }
return eqtype(t1->type, t2->type, d+1); return eqtype(t1->type, t2->type, d+1);
} }
...@@ -1304,6 +1323,8 @@ loop: ...@@ -1304,6 +1323,8 @@ loop:
case TPTR32: case TPTR32:
case TPTR64: case TPTR64:
case TCHAN: case TCHAN:
case TARRAY:
case TDARRAY:
stp = &st->type; stp = &st->type;
goto loop; goto loop;
...@@ -1373,6 +1394,8 @@ deep(Type *t) ...@@ -1373,6 +1394,8 @@ deep(Type *t)
case TPTR32: case TPTR32:
case TPTR64: case TPTR64:
case TCHAN: case TCHAN:
case TARRAY:
case TDARRAY:
nt = shallow(t); nt = shallow(t);
nt->type = deep(t->type); nt->type = deep(t->type);
break; break;
......
...@@ -56,6 +56,11 @@ func selectsend(sel *byte, hchan *chan any, elem any) (selected bool); ...@@ -56,6 +56,11 @@ func selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
func selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool); func selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
func selectgo(sel *byte); func selectgo(sel *byte);
func newarray(nel uint32, cap uint32, width uint32) (ary *[]any);
func arraysliced(old *[]any, lb uint32, hb uint32, width uint32) (ary *[]any);
func arrayslices(old *any, nel uint32, lb uint32, hb uint32, width uint32) (ary *[]any);
func arrays2d(old *any, nel uint32) (ary *[]any);
func gosched(); func gosched();
func goexit(); func goexit();
...@@ -124,6 +129,12 @@ export ...@@ -124,6 +129,12 @@ export
selectrecv selectrecv
selectgo selectgo
// dynamic arrays
newarray
arraysliced
arrayslices
arrays2d
// go routines // go routines
gosched gosched
goexit goexit
......
This diff is collapsed.
...@@ -429,17 +429,20 @@ loop: ...@@ -429,17 +429,20 @@ loop:
} }
} }
if(t->etype == TARRAY) { // convert dynamic to static generated by ONEW
arrayconv(t, l); if(isptrto(t, TARRAY) && isptrto(l->type, TDARRAY))
goto ret; goto ret;
}
// if(t->etype == TARRAY) {
// arrayconv(t, l);
// goto ret;
// }
r = isandss(n->type, l); r = isandss(n->type, l);
if(r != N) { if(r != N) {
*n = *r; *n = *r;
goto ret; goto ret;
} }
badtype(n->op, l->type, t); badtype(n->op, l->type, t);
goto ret; goto ret;
...@@ -566,6 +569,28 @@ loop: ...@@ -566,6 +569,28 @@ loop:
n->type = types[TINT32]; n->type = types[TINT32];
goto ret; goto ret;
case OCAP:
if(top != Erv)
goto nottop;
walktype(n->left, Erv);
evconst(n);
t = n->left->type;
if(t != T && isptr[t->etype])
t = t->type;
if(t == T)
goto ret;
switch(t->etype) {
default:
goto badt;
case TDARRAY:
break;
case TARRAY:
nodconst(n, types[TINT32], t->bound);
break;
}
n->type = types[TINT32];
goto ret;
case OINDEX: case OINDEX:
case OINDEXPTR: case OINDEXPTR:
if(top == Etop) if(top == Etop)
...@@ -627,8 +652,8 @@ loop: ...@@ -627,8 +652,8 @@ loop:
*n = *mapop(n, top); *n = *mapop(n, top);
break; break;
case TARRAY:
case TDARRAY: case TDARRAY:
case TARRAY:
// right side must be an int // right side must be an int
if(n->right->type == T) { if(n->right->type == T) {
convlit(n->right, types[TINT32]); convlit(n->right, types[TINT32]);
...@@ -672,10 +697,17 @@ loop: ...@@ -672,10 +697,17 @@ loop:
walktype(n->right, Erv); walktype(n->right, Erv);
if(n->left == N || n->right == N) if(n->left == N || n->right == N)
goto ret; goto ret;
if(isptrto(n->left->type, TSTRING)) { t = n->left->type;
if(isptr[t->etype])
t = t->type;
if(t->etype == TSTRING) {
*n = *stringop(n, top); *n = *stringop(n, top);
goto ret; goto ret;
} }
if(t->etype == TDARRAY || t->etype == TARRAY) {
*n = *arrayop(n, top);
goto ret;
}
badtype(OSLICE, n->left->type, T); badtype(OSLICE, n->left->type, T);
goto ret; goto ret;
...@@ -1403,6 +1435,9 @@ ascompat(Type *t1, Type *t2) ...@@ -1403,6 +1435,9 @@ ascompat(Type *t1, Type *t2)
if(isptrto(t1, TSTRUCT)) if(isptrto(t1, TSTRUCT))
return 1; return 1;
if(isptrto(t1, TDARRAY))
if(isptrto(t2, TARRAY))
return 1;
return 0; return 0;
} }
...@@ -1498,13 +1533,19 @@ newcompat(Node *n) ...@@ -1498,13 +1533,19 @@ newcompat(Node *n)
fatal("newcompat: type should be pointer %lT", t); fatal("newcompat: type should be pointer %lT", t);
t = t->type; t = t->type;
if(t->etype == TMAP) { switch(t->etype) {
case TMAP:
r = mapop(n, Erv); r = mapop(n, Erv);
return r; return r;
}
if(t->etype == TCHAN) { case TCHAN:
r = chanop(n, Erv); r = chanop(n, Erv);
return r; return r;
case TDARRAY:
case TARRAY:
r = arrayop(n, Erv);
return r;
} }
if(n->left != N) if(n->left != N)
...@@ -2082,6 +2123,168 @@ shape: ...@@ -2082,6 +2123,168 @@ shape:
return N; return N;
} }
Type*
fixarray(Type *tm)
{
Type *t;
t = tm->type;
if(t == T) {
fatal("fixarray: t nil");
return T;
}
if(t->etype != TDARRAY && t->etype != TARRAY) {
fatal("fixarray: %lT not array", tm);
return T;
}
if(t->type == T) {
fatal("fixarray: array element type is nil");
return T;
}
dowidth(t->type);
return t;
}
Node*
arrayop(Node *n, int top)
{
Node *r, *a;
Type *t;
Node *on;
Iter save;
r = n;
switch(n->op) {
default:
fatal("darrayop: unknown op %O", n->op);
case ONEW:
// newarray(nel uint32, max uint32, width uint32) (ary *[]any)
t = fixarray(n->type);
a = nodintconst(t->type->width); // width
a = nod(OCONV, a, N);
a->type = types[TUINT32];
r = a;
a = listfirst(&save, &n->left); // max
if(a == N)
a = nodintconst(0);
a = nod(OCONV, a, N);
a->type = types[TUINT32];
r = list(a, r);
a = t->dbound; // nel
if(a == N)
a = nodintconst(t->bound);
a = nod(OCONV, a, N);
a->type = types[TUINT32];
r = list(a, r);
on = syslook("newarray", 1);
argtype(on, t->type); // any-1
r = nod(OCALL, on, r);
walktype(r, top);
if(t->etype == TARRAY) {
// single case when we can convert a dynamic
// array pointer to a static array pointer
// saves making a sys function to alloc a static
r = nod(OCONV, r, N);
r->type = ptrto(t);
}
break;
case OAS:
// arrays2d(old *any, nel uint32) (ary *[]any)
t = fixarray(n->right->type);
a = nodintconst(t->bound); // nel
a = nod(OCONV, a, N);
a->type = types[TUINT32];
r = a;
a = n->right; // old
r = list(a, r);
on = syslook("arrays2d", 1);
argtype(on, n->right->type->type); // any-1
argtype(on, t->type); // any-2
r = nod(OCALL, on, r);
walktype(r, top);
n->right = r;
return n;
case OSLICE:
if(isptrto(n->left->type, TARRAY))
goto slicestatic;
// arrayslices(old *[]any, lb uint32, hb uint32, width uint32) (ary *[]any)
t = fixarray(n->left->type);
a = nodintconst(t->type->width); // width
a = nod(OCONV, a, N);
a->type = types[TUINT32];
r = a;
a = nod(OCONV, n->right->right, N); // hb
a->type = types[TUINT32];
r = list(a, r);
a = nod(OCONV, n->right->left, N); // lb
a->type = types[TINT32];
r = list(a, r);
a = n->left; // old
r = list(a, r);
on = syslook("arraysliced", 1);
argtype(on, t->type); // any-1
argtype(on, t->type); // any-2
r = nod(OCALL, on, r);
walktype(r, top);
break;
slicestatic:
// arrayslices(old *any, nel uint32, lb uint32, hb uint32, width uint32) (ary *[]any)
t = fixarray(n->left->type);
a = nodintconst(t->type->width); // width
a = nod(OCONV, a, N);
a->type = types[TUINT32];
r = a;
a = nod(OCONV, n->right->right, N); // hb
a->type = types[TUINT32];
r = list(a, r);
a = nod(OCONV, n->right->left, N); // lb
a->type = types[TINT32];
r = list(a, r);
a = nodintconst(t->bound); // nel
a = nod(OCONV, a, N);
a->type = types[TINT32];
r = list(a, r);
a = n->left; // old
r = list(a, r);
on = syslook("arrayslices", 1);
argtype(on, t); // any-1
argtype(on, t->type); // any-2
r = nod(OCALL, on, r);
walktype(r, top);
break;
}
return r;
}
void void
diagnamed(Type *t) diagnamed(Type *t)
{ {
...@@ -2178,37 +2381,48 @@ convas(Node *n) ...@@ -2178,37 +2381,48 @@ convas(Node *n)
return n; return n;
} }
if(isptrto(lt, TDARRAY) && isptrto(rt, TARRAY)) {
if(!eqtype(lt->type->type, rt->type->type, 0))
goto bad;
*n = *arrayop(n, Etop);
return n;
}
if(ascompat(lt, rt))
return n;
bad:
badtype(n->op, lt, rt); badtype(n->op, lt, rt);
return n; return n;
} }
void //void
arrayconv(Type *t, Node *n) //arrayconv(Type *t, Node *n)
{ //{
int c; // int c;
Iter save; // Iter save;
Node *l; // Node *l;
//
l = listfirst(&save, &n); // l = listfirst(&save, &n);
c = 0; // c = 0;
//
loop: //loop:
if(l == N) { // if(l == N) {
if(t->bound == 0) // if(t->bound == 0)
t->bound = c; // t->bound = c;
if(t->bound == 0 || t->bound < c) // if(t->bound == 0 || t->bound < c)
yyerror("error with array convert bounds"); // yyerror("error with array convert bounds");
return; // return;
} // }
//
c++; // c++;
walktype(l, Erv); // walktype(l, Erv);
convlit(l, t->type); // convlit(l, t->type);
if(!ascompat(l->type, t->type)) // if(!ascompat(l->type, t->type))
badtype(OARRAY, l->type, t->type); // badtype(OARRAY, l->type, t->type);
l = listnext(&save); // l = listnext(&save);
goto loop; // goto loop;
} //}
Node* Node*
old2new(Node *n, Type *t) old2new(Node *n, Type *t)
......
...@@ -20,6 +20,7 @@ LIBOFILES=\ ...@@ -20,6 +20,7 @@ LIBOFILES=\
runtime.$O\ runtime.$O\
map.$O\ map.$O\
chan.$O\ chan.$O\
array.$O\
print.$O\ print.$O\
rune.$O\ rune.$O\
proc.$O\ proc.$O\
......
// 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 "runtime.h"
static int32 debug = 0;
// newarray(nel uint32, cap uint32, width uint32) (ary *[]any);
void
sys·newarray(uint32 nel, uint32 cap, uint32 width, Array* ret)
{
Array *d;
uint64 size;
if(cap < nel)
cap = nel;
size = cap*width;
d = mal(sizeof(*d) - sizeof(d->b) + size);
d->nel = nel;
d->cap = cap;
d->array = d->b;
ret = d;
FLUSH(&d);
if(debug) {
prints("newarray: nel=");
sys·printint(nel);
prints("; cap=");
sys·printint(cap);
prints("; width=");
sys·printint(width);
prints("; ret=");
sys·printpointer(ret);
prints("\n");
}
}
// arraysliced(old *[]any, lb uint32, hb uint32, width uint32) (ary *[]any);
void
sys·arraysliced(Array* old, uint32 lb, uint32 hb, uint32 width, Array* ret)
{
Array *d;
if(hb > old->cap || lb > hb) {
if(debug) {
prints("sys·arrayslices: old=");
sys·printpointer(old);
prints("; lb=");
sys·printint(lb);
prints("; hb=");
sys·printint(hb);
prints("; width=");
sys·printint(width);
prints("\n");
prints("oldarray: nel=");
sys·printint(old->nel);
prints("; cap=");
sys·printint(old->cap);
prints("\n");
}
throw("sys·arraysliced: new size exceeds old size");
}
// new array is inside old array
d = mal(sizeof(*d) - sizeof(d->b));
d->nel = hb-lb;
d->cap = old->cap - lb;
d->array = old->array + lb*width;
ret = d;
FLUSH(&d);
if(debug) {
prints("sys·arrayslices: old=");
sys·printpointer(old);
prints("; lb=");
sys·printint(lb);
prints("; hb=");
sys·printint(hb);
prints("; width=");
sys·printint(width);
prints("; ret=");
sys·printpointer(ret);
prints("\n");
}
}
// arrayslices(old *any, nel uint32, lb uint32, hb uint32, width uint32) (ary *[]any);
void
sys·arrayslices(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Array* ret)
{
Array *d;
if(hb > nel || lb > hb) {
if(debug) {
prints("sys·arrayslices: old=");
sys·printpointer(old);
prints("; nel=");
sys·printint(nel);
prints("; lb=");
sys·printint(lb);
prints("; hb=");
sys·printint(hb);
prints("; width=");
sys·printint(width);
prints("\n");
}
throw("sys·arrayslices: new size exceeds cap");
}
// new array is inside old array
d = mal(sizeof(*d) - sizeof(d->b));
d->nel = hb-lb;
d->cap = nel-lb;
d->array = old + lb*width;
ret = d;
FLUSH(&d);
if(debug) {
prints("sys·arrayslices: old=");
sys·printpointer(old);
prints("; nel=");
sys·printint(nel);
prints("; lb=");
sys·printint(lb);
prints("; hb=");
sys·printint(hb);
prints("; width=");
sys·printint(width);
prints("; ret=");
sys·printpointer(ret);
prints("\n");
}
}
// arrays2d(old *any, nel uint32) (ary *[]any)
void
sys·arrays2d(byte* old, uint32 nel, Array* ret)
{
Array *d;
// new dope to old array
d = mal(sizeof(*d) - sizeof(d->b));
d->nel = nel;
d->cap = nel;
d->array = old;
ret = d;
FLUSH(&d);
if(debug) {
prints("sys·arrays2d: old=");
sys·printpointer(old);
prints("; nel=");
sys·printint(nel);
prints("; ret=");
sys·printpointer(ret);
prints("\n");
}
}
...@@ -37,6 +37,7 @@ typedef struct String *string; ...@@ -37,6 +37,7 @@ typedef struct String *string;
typedef struct Sigs Sigs; typedef struct Sigs Sigs;
typedef struct Sigi Sigi; typedef struct Sigi Sigi;
typedef struct Map Map; typedef struct Map Map;
typedef struct Array Array;
typedef struct Gobuf Gobuf; typedef struct Gobuf Gobuf;
typedef struct G G; typedef struct G G;
typedef struct M M; typedef struct M M;
...@@ -99,6 +100,14 @@ struct Sigi ...@@ -99,6 +100,14 @@ struct Sigi
uint32 hash; uint32 hash;
uint32 offset; uint32 offset;
}; };
struct Array
{ // must not move anything
byte* array; // actual data
uint32 nel; // number of elements
uint32 cap; // allocate3d number of elements
byte b[8]; // actual array - may not be contig
};
struct Map struct Map
{ {
Sigi* si; Sigi* si;
......
...@@ -325,7 +325,7 @@ func Split(U PS) *dch2{ ...@@ -325,7 +325,7 @@ func Split(U PS) *dch2{
func Add(U, V PS) PS{ func Add(U, V PS) PS{
Z := mkPS(); Z := mkPS();
go func(U, V, Z PS){ go func(U, V, Z PS){
var uv *[2] *rat; var uv *[] *rat;
for { for {
<-Z.req; <-Z.req;
uv = get2(U,V); uv = get2(U,V);
...@@ -419,9 +419,9 @@ func Shift(c *rat, U PS) PS{ ...@@ -419,9 +419,9 @@ func Shift(c *rat, U PS) PS{
// Convert array of coefficients, constant term first // Convert array of coefficients, constant term first
// to a (finite) power series // to a (finite) power series
/* BUG: NEED LEN OF ARRAY
func Poly(a [] *rat) PS{ func Poly(a [] *rat) PS{
Z:=mkPS(); Z:=mkPS();
/* BUG: NEED LEN OF ARRAY
begin func(a [] *rat, Z PS){ begin func(a [] *rat, Z PS){
j:=0; j:=0;
done:=0; done:=0;
...@@ -431,9 +431,9 @@ func Poly(a [] *rat) PS{ ...@@ -431,9 +431,9 @@ func Poly(a [] *rat) PS{
for(; i<j; i=i+1) put(a[i],Z); for(; i<j; i=i+1) put(a[i],Z);
put(finis,Z); put(finis,Z);
}(); }();
*/
return Z; return Z;
} }
*/
// Multiply. The algorithm is // Multiply. The algorithm is
// let U = u + x*UU // let U = u + x*UU
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment