ref: a70728e1cc959755252df483ef9c755bf03e5a25
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;
};
};
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;
}
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
setarray(Array *a, usize offset, Array *v)
{
a->arraydata[offset] = v;
}
void
setshape(Array *a, int dim, usize size)
{
a->shape[dim] = size;
}
static int printarraysub(char *, Array *, 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);
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
printarraysub(char *buf, Array *a, int depth)
{
char *p = buf;
if(a->rank == 0){
p += printitem(p, a, 0, depth);
goto end;
}else 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){
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;
}
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
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 += sprint(p, " ");
p += sprint(p, "%s", e->name);
if(left)
p += sprint(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 += sprint(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;
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;
}
}
end:
return b;
}