shithub: lpa

ref: ddf9cc77ac875f0045e03dd59f516e302a4fbb7a
dir: /array.c/

View raw version
#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;
}

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;
}