ref: 2b23d05d57743af57385cd42c0fd2d223b11d8c8
dir: /array.c/
#include <u.h> #include <libc.h> #include <thread.h> #include "dat.h" #include "fns.h" /* This file is the only file that knows how arrays are stored. * In theory, that allows us to experiment with other representations later. */ struct Array { int type; int rank; usize size; usize *shape; union { void *data; vlong *intdata; Rune *chardata; Array **arraydata; ConstraintVar **vardata; }; }; void initarrays(void) { dataspecs[DataArray].size = sizeof(Array); } Array * allocarray(int type, int rank, usize size) { Array *a = alloc(DataArray); a->type = type; a->rank = rank; a->size = size; switch(type){ case TypeNumber: size *= sizeof(vlong); break; case TypeChar: size *= sizeof(Rune); break; case TypeArray: size *= sizeof(Array *); break; case TypeVar: size *= sizeof(ConstraintVar *); break; } a->shape = allocextra(a, (sizeof(usize) * rank) + size); a->data = (void*)(a->shape+rank); return a; } void setint(Array *a, usize offset, vlong v) { a->intdata[offset] = v; } void setchar(Array *a, usize offset, Rune v) { a->chardata[offset] = v; } void setarray(Array *a, usize offset, Array *v) { a->arraydata[offset] = v; } void setvar(Array *a, usize offset, ConstraintVar *v) { a->vardata[offset] = v; } void setshape(Array *a, int dim, usize size) { a->shape[dim] = size; } int gettype(Array *a) { return a->type; } int getrank(Array *a) { return a->rank; } usize getshape(Array *a, int dim) { return a->shape[dim]; } vlong getint(Array *a, usize i) { return a->intdata[i]; } Rune getchar(Array *a, usize i) { return a->chardata[i]; } Array * getarray(Array *a, usize i) { return a->arraydata[i]; } ConstraintVar * getvar(Array *a, usize i) { return a->vardata[i]; } static int printconstraintvar(char *, ConstraintVar *, int); static int printarraysub(char *, Array *, int); static int printexpr(char *, Ast *, int); static int printitem(char *p, Array *a, uvlong i, int depth) { switch(a->type){ case TypeNumber: return sprint(p, "%lld", a->intdata[i]); case TypeChar: return sprint(p, "%C", a->chardata[i]); case TypeArray: return printarraysub(p, a->arraydata[i], depth); case TypeVar: return printconstraintvar(p, a->vardata[i], depth); default: return sprint(p, "???"); } } static int indent(char *buf, int depth) { char *p = buf; for(int i = 0; i < depth; i++) p += sprint(p, " "); return p-buf; } static int printconstraintvar(char *buf, ConstraintVar *v, int depth) { static int extrainfo = 1; char *p = buf; if(v->ast) p += printexpr(p, v->ast, 0); else{ p += sprint(p, "%s⍙%d", v->name, v->id); if(v->count > 0 && extrainfo){ p += sprint(p, " {\n"); for(uvlong i = 0; i < v->count; i++){ p += indent(p, depth+1); int ei = extrainfo; extrainfo = 0; p += printexpr(p, v->constraints[i]->ast, depth+1); extrainfo = ei; p += sprint(p, "\n"); } p += indent(p, depth); p += sprint(p, "}"); } } return p-buf; } static int printarraysub(char *buf, Array *a, int depth) { char *p = buf; if(a->rank <= 1 && a->type == TypeNumber){ if(a->size == 0) p += sprint(p, "⍬"); for(uvlong i = 0; i < a->size; i++){ if(i != 0) p += sprint(p, " "); p += printitem(p, a, i, depth); } goto end; }else if(a->rank <= 1 && a->type == TypeChar){ p += sprint(p, "'"); for(uvlong i = 0; i < a->size; i++) p += printitem(p, a, i, depth); /* TODO: quoting */ p += sprint(p, "'"); goto end; }else if(a->rank == 1 && (a->type == TypeArray || a->type == TypeVar)){ if(a->size == 0){ p += sprint(p, "( ⋄ )"); goto end; } p += sprint(p, "("); for(uvlong i = 0; i < a->size; i++){ if(i != 0){ p += sprint(p, "\n"); p += indent(p, depth+1); } p += printitem(p, a, i, depth+1); } p += sprint(p, ")"); goto end; }else if(a->rank == 0 && a->type == TypeVar){ p += printitem(p, a, 0, depth); goto end; } p += sprint(p, "Some array I can't print yet"); end: return p-buf; } char * printarray(Array *a) { char buf[2048]; /* TODO: fixed size :) */ printarraysub(buf, a, 0); return buf; } static int addspace(char *p) { if(*(p-1) == ' ') return 0; else return sprint(p, " "); } static int printexpr(char *start, Ast *e, int left) { if(e == nil) return sprint(start, "{?nil?}"); char *p = start; int paren = 0; if(left){ switch(e->tag){ case AstAssign: case AstMonadic: case AstDyadic: case AstStrand: p += sprint(p, "("); paren = 1; break; } } switch(e->tag){ case AstName: if(!left) p += addspace(p); p += sprint(p, "%s", e->name); if(left) p += addspace(p); break; case AstAssign: p += printexpr(p, e->left, 0); p += sprint(p, "←"); p += printexpr(p, e->right, 0); break; case AstMonadic: p += printexpr(p, e->func, 1); p += printexpr(p, e->right, 0); break; case AstDyadic: p += printexpr(p, e->left, 1); p += printexpr(p, e->func, 1); p += printexpr(p, e->right, 0); break; case AstConst: p += printarraysub(p, e->val, 0); break; case AstPrim: p += sprint(p, "%s", primsymb(e->prim)); break; case AstStrand: for(uvlong i = 0; i < e->childcount; i++){ if(i != 0) p += addspace(p); p += printexpr(p, e->children[i], 1); } break; case AstLater: p += sprint(p, "{later..}"); break; default: p += sprint(p, "{expr %d}", e->tag); break; } if(paren) p += sprint(p, ")"); return p - start; } char * printfunc(Function *f) /* Doesn't really belong here.. */ { char buf[2048]; /* TODO: fixed size :) */ char *p = buf; if(f->ast == nil){ sprint(p, "%s", primsymb(f->prim)); return buf; } p += sprint(p, "∇"); if(f->ast->funcresult) p += sprint(p, "%s←", f->ast->funcresult->name); if(f->ast->funcleftarg) p += sprint(p, "%s ", f->ast->funcleftarg->name); p += sprint(p, "%s", f->ast->funcname->name); if(f->ast->funcrightarg) p += sprint(p, " %s", f->ast->funcrightarg->name); for(uvlong i = 0; i < f->ast->funclocals->childcount; i++) p += sprint(p, ";%s", f->ast->funclocals->children[i]->name); for(uvlong i = 0; i < f->ast->childcount; i++){ p += sprint(p, "\n "); p += printexpr(p, f->ast->children[i], 0); } sprint(p, "\n∇"); return buf; } Array * simplifyarray(Array *a) { /* Given an array of type TypeArray, where all the elements are * simple scalars of the same type, return an array of that type */ Array *b = nil; int type; if(a->type != TypeArray || a->size == 0) goto end; type = a->arraydata[0]->type; b = allocarray(type, a->rank, a->size); for(uvlong dim = 0; dim < a->rank; dim++) b->shape[dim] = a->shape[dim]; for(uvlong i = 0; i < a->size; i++){ if(a->arraydata[i]->type != type || a->arraydata[i]->rank != 0){ b = a; goto end; /* Must be the same type and scalar */ } switch(type){ case TypeNumber: b->intdata[i] = a->arraydata[i]->intdata[0]; break; case TypeChar: b->chardata[i] = a->arraydata[i]->chardata[0]; break; case TypeVar: b->vardata[i] = a->arraydata[i]->vardata[0]; break; default: b = a; goto end; } } end: return b; }