]> Cypherpunks repositories - gostls13.git/commitdiff
arrays
authorKen Thompson <ken@golang.org>
Thu, 28 Aug 2008 00:28:30 +0000 (17:28 -0700)
committerKen Thompson <ken@golang.org>
Thu, 28 Aug 2008 00:28:30 +0000 (17:28 -0700)
R=r
OCL=14603
CL=14603

14 files changed:
src/cmd/6g/align.c
src/cmd/6g/cgen.c
src/cmd/gc/export.c
src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/lex.c
src/cmd/gc/subr.c
src/cmd/gc/sys.go
src/cmd/gc/sysimport.c
src/cmd/gc/walk.c
src/runtime/Makefile
src/runtime/array.c [new file with mode: 0644]
src/runtime/runtime.h
test/chan/powser1.go

index 2ba6b04e74e676898f3d5c76c2db23a73bb081dd..8c837dd885e2abc2c9a1e90c58c67d5dcd107087 100644 (file)
@@ -157,12 +157,14 @@ dowidth(Type *t)
        case TSTRING:           // implemented as pointer
                w = wptr;
                break;
-       case TARRAY:
        case TDARRAY:
+               fatal("width of a dynamic array");
+       case TARRAY:
                if(t->type == T)
                        break;
                dowidth(t->type);
-               w = t->bound * t->type->width;
+               w = t->bound * t->type->width
+;//                    + offsetof(Array, b[0]);
                break;
 
        case TSTRUCT:
index b4ae1dfb92889da24a56954373ac93ae34229143..7870a8f7e6d0c253f795202a0181847a1a0c6e50 100644 (file)
@@ -136,6 +136,20 @@ cgen(Node *n, Node *res)
                }
                regalloc(&n1, nl->type, res);
                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);
                regfree(&n1);
                break;
@@ -173,9 +187,33 @@ cgen(Node *n, Node *res)
                        regfree(&n1);
                        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);
                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:
                agen(nl, res);
                break;
@@ -253,6 +291,7 @@ agen(Node *n, Node *res)
 {
        Node *nl, *nr;
        Node n1, n2, n3, tmp;
+       Prog *p1;
        uint32 w;
        Type *t;
 
@@ -347,15 +386,60 @@ agen(Node *n, Node *res)
                // &a is in res
                // i is in &n1
                // 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])
-                       regalloc(&n2, types[TINT64], &n1);      // i/int64
-               else
-                       regalloc(&n2, types[TUINT64], &n1);     // i/uint64
+                       t = types[TINT64];
+
+               regalloc(&n2, t, &n1);                  // i
                gmove(&n1, &n2);
-               gins(optoas(OMUL, types[TINT64]), &n3, &n2);
-               gins(optoas(OADD, types[tptr]), &n2, res);
                regfree(&n1);
+
+               nodconst(&n3, t, w);                    // w
+               gins(optoas(OMUL, t), &n3, &n2);
+               gins(optoas(OADD, types[tptr]), &n2, res);
                regfree(&n2);
                break;
 
index aaa32a11b2afa2747e8627f2f53a2741e05f29ac..57f823d6f2f6dcb39a21d227c2045d317a99dc3f 100644 (file)
@@ -147,12 +147,17 @@ dumpexporttype(Sym *s)
                break;
 
        case TARRAY:
+       case TDARRAY:
                reexport(t->type);
 
                /* type 2 */
                Bprint(bout, "\ttype ");
                if(s->export != 0)
                        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);
                break;
 
@@ -517,8 +522,13 @@ doimport2(Node *ss, Val *b, Node *st)
        Type *t;
        Sym *s;
 
-       t = typ(TARRAY);
-       t->bound = mpgetfix(b->u.xval);
+       if(b == nil) {
+               t = typ(TDARRAY);
+               t->dbound = N;
+       } else {
+               t = typ(TARRAY);
+               t->bound = mpgetfix(b->u.xval);
+       }
        s = pkglookup(st->sym->name, st->psym->name);
        t->type = s->otype;
 
index b8ddcc3cd042a58004715da646e3e46a17117c4b..02e15810b603c578d8b124aa259defb8d70681eb 100644 (file)
@@ -3,11 +3,6 @@
 // license that can be found in the LICENSE file.
 
 /*
-todo:
-       1. dyn arrays
-       2. multi
-tothinkabout:
-       2. argument in import
 */
 
 #include       <u.h>
@@ -55,6 +50,21 @@ struct       String
        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
 {
        Mpscale = 29,           /* safely smaller than bits in a long */
@@ -131,6 +141,7 @@ struct      Type
 
        // TARRAY
        int32   bound;
+       Node*   dbound;
 };
 #define        T       ((Type*)0)
 
@@ -251,7 +262,7 @@ enum
        ORETURN, OFOR, OIF, OSWITCH, OI2S, OS2I, OI2I,
        OAS, OASOP, OCASE, OXCASE, OSCASE, OFALL, OXFALL,
        OGOTO, OPROC, ONEW, OEMPTY, OSELECT,
-       OLEN, OPANIC, OPRINT, OTYPEOF,
+       OLEN, OCAP, OPANIC, OPRINT, OTYPEOF,
 
        OOROR,
        OANDAND,
@@ -669,6 +680,7 @@ Type*       fixmap(Type*);
 Node*  mapop(Node*, int);
 Type*  fixchan(Type*);
 Node*  chanop(Node*, int);
+Node*  arrayop(Node*, int);
 Node*  isandss(Type*, Node*);
 Node*  convas(Node*);
 void   arrayconv(Type*, Node*);
index 8f1b71a16d0fdf3a749e35cfe439e8474bf69c08..ab197df5111892b821e0845696798f6f409dab5c 100644 (file)
@@ -18,7 +18,7 @@
 %token <sym>           LPACKAGE LIMPORT LEXPORT
 %token <sym>           LMAP LCHAN LINTERFACE LFUNC LSTRUCT
 %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>           LFOR LIF LELSE LSWITCH LCASE LDEFAULT
 %token <sym>           LBREAK LCONTINUE LGO LGOTO LRANGE
@@ -733,6 +733,10 @@ pexpr:
        {
                $$ = nod(OLEN, $3, N);
        }
+|      LCAP '(' expr ')'
+       {
+               $$ = nod(OCAP, $3, N);
+       }
 |      LTYPEOF '(' type ')'
        {
                $$ = nod(OTYPEOF, N, N);
@@ -852,6 +856,7 @@ key:
 |      LFALSE
 |      LIOTA
 |      LLEN
+|      LCAP
 |      LPANIC
 |      LPRINT
 |      LNEW
@@ -1519,6 +1524,11 @@ hidden_import:
                // type array
                doimport2($2, &$4, $6);
        }
+|      LTYPE hidden_importsym '[' ']' hidden_importsym
+       {
+               // type array
+               doimport2($2, nil, $5);
+       }
 |      LTYPE hidden_importsym '(' ohidden_importsym_list ')'
        {
                // type function
index ceec9242928ea8497aae24b3036aeb5b40061b0f..b03762332d91538bcc200533fc128cfff549edd8 100644 (file)
@@ -998,6 +998,7 @@ static      struct
        "map",          LMAP,           Txxx,
        "new",          LNEW,           Txxx,
        "len",          LLEN,           Txxx,
+       "cap",          LCAP,           Txxx,
        "nil",          LNIL,           Txxx,
        "package",      LPACKAGE,       Txxx,
        "panic",        LPANIC,         Txxx,
index 0234700fc329e17ef0df4e3a9e56f93e1a1a58fd..66e20b863d6384f74ade3d0719a4a3c047dd5c26 100644 (file)
@@ -374,27 +374,39 @@ Type*
 aindex(Node *b, Type *t)
 {
        Type *r;
-
-       r = typ(TARRAY);
-       r->type = t;
-
-       if(t->etype == TDARRAY)
-               yyerror("dynamic array type cannot be a dynamic array");
+       int bound;
 
        walktype(b, Erv);
        switch(whatis(b)) {
-       default:
-               yyerror("array bound must be a constant integer expression");
+       default:        // variable bound
+               walktype(b, Erv);
+               if(b->type != T && isint[b->type->etype])
+                       goto dyn;
+               yyerror("array bound must be an integer expression");
+               bound = 0;
                break;
 
-       case Wnil:      // default zero lb
-               r->bound = 0;
-               break;
+       case Wnil:      // open bound
+               goto dyn;
 
-       case Wlitint:   // fixed lb
-               r->bound = mpgetfix(b->val.u.xval);
+       case Wlitint:   // fixed bound
+               bound = mpgetfix(b->val.u.xval);
                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;
 }
 
@@ -641,6 +653,7 @@ opnames[] =
        [OLABEL]        = "LABEL",
        [OLE]           = "LE",
        [OLEN]          = "LEN",
+       [OCAP]          = "CAP",
        [OLIST]         = "LIST",
        [OLITERAL]      = "LITERAL",
        [OLSH]          = "LSH",
@@ -1001,6 +1014,8 @@ Tconv(Fmt *fp)
 
        case TDARRAY:
                snprint(buf1, sizeof(buf1), "[]%T", t->type);
+               if(t->dbound != N)
+                       snprint(buf1, sizeof(buf1), "[<expr>]%T", t->type);
                strncat(buf, buf1, sizeof(buf));
                break;
 
@@ -1229,7 +1244,6 @@ eqtype(Type *t1, Type *t2, int d)
 {
        if(d >= 10)
                return 1;
-
        if(t1 == t2)
                return 1;
        if(t1 == T || t2 == T)
@@ -1279,6 +1293,11 @@ eqtype(Type *t1, Type *t2, int d)
                        t2 = t2->down;
                }
                return 1;
+
+       case TARRAY:
+               if(t1->bound == t2->bound)
+                       break;
+               return 0;
        }
        return eqtype(t1->type, t2->type, d+1);
 }
@@ -1304,6 +1323,8 @@ loop:
        case TPTR32:
        case TPTR64:
        case TCHAN:
+       case TARRAY:
+       case TDARRAY:
                stp = &st->type;
                goto loop;
 
@@ -1373,6 +1394,8 @@ deep(Type *t)
        case TPTR32:
        case TPTR64:
        case TCHAN:
+       case TARRAY:
+       case TDARRAY:
                nt = shallow(t);
                nt->type = deep(t->type);
                break;
index 02137bf16e451bfa9523d463a2cbeda6e69147bd..8a9949a4e7b16c1e26e4c765d24233c7d93d9269 100644 (file)
@@ -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   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   goexit();
 
@@ -124,6 +129,12 @@ export
        selectrecv
        selectgo
 
+       // dynamic arrays
+       newarray
+       arraysliced
+       arrayslices
+       arrays2d
+
        // go routines
        gosched
        goexit
index bf2b468ad433af0fca43df01da2c06bed48296bc..9bcf7299c3da1d3e3ccb82ca274e77a2fd6de5fe 100644 (file)
@@ -3,10 +3,10 @@ char* sysimport =
        "type sys._esys_002 {}\n"
        "type sys.any 24\n"
        "type sys._esys_003 *sys.any\n"
-       "type sys._osys_373 {_esys_371 sys._esys_003}\n"
+       "type sys._osys_409 {_esys_407 sys._esys_003}\n"
        "type sys.uint32 6\n"
-       "type sys._isys_375 {_esys_372 sys.uint32}\n"
-       "type sys._esys_001 (sys._esys_002 sys._osys_373 sys._isys_375)\n"
+       "type sys._isys_411 {_esys_408 sys.uint32}\n"
+       "type sys._esys_001 (sys._esys_002 sys._osys_409 sys._isys_411)\n"
        "var !sys.mal sys._esys_001\n"
        "type sys._esys_005 {}\n"
        "type sys._esys_006 {}\n"
@@ -16,288 +16,320 @@ char*     sysimport =
        "type sys._esys_009 {}\n"
        "type sys._esys_010 {}\n"
        "type sys.int32 5\n"
-       "type sys._isys_381 {_esys_380 sys.int32}\n"
-       "type sys._esys_008 (sys._esys_009 sys._esys_010 sys._isys_381)\n"
+       "type sys._isys_417 {_esys_416 sys.int32}\n"
+       "type sys._esys_008 (sys._esys_009 sys._esys_010 sys._isys_417)\n"
        "var !sys.panicl sys._esys_008\n"
        "type sys._esys_012 {}\n"
        "type sys._esys_013 {}\n"
        "type sys.bool 12\n"
-       "type sys._isys_386 {_esys_385 sys.bool}\n"
-       "type sys._esys_011 (sys._esys_012 sys._esys_013 sys._isys_386)\n"
+       "type sys._isys_422 {_esys_421 sys.bool}\n"
+       "type sys._esys_011 (sys._esys_012 sys._esys_013 sys._isys_422)\n"
        "var !sys.printbool sys._esys_011\n"
        "type sys._esys_015 {}\n"
        "type sys._esys_016 {}\n"
        "type sys.float64 10\n"
-       "type sys._isys_391 {_esys_390 sys.float64}\n"
-       "type sys._esys_014 (sys._esys_015 sys._esys_016 sys._isys_391)\n"
+       "type sys._isys_427 {_esys_426 sys.float64}\n"
+       "type sys._esys_014 (sys._esys_015 sys._esys_016 sys._isys_427)\n"
        "var !sys.printfloat sys._esys_014\n"
        "type sys._esys_018 {}\n"
        "type sys._esys_019 {}\n"
        "type sys.int64 7\n"
-       "type sys._isys_396 {_esys_395 sys.int64}\n"
-       "type sys._esys_017 (sys._esys_018 sys._esys_019 sys._isys_396)\n"
+       "type sys._isys_432 {_esys_431 sys.int64}\n"
+       "type sys._esys_017 (sys._esys_018 sys._esys_019 sys._isys_432)\n"
        "var !sys.printint sys._esys_017\n"
        "type sys._esys_021 {}\n"
        "type sys._esys_022 {}\n"
        "type sys._esys_023 25\n"
        "type sys.string *sys._esys_023\n"
-       "type sys._isys_401 {_esys_400 sys.string}\n"
-       "type sys._esys_020 (sys._esys_021 sys._esys_022 sys._isys_401)\n"
+       "type sys._isys_437 {_esys_436 sys.string}\n"
+       "type sys._esys_020 (sys._esys_021 sys._esys_022 sys._isys_437)\n"
        "var !sys.printstring sys._esys_020\n"
        "type sys._esys_025 {}\n"
        "type sys._esys_026 {}\n"
        "type sys._esys_027 *sys.any\n"
-       "type sys._isys_406 {_esys_405 sys._esys_027}\n"
-       "type sys._esys_024 (sys._esys_025 sys._esys_026 sys._isys_406)\n"
+       "type sys._isys_442 {_esys_441 sys._esys_027}\n"
+       "type sys._esys_024 (sys._esys_025 sys._esys_026 sys._isys_442)\n"
        "var !sys.printpointer sys._esys_024\n"
        "type sys._esys_029 {}\n"
-       "type sys._osys_413 {_esys_410 sys.string}\n"
-       "type sys._isys_415 {_esys_411 sys.string _esys_412 sys.string}\n"
-       "type sys._esys_028 (sys._esys_029 sys._osys_413 sys._isys_415)\n"
+       "type sys._osys_449 {_esys_446 sys.string}\n"
+       "type sys._isys_451 {_esys_447 sys.string _esys_448 sys.string}\n"
+       "type sys._esys_028 (sys._esys_029 sys._osys_449 sys._isys_451)\n"
        "var !sys.catstring sys._esys_028\n"
        "type sys._esys_031 {}\n"
-       "type sys._osys_423 {_esys_420 sys.int32}\n"
-       "type sys._isys_425 {_esys_421 sys.string _esys_422 sys.string}\n"
-       "type sys._esys_030 (sys._esys_031 sys._osys_423 sys._isys_425)\n"
+       "type sys._osys_459 {_esys_456 sys.int32}\n"
+       "type sys._isys_461 {_esys_457 sys.string _esys_458 sys.string}\n"
+       "type sys._esys_030 (sys._esys_031 sys._osys_459 sys._isys_461)\n"
        "var !sys.cmpstring sys._esys_030\n"
        "type sys._esys_033 {}\n"
-       "type sys._osys_434 {_esys_430 sys.string}\n"
-       "type sys._isys_436 {_esys_431 sys.string _esys_432 sys.int32 _esys_433 sys.int32}\n"
-       "type sys._esys_032 (sys._esys_033 sys._osys_434 sys._isys_436)\n"
+       "type sys._osys_470 {_esys_466 sys.string}\n"
+       "type sys._isys_472 {_esys_467 sys.string _esys_468 sys.int32 _esys_469 sys.int32}\n"
+       "type sys._esys_032 (sys._esys_033 sys._osys_470 sys._isys_472)\n"
        "var !sys.slicestring sys._esys_032\n"
        "type sys._esys_035 {}\n"
        "type sys.uint8 2\n"
-       "type sys._osys_445 {_esys_442 sys.uint8}\n"
-       "type sys._isys_447 {_esys_443 sys.string _esys_444 sys.int32}\n"
-       "type sys._esys_034 (sys._esys_035 sys._osys_445 sys._isys_447)\n"
+       "type sys._osys_481 {_esys_478 sys.uint8}\n"
+       "type sys._isys_483 {_esys_479 sys.string _esys_480 sys.int32}\n"
+       "type sys._esys_034 (sys._esys_035 sys._osys_481 sys._isys_483)\n"
        "var !sys.indexstring sys._esys_034\n"
        "type sys._esys_037 {}\n"
-       "type sys._osys_454 {_esys_452 sys.string}\n"
-       "type sys._isys_456 {_esys_453 sys.int64}\n"
-       "type sys._esys_036 (sys._esys_037 sys._osys_454 sys._isys_456)\n"
+       "type sys._osys_490 {_esys_488 sys.string}\n"
+       "type sys._isys_492 {_esys_489 sys.int64}\n"
+       "type sys._esys_036 (sys._esys_037 sys._osys_490 sys._isys_492)\n"
        "var !sys.intstring sys._esys_036\n"
        "type sys._esys_039 {}\n"
-       "type sys._osys_463 {_esys_460 sys.string}\n"
+       "type sys._osys_499 {_esys_496 sys.string}\n"
        "type sys._esys_040 *sys.uint8\n"
-       "type sys._isys_465 {_esys_461 sys._esys_040 _esys_462 sys.int32}\n"
-       "type sys._esys_038 (sys._esys_039 sys._osys_463 sys._isys_465)\n"
+       "type sys._isys_501 {_esys_497 sys._esys_040 _esys_498 sys.int32}\n"
+       "type sys._esys_038 (sys._esys_039 sys._osys_499 sys._isys_501)\n"
        "var !sys.byteastring sys._esys_038\n"
        "type sys._esys_042 {}\n"
        "type sys._esys_043 <>\n"
-       "type sys._osys_474 {_esys_470 sys._esys_043}\n"
+       "type sys._osys_510 {_esys_506 sys._esys_043}\n"
        "type sys._esys_044 *sys.uint8\n"
        "type sys._esys_045 *sys.uint8\n"
-       "type sys._ssys_481 {}\n"
-       "type sys._esys_046 *sys._ssys_481\n"
-       "type sys._isys_476 {_esys_471 sys._esys_044 _esys_472 sys._esys_045 _esys_473 sys._esys_046}\n"
-       "type sys._esys_041 (sys._esys_042 sys._osys_474 sys._isys_476)\n"
+       "type sys._ssys_517 {}\n"
+       "type sys._esys_046 *sys._ssys_517\n"
+       "type sys._isys_512 {_esys_507 sys._esys_044 _esys_508 sys._esys_045 _esys_509 sys._esys_046}\n"
+       "type sys._esys_041 (sys._esys_042 sys._osys_510 sys._isys_512)\n"
        "var !sys.mkiface sys._esys_041\n"
        "type sys._esys_048 {}\n"
-       "type sys._osys_485 {_esys_484 sys.int32}\n"
+       "type sys._osys_521 {_esys_520 sys.int32}\n"
        "type sys._esys_049 {}\n"
-       "type sys._esys_047 (sys._esys_048 sys._osys_485 sys._esys_049)\n"
+       "type sys._esys_047 (sys._esys_048 sys._osys_521 sys._esys_049)\n"
        "var !sys.argc sys._esys_047\n"
        "type sys._esys_051 {}\n"
-       "type sys._osys_489 {_esys_488 sys.int32}\n"
+       "type sys._osys_525 {_esys_524 sys.int32}\n"
        "type sys._esys_052 {}\n"
-       "type sys._esys_050 (sys._esys_051 sys._osys_489 sys._esys_052)\n"
+       "type sys._esys_050 (sys._esys_051 sys._osys_525 sys._esys_052)\n"
        "var !sys.envc sys._esys_050\n"
        "type sys._esys_054 {}\n"
-       "type sys._osys_494 {_esys_492 sys.string}\n"
-       "type sys._isys_496 {_esys_493 sys.int32}\n"
-       "type sys._esys_053 (sys._esys_054 sys._osys_494 sys._isys_496)\n"
+       "type sys._osys_530 {_esys_528 sys.string}\n"
+       "type sys._isys_532 {_esys_529 sys.int32}\n"
+       "type sys._esys_053 (sys._esys_054 sys._osys_530 sys._isys_532)\n"
        "var !sys.argv sys._esys_053\n"
        "type sys._esys_056 {}\n"
-       "type sys._osys_502 {_esys_500 sys.string}\n"
-       "type sys._isys_504 {_esys_501 sys.int32}\n"
-       "type sys._esys_055 (sys._esys_056 sys._osys_502 sys._isys_504)\n"
+       "type sys._osys_538 {_esys_536 sys.string}\n"
+       "type sys._isys_540 {_esys_537 sys.int32}\n"
+       "type sys._esys_055 (sys._esys_056 sys._osys_538 sys._isys_540)\n"
        "var !sys.envv sys._esys_055\n"
        "type sys._esys_058 {}\n"
-       "type sys._osys_511 {_esys_508 sys.float64 _esys_509 sys.int32}\n"
-       "type sys._isys_513 {_esys_510 sys.float64}\n"
-       "type sys._esys_057 (sys._esys_058 sys._osys_511 sys._isys_513)\n"
+       "type sys._osys_547 {_esys_544 sys.float64 _esys_545 sys.int32}\n"
+       "type sys._isys_549 {_esys_546 sys.float64}\n"
+       "type sys._esys_057 (sys._esys_058 sys._osys_547 sys._isys_549)\n"
        "var !sys.frexp sys._esys_057\n"
        "type sys._esys_060 {}\n"
-       "type sys._osys_520 {_esys_517 sys.float64}\n"
-       "type sys._isys_522 {_esys_518 sys.float64 _esys_519 sys.int32}\n"
-       "type sys._esys_059 (sys._esys_060 sys._osys_520 sys._isys_522)\n"
+       "type sys._osys_556 {_esys_553 sys.float64}\n"
+       "type sys._isys_558 {_esys_554 sys.float64 _esys_555 sys.int32}\n"
+       "type sys._esys_059 (sys._esys_060 sys._osys_556 sys._isys_558)\n"
        "var !sys.ldexp sys._esys_059\n"
        "type sys._esys_062 {}\n"
-       "type sys._osys_530 {_esys_527 sys.float64 _esys_528 sys.float64}\n"
-       "type sys._isys_532 {_esys_529 sys.float64}\n"
-       "type sys._esys_061 (sys._esys_062 sys._osys_530 sys._isys_532)\n"
+       "type sys._osys_566 {_esys_563 sys.float64 _esys_564 sys.float64}\n"
+       "type sys._isys_568 {_esys_565 sys.float64}\n"
+       "type sys._esys_061 (sys._esys_062 sys._osys_566 sys._isys_568)\n"
        "var !sys.modf sys._esys_061\n"
        "type sys._esys_064 {}\n"
-       "type sys._osys_539 {_esys_536 sys.bool}\n"
-       "type sys._isys_541 {_esys_537 sys.float64 _esys_538 sys.int32}\n"
-       "type sys._esys_063 (sys._esys_064 sys._osys_539 sys._isys_541)\n"
+       "type sys._osys_575 {_esys_572 sys.bool}\n"
+       "type sys._isys_577 {_esys_573 sys.float64 _esys_574 sys.int32}\n"
+       "type sys._esys_063 (sys._esys_064 sys._osys_575 sys._isys_577)\n"
        "var !sys.isInf sys._esys_063\n"
        "type sys._esys_066 {}\n"
-       "type sys._osys_548 {_esys_546 sys.bool}\n"
-       "type sys._isys_550 {_esys_547 sys.float64}\n"
-       "type sys._esys_065 (sys._esys_066 sys._osys_548 sys._isys_550)\n"
+       "type sys._osys_584 {_esys_582 sys.bool}\n"
+       "type sys._isys_586 {_esys_583 sys.float64}\n"
+       "type sys._esys_065 (sys._esys_066 sys._osys_584 sys._isys_586)\n"
        "var !sys.isNaN sys._esys_065\n"
        "type sys._esys_068 {}\n"
-       "type sys._osys_556 {_esys_554 sys.float64}\n"
-       "type sys._isys_558 {_esys_555 sys.int32}\n"
-       "type sys._esys_067 (sys._esys_068 sys._osys_556 sys._isys_558)\n"
+       "type sys._osys_592 {_esys_590 sys.float64}\n"
+       "type sys._isys_594 {_esys_591 sys.int32}\n"
+       "type sys._esys_067 (sys._esys_068 sys._osys_592 sys._isys_594)\n"
        "var !sys.Inf sys._esys_067\n"
        "type sys._esys_070 {}\n"
-       "type sys._osys_563 {_esys_562 sys.float64}\n"
+       "type sys._osys_599 {_esys_598 sys.float64}\n"
        "type sys._esys_071 {}\n"
-       "type sys._esys_069 (sys._esys_070 sys._osys_563 sys._esys_071)\n"
+       "type sys._esys_069 (sys._esys_070 sys._osys_599 sys._esys_071)\n"
        "var !sys.NaN sys._esys_069\n"
        "type sys._esys_073 {}\n"
        "type sys._esys_075 [sys.any] sys.any\n"
        "type sys._esys_074 *sys._esys_075\n"
-       "type sys._osys_566 {hmap sys._esys_074}\n"
-       "type sys._isys_568 {keysize sys.uint32 valsize sys.uint32 keyalg sys.uint32 valalg sys.uint32 hint sys.uint32}\n"
-       "type sys._esys_072 (sys._esys_073 sys._osys_566 sys._isys_568)\n"
+       "type sys._osys_602 {hmap sys._esys_074}\n"
+       "type sys._isys_604 {keysize sys.uint32 valsize sys.uint32 keyalg sys.uint32 valalg sys.uint32 hint sys.uint32}\n"
+       "type sys._esys_072 (sys._esys_073 sys._osys_602 sys._isys_604)\n"
        "var !sys.newmap sys._esys_072\n"
        "type sys._esys_077 {}\n"
-       "type sys._osys_577 {val sys.any}\n"
+       "type sys._osys_613 {val sys.any}\n"
        "type sys._esys_079 [sys.any] sys.any\n"
        "type sys._esys_078 *sys._esys_079\n"
-       "type sys._isys_579 {hmap sys._esys_078 key sys.any}\n"
-       "type sys._esys_076 (sys._esys_077 sys._osys_577 sys._isys_579)\n"
+       "type sys._isys_615 {hmap sys._esys_078 key sys.any}\n"
+       "type sys._esys_076 (sys._esys_077 sys._osys_613 sys._isys_615)\n"
        "var !sys.mapaccess1 sys._esys_076\n"
        "type sys._esys_081 {}\n"
-       "type sys._osys_585 {val sys.any pres sys.bool}\n"
+       "type sys._osys_621 {val sys.any pres sys.bool}\n"
        "type sys._esys_083 [sys.any] sys.any\n"
        "type sys._esys_082 *sys._esys_083\n"
-       "type sys._isys_587 {hmap sys._esys_082 key sys.any}\n"
-       "type sys._esys_080 (sys._esys_081 sys._osys_585 sys._isys_587)\n"
+       "type sys._isys_623 {hmap sys._esys_082 key sys.any}\n"
+       "type sys._esys_080 (sys._esys_081 sys._osys_621 sys._isys_623)\n"
        "var !sys.mapaccess2 sys._esys_080\n"
        "type sys._esys_085 {}\n"
        "type sys._esys_086 {}\n"
        "type sys._esys_088 [sys.any] sys.any\n"
        "type sys._esys_087 *sys._esys_088\n"
-       "type sys._isys_594 {hmap sys._esys_087 key sys.any val sys.any}\n"
-       "type sys._esys_084 (sys._esys_085 sys._esys_086 sys._isys_594)\n"
+       "type sys._isys_630 {hmap sys._esys_087 key sys.any val sys.any}\n"
+       "type sys._esys_084 (sys._esys_085 sys._esys_086 sys._isys_630)\n"
        "var !sys.mapassign1 sys._esys_084\n"
        "type sys._esys_090 {}\n"
        "type sys._esys_091 {}\n"
        "type sys._esys_093 [sys.any] sys.any\n"
        "type sys._esys_092 *sys._esys_093\n"
-       "type sys._isys_600 {hmap sys._esys_092 key sys.any val sys.any pres sys.bool}\n"
-       "type sys._esys_089 (sys._esys_090 sys._esys_091 sys._isys_600)\n"
+       "type sys._isys_636 {hmap sys._esys_092 key sys.any val sys.any pres sys.bool}\n"
+       "type sys._esys_089 (sys._esys_090 sys._esys_091 sys._isys_636)\n"
        "var !sys.mapassign2 sys._esys_089\n"
        "type sys._esys_095 {}\n"
        "type sys._esys_097 1 sys.any\n"
        "type sys._esys_096 *sys._esys_097\n"
-       "type sys._osys_607 {hchan sys._esys_096}\n"
-       "type sys._isys_609 {elemsize sys.uint32 elemalg sys.uint32 hint sys.uint32}\n"
-       "type sys._esys_094 (sys._esys_095 sys._osys_607 sys._isys_609)\n"
+       "type sys._osys_643 {hchan sys._esys_096}\n"
+       "type sys._isys_645 {elemsize sys.uint32 elemalg sys.uint32 hint sys.uint32}\n"
+       "type sys._esys_094 (sys._esys_095 sys._osys_643 sys._isys_645)\n"
        "var !sys.newchan sys._esys_094\n"
        "type sys._esys_099 {}\n"
-       "type sys._osys_616 {elem sys.any}\n"
+       "type sys._osys_652 {elem sys.any}\n"
        "type sys._esys_101 1 sys.any\n"
        "type sys._esys_100 *sys._esys_101\n"
-       "type sys._isys_618 {hchan sys._esys_100}\n"
-       "type sys._esys_098 (sys._esys_099 sys._osys_616 sys._isys_618)\n"
+       "type sys._isys_654 {hchan sys._esys_100}\n"
+       "type sys._esys_098 (sys._esys_099 sys._osys_652 sys._isys_654)\n"
        "var !sys.chanrecv1 sys._esys_098\n"
        "type sys._esys_103 {}\n"
-       "type sys._osys_623 {elem sys.any pres sys.bool}\n"
+       "type sys._osys_659 {elem sys.any pres sys.bool}\n"
        "type sys._esys_105 1 sys.any\n"
        "type sys._esys_104 *sys._esys_105\n"
-       "type sys._isys_625 {hchan sys._esys_104}\n"
-       "type sys._esys_102 (sys._esys_103 sys._osys_623 sys._isys_625)\n"
+       "type sys._isys_661 {hchan sys._esys_104}\n"
+       "type sys._esys_102 (sys._esys_103 sys._osys_659 sys._isys_661)\n"
        "var !sys.chanrecv2 sys._esys_102\n"
        "type sys._esys_107 {}\n"
-       "type sys._osys_631 {pres sys.bool}\n"
+       "type sys._osys_667 {pres sys.bool}\n"
        "type sys._esys_109 1 sys.any\n"
        "type sys._esys_108 *sys._esys_109\n"
        "type sys._esys_110 *sys.any\n"
-       "type sys._isys_633 {hchan sys._esys_108 elem sys._esys_110}\n"
-       "type sys._esys_106 (sys._esys_107 sys._osys_631 sys._isys_633)\n"
+       "type sys._isys_669 {hchan sys._esys_108 elem sys._esys_110}\n"
+       "type sys._esys_106 (sys._esys_107 sys._osys_667 sys._isys_669)\n"
        "var !sys.chanrecv3 sys._esys_106\n"
        "type sys._esys_112 {}\n"
        "type sys._esys_113 {}\n"
        "type sys._esys_115 1 sys.any\n"
        "type sys._esys_114 *sys._esys_115\n"
-       "type sys._isys_639 {hchan sys._esys_114 elem sys.any}\n"
-       "type sys._esys_111 (sys._esys_112 sys._esys_113 sys._isys_639)\n"
+       "type sys._isys_675 {hchan sys._esys_114 elem sys.any}\n"
+       "type sys._esys_111 (sys._esys_112 sys._esys_113 sys._isys_675)\n"
        "var !sys.chansend1 sys._esys_111\n"
        "type sys._esys_117 {}\n"
-       "type sys._osys_644 {pres sys.bool}\n"
+       "type sys._osys_680 {pres sys.bool}\n"
        "type sys._esys_119 1 sys.any\n"
        "type sys._esys_118 *sys._esys_119\n"
-       "type sys._isys_646 {hchan sys._esys_118 elem sys.any}\n"
-       "type sys._esys_116 (sys._esys_117 sys._osys_644 sys._isys_646)\n"
+       "type sys._isys_682 {hchan sys._esys_118 elem sys.any}\n"
+       "type sys._esys_116 (sys._esys_117 sys._osys_680 sys._isys_682)\n"
        "var !sys.chansend2 sys._esys_116\n"
        "type sys._esys_121 {}\n"
        "type sys._esys_122 *sys.uint8\n"
-       "type sys._osys_652 {sel sys._esys_122}\n"
-       "type sys._isys_654 {size sys.uint32}\n"
-       "type sys._esys_120 (sys._esys_121 sys._osys_652 sys._isys_654)\n"
+       "type sys._osys_688 {sel sys._esys_122}\n"
+       "type sys._isys_690 {size sys.uint32}\n"
+       "type sys._esys_120 (sys._esys_121 sys._osys_688 sys._isys_690)\n"
        "var !sys.newselect sys._esys_120\n"
        "type sys._esys_124 {}\n"
-       "type sys._osys_659 {selected sys.bool}\n"
+       "type sys._osys_695 {selected sys.bool}\n"
        "type sys._esys_125 *sys.uint8\n"
        "type sys._esys_127 1 sys.any\n"
        "type sys._esys_126 *sys._esys_127\n"
-       "type sys._isys_661 {sel sys._esys_125 hchan sys._esys_126 elem sys.any}\n"
-       "type sys._esys_123 (sys._esys_124 sys._osys_659 sys._isys_661)\n"
+       "type sys._isys_697 {sel sys._esys_125 hchan sys._esys_126 elem sys.any}\n"
+       "type sys._esys_123 (sys._esys_124 sys._osys_695 sys._isys_697)\n"
        "var !sys.selectsend sys._esys_123\n"
        "type sys._esys_129 {}\n"
-       "type sys._osys_668 {selected sys.bool}\n"
+       "type sys._osys_704 {selected sys.bool}\n"
        "type sys._esys_130 *sys.uint8\n"
        "type sys._esys_132 1 sys.any\n"
        "type sys._esys_131 *sys._esys_132\n"
        "type sys._esys_133 *sys.any\n"
-       "type sys._isys_670 {sel sys._esys_130 hchan sys._esys_131 elem sys._esys_133}\n"
-       "type sys._esys_128 (sys._esys_129 sys._osys_668 sys._isys_670)\n"
+       "type sys._isys_706 {sel sys._esys_130 hchan sys._esys_131 elem sys._esys_133}\n"
+       "type sys._esys_128 (sys._esys_129 sys._osys_704 sys._isys_706)\n"
        "var !sys.selectrecv sys._esys_128\n"
        "type sys._esys_135 {}\n"
        "type sys._esys_136 {}\n"
        "type sys._esys_137 *sys.uint8\n"
-       "type sys._isys_677 {sel sys._esys_137}\n"
-       "type sys._esys_134 (sys._esys_135 sys._esys_136 sys._isys_677)\n"
+       "type sys._isys_713 {sel sys._esys_137}\n"
+       "type sys._esys_134 (sys._esys_135 sys._esys_136 sys._isys_713)\n"
        "var !sys.selectgo sys._esys_134\n"
        "type sys._esys_139 {}\n"
-       "type sys._esys_140 {}\n"
-       "type sys._esys_141 {}\n"
-       "type sys._esys_138 (sys._esys_139 sys._esys_140 sys._esys_141)\n"
-       "var !sys.gosched sys._esys_138\n"
+       "type sys._esys_141 [] sys.any\n"
+       "type sys._esys_140 *sys._esys_141\n"
+       "type sys._osys_717 {ary sys._esys_140}\n"
+       "type sys._isys_719 {nel sys.uint32 cap sys.uint32 width sys.uint32}\n"
+       "type sys._esys_138 (sys._esys_139 sys._osys_717 sys._isys_719)\n"
+       "var !sys.newarray sys._esys_138\n"
        "type sys._esys_143 {}\n"
-       "type sys._esys_144 {}\n"
-       "type sys._esys_145 {}\n"
-       "type sys._esys_142 (sys._esys_143 sys._esys_144 sys._esys_145)\n"
-       "var !sys.goexit sys._esys_142\n"
-       "type sys._esys_147 {}\n"
-       "type sys._osys_686 {_esys_683 sys.string _esys_684 sys.bool}\n"
-       "type sys._isys_688 {_esys_685 sys.string}\n"
-       "type sys._esys_146 (sys._esys_147 sys._osys_686 sys._isys_688)\n"
-       "var !sys.readfile sys._esys_146\n"
+       "type sys._esys_145 [] sys.any\n"
+       "type sys._esys_144 *sys._esys_145\n"
+       "type sys._osys_726 {ary sys._esys_144}\n"
+       "type sys._esys_147 [] sys.any\n"
+       "type sys._esys_146 *sys._esys_147\n"
+       "type sys._isys_728 {old sys._esys_146 lb sys.uint32 hb sys.uint32 width sys.uint32}\n"
+       "type sys._esys_142 (sys._esys_143 sys._osys_726 sys._isys_728)\n"
+       "var !sys.arraysliced sys._esys_142\n"
        "type sys._esys_149 {}\n"
-       "type sys._osys_695 {_esys_692 sys.bool}\n"
-       "type sys._isys_697 {_esys_693 sys.string _esys_694 sys.string}\n"
-       "type sys._esys_148 (sys._esys_149 sys._osys_695 sys._isys_697)\n"
-       "var !sys.writefile sys._esys_148\n"
-       "type sys._esys_151 {}\n"
-       "type sys._osys_707 {_esys_702 sys.int32 _esys_703 sys.int32}\n"
-       "type sys._esys_152 *sys.uint8\n"
-       "type sys._isys_709 {_esys_704 sys._esys_152 _esys_705 sys.int32 _esys_706 sys.int32}\n"
-       "type sys._esys_150 (sys._esys_151 sys._osys_707 sys._isys_709)\n"
-       "var !sys.bytestorune sys._esys_150\n"
+       "type sys._esys_151 [] sys.any\n"
+       "type sys._esys_150 *sys._esys_151\n"
+       "type sys._osys_736 {ary sys._esys_150}\n"
+       "type sys._esys_152 *sys.any\n"
+       "type sys._isys_738 {old sys._esys_152 nel sys.uint32 lb sys.uint32 hb sys.uint32 width sys.uint32}\n"
+       "type sys._esys_148 (sys._esys_149 sys._osys_736 sys._isys_738)\n"
+       "var !sys.arrayslices sys._esys_148\n"
        "type sys._esys_154 {}\n"
-       "type sys._osys_720 {_esys_715 sys.int32 _esys_716 sys.int32}\n"
-       "type sys._isys_722 {_esys_717 sys.string _esys_718 sys.int32 _esys_719 sys.int32}\n"
-       "type sys._esys_153 (sys._esys_154 sys._osys_720 sys._isys_722)\n"
-       "var !sys.stringtorune sys._esys_153\n"
-       "type sys._esys_156 {}\n"
-       "type sys._esys_157 {}\n"
-       "type sys._isys_728 {ms sys.int64}\n"
-       "type sys._esys_155 (sys._esys_156 sys._esys_157 sys._isys_728)\n"
-       "var !sys.sleep sys._esys_155\n"
+       "type sys._esys_156 [] sys.any\n"
+       "type sys._esys_155 *sys._esys_156\n"
+       "type sys._osys_747 {ary sys._esys_155}\n"
+       "type sys._esys_157 *sys.any\n"
+       "type sys._isys_749 {old sys._esys_157 nel sys.uint32}\n"
+       "type sys._esys_153 (sys._esys_154 sys._osys_747 sys._isys_749)\n"
+       "var !sys.arrays2d sys._esys_153\n"
        "type sys._esys_159 {}\n"
        "type sys._esys_160 {}\n"
-       "type sys._isys_733 {_esys_732 sys.int32}\n"
-       "type sys._esys_158 (sys._esys_159 sys._esys_160 sys._isys_733)\n"
-       "var !sys.exit sys._esys_158\n"
-       "type sys._esys_162 {}\n"
+       "type sys._esys_161 {}\n"
+       "type sys._esys_158 (sys._esys_159 sys._esys_160 sys._esys_161)\n"
+       "var !sys.gosched sys._esys_158\n"
        "type sys._esys_163 {}\n"
        "type sys._esys_164 {}\n"
-       "type sys._esys_161 (sys._esys_162 sys._esys_163 sys._esys_164)\n"
+       "type sys._esys_165 {}\n"
+       "type sys._esys_162 (sys._esys_163 sys._esys_164 sys._esys_165)\n"
+       "var !sys.goexit sys._esys_162\n"
+       "type sys._esys_167 {}\n"
+       "type sys._osys_760 {_esys_757 sys.string _esys_758 sys.bool}\n"
+       "type sys._isys_762 {_esys_759 sys.string}\n"
+       "type sys._esys_166 (sys._esys_167 sys._osys_760 sys._isys_762)\n"
+       "var !sys.readfile sys._esys_166\n"
+       "type sys._esys_169 {}\n"
+       "type sys._osys_769 {_esys_766 sys.bool}\n"
+       "type sys._isys_771 {_esys_767 sys.string _esys_768 sys.string}\n"
+       "type sys._esys_168 (sys._esys_169 sys._osys_769 sys._isys_771)\n"
+       "var !sys.writefile sys._esys_168\n"
+       "type sys._esys_171 {}\n"
+       "type sys._osys_781 {_esys_776 sys.int32 _esys_777 sys.int32}\n"
+       "type sys._esys_172 *sys.uint8\n"
+       "type sys._isys_783 {_esys_778 sys._esys_172 _esys_779 sys.int32 _esys_780 sys.int32}\n"
+       "type sys._esys_170 (sys._esys_171 sys._osys_781 sys._isys_783)\n"
+       "var !sys.bytestorune sys._esys_170\n"
+       "type sys._esys_174 {}\n"
+       "type sys._osys_794 {_esys_789 sys.int32 _esys_790 sys.int32}\n"
+       "type sys._isys_796 {_esys_791 sys.string _esys_792 sys.int32 _esys_793 sys.int32}\n"
+       "type sys._esys_173 (sys._esys_174 sys._osys_794 sys._isys_796)\n"
+       "var !sys.stringtorune sys._esys_173\n"
+       "type sys._esys_176 {}\n"
+       "type sys._esys_177 {}\n"
+       "type sys._isys_802 {ms sys.int64}\n"
+       "type sys._esys_175 (sys._esys_176 sys._esys_177 sys._isys_802)\n"
+       "var !sys.sleep sys._esys_175\n"
+       "type sys._esys_179 {}\n"
+       "type sys._esys_180 {}\n"
+       "type sys._isys_807 {_esys_806 sys.int32}\n"
+       "type sys._esys_178 (sys._esys_179 sys._esys_180 sys._isys_807)\n"
+       "var !sys.exit sys._esys_178\n"
+       "type sys._esys_182 {}\n"
+       "type sys._esys_183 {}\n"
+       "type sys._esys_184 {}\n"
+       "type sys._esys_181 (sys._esys_182 sys._esys_183 sys._esys_184)\n"
        "))\n"
 ;
index 3e3491bc02b13bdd42d3bb11f453835a9f693a62..5b2fc97539505c67932abec0e0ba29118a655243 100644 (file)
@@ -429,17 +429,20 @@ loop:
                        }
                }
 
-               if(t->etype == TARRAY) {
-                       arrayconv(t, l);
+               // convert dynamic to static generated by ONEW
+               if(isptrto(t, TARRAY) && isptrto(l->type, TDARRAY))
                        goto ret;
-               }
+
+//             if(t->etype == TARRAY) {
+//                     arrayconv(t, l);
+//                     goto ret;
+//             }
 
                r = isandss(n->type, l);
                if(r != N) {
                        *n = *r;
                        goto ret;
                }
-
                badtype(n->op, l->type, t);
                goto ret;
 
@@ -566,6 +569,28 @@ loop:
                n->type = types[TINT32];
                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 OINDEXPTR:
                if(top == Etop)
@@ -627,8 +652,8 @@ loop:
                                *n = *mapop(n, top);
                        break;
 
-               case TARRAY:
                case TDARRAY:
+               case TARRAY:
                        // right side must be an int
                        if(n->right->type == T) {
                                convlit(n->right, types[TINT32]);
@@ -672,10 +697,17 @@ loop:
                walktype(n->right, Erv);
                if(n->left == N || n->right == N)
                        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);
                        goto ret;
                }
+               if(t->etype == TDARRAY || t->etype == TARRAY) {
+                       *n = *arrayop(n, top);
+                       goto ret;
+               }
                badtype(OSLICE, n->left->type, T);
                goto ret;
 
@@ -1403,6 +1435,9 @@ ascompat(Type *t1, Type *t2)
                if(isptrto(t1, TSTRUCT))
                        return 1;
 
+       if(isptrto(t1, TDARRAY))
+               if(isptrto(t2, TARRAY))
+                       return 1;
        return 0;
 }
 
@@ -1498,13 +1533,19 @@ newcompat(Node *n)
                fatal("newcompat: type should be pointer %lT", t);
 
        t = t->type;
-       if(t->etype == TMAP) {
+       switch(t->etype) {
+       case TMAP:
                r = mapop(n, Erv);
                return r;
-       }
-       if(t->etype == TCHAN) {
+
+       case TCHAN:
                r = chanop(n, Erv);
                return r;
+
+       case TDARRAY:
+       case TARRAY:
+               r = arrayop(n, Erv);
+               return r;
        }
 
        if(n->left != N)
@@ -2082,6 +2123,168 @@ shape:
        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
 diagnamed(Type *t)
 {
@@ -2178,37 +2381,48 @@ convas(Node *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);
        return n;
 }
 
-void
-arrayconv(Type *t, Node *n)
-{
-       int c;
-       Iter save;
-       Node *l;
-
-       l = listfirst(&save, &n);
-       c = 0;
-
-loop:
-       if(l == N) {
-               if(t->bound == 0)
-                       t->bound = c;
-               if(t->bound == 0 || t->bound < c)
-                       yyerror("error with array convert bounds");
-               return;
-       }
-
-       c++;
-       walktype(l, Erv);
-       convlit(l, t->type);
-       if(!ascompat(l->type, t->type))
-               badtype(OARRAY, l->type, t->type);
-       l = listnext(&save);
-       goto loop;
-}
+//void
+//arrayconv(Type *t, Node *n)
+//{
+//     int c;
+//     Iter save;
+//     Node *l;
+//
+//     l = listfirst(&save, &n);
+//     c = 0;
+//
+//loop:
+//     if(l == N) {
+//             if(t->bound == 0)
+//                     t->bound = c;
+//             if(t->bound == 0 || t->bound < c)
+//                     yyerror("error with array convert bounds");
+//             return;
+//     }
+//
+//     c++;
+//     walktype(l, Erv);
+//     convlit(l, t->type);
+//     if(!ascompat(l->type, t->type))
+//             badtype(OARRAY, l->type, t->type);
+//     l = listnext(&save);
+//     goto loop;
+//}
 
 Node*
 old2new(Node *n, Type *t)
index 1dc29598e498f91c8f168a1001ac6327b40c136c..d70a4baf7799d24970bb3993d8fea23932e18b87 100644 (file)
@@ -20,6 +20,7 @@ LIBOFILES=\
        runtime.$O\
        map.$O\
        chan.$O\
+       array.$O\
        print.$O\
        rune.$O\
        proc.$O\
diff --git a/src/runtime/array.c b/src/runtime/array.c
new file mode 100644 (file)
index 0000000..548886e
--- /dev/null
@@ -0,0 +1,165 @@
+// 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");
+       }
+}
index 591af542dcbd486fc7f3b05d17a8c82fe8c3a92f..c7471cf3e6d4ea5dbda894d60f05f09d6ebc15cd 100644 (file)
@@ -37,6 +37,7 @@ typedef       struct  String          *string;
 typedef        struct  Sigs            Sigs;
 typedef        struct  Sigi            Sigi;
 typedef        struct  Map             Map;
+typedef        struct  Array           Array;
 typedef        struct  Gobuf           Gobuf;
 typedef        struct  G               G;
 typedef        struct  M               M;
@@ -99,6 +100,14 @@ struct      Sigi
        uint32  hash;
        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
 {
        Sigi*   si;
index 3bf70fff7ac14bd02dccf9733cff2ac35de332bf..e737c55bfe9642b847dbdb1bd5df1535f68c8ade 100644 (file)
@@ -325,7 +325,7 @@ func Split(U PS) *dch2{
 func Add(U, V PS) PS{
        Z := mkPS();
        go func(U, V, Z PS){
-               var uv *[2] *rat;
+               var uv *[] *rat;
                for {
                        <-Z.req;
                        uv = get2(U,V);
@@ -419,9 +419,9 @@ func Shift(c *rat, U PS) PS{
 // Convert array of coefficients, constant term first
 // to a (finite) power series
 
+/* BUG: NEED LEN OF ARRAY
 func Poly(a [] *rat) PS{
        Z:=mkPS();
-/* BUG: NEED LEN OF ARRAY
        begin func(a [] *rat, Z PS){
                j:=0;
                done:=0;
@@ -431,9 +431,9 @@ func Poly(a [] *rat) PS{
                for(; i<j; i=i+1) put(a[i],Z);
                put(finis,Z);
        }();
-*/
        return Z;
 }
+*/
 
 // Multiply. The algorithm is
 //     let U = u + x*UU