~pmikkelsen/lpa

ecef9816dc8f772ca7f93cfcfe914759065e358f — Peter Mikkelsen 2 months ago 50104ba
Better printing of array values
9 files changed, 178 insertions(+), 31 deletions(-)

M array.c
M dat.h
M fns.h
M fs.c
M lpa
M parse.c
M scan.c
M session.c
M value.c
M array.c => array.c +120 -9
@@ 11,6 11,7 @@

struct Array
{
	int type;
	int rank;
	usize size;
	usize *shape;


@@ 18,6 19,7 @@ struct Array
		void *data;
		vlong *intdata;
		Rune *chardata;
		Array **arraydata;
	};
};



@@ 31,6 33,7 @@ Array *
allocarray(int type, int rank, usize size)
{
	Array *a = alloc(DataArray);
	a->type = type;
	a->rank = rank;
	a->size = size;



@@ 41,6 44,9 @@ allocarray(int type, int rank, usize size)
	case TypeChar:
		size *= sizeof(Rune);
		break;
	case TypeArray:
		size *= sizeof(Array *);
		break;
	}

	a->shape = allocextra(a, (sizeof(usize) * rank) + size);


@@ 56,22 62,127 @@ setint(Array *a, usize offset, vlong 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)
{
	/* TODO: this is just for debugging */
	char buf[2048];
	char *p = buf;
	p += sprint(p, "type: %s shape: ", "numeric");
	for(int i = 0; i < a->rank; i++)
		p += sprint(p, "%lld ", a->shape[i]);
	p += sprint(p, "data: ");
	for(uvlong i = 0; i < a->size; i++)
		p += sprint(p, "%lld ", a->intdata[i]);
	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;
}
\ No newline at end of file

M dat.h => dat.h +1 -0
@@ 149,6 149,7 @@ enum ArrayType
{
	TypeNumber,
	TypeChar,
	TypeArray,
};

typedef struct Array Array;

M fns.h => fns.h +2 -0
@@ 2,7 2,9 @@
void initarrays(void);
Array *allocarray(int, int, usize);
void setint(Array *, usize, vlong);
void setarray(Array *, usize, Array *);
void setshape(Array *, int, usize);
Array *simplifyarray(Array *);

char *printarray(Array *);


M fs.c => fs.c +10 -0
@@ 613,6 613,16 @@ static Srv fs = {
void
startfs(char *name, char *mtpt)
{
	char *srvname = smprint("/srv/%s", name);
	if(access(srvname, AREAD|AWRITE) == 0){
		int fd = open(srvname, ORDWR);
		if(fd < 0)
			sysfatal("open lpa service");
		if(mount(fd, -1, mtpt, MREPL, "") != 0)
			sysfatal("mount lpa service");
		return;
	}

	dataspecs[DataAux].size = sizeof(Aux);

	username = getuser();

M lpa => lpa +4 -8
@@ 12,7 12,7 @@ fn usage{
}

fn nosession{
	echo 'session '^$id^' does not exist (or lpafs is not running)'
	echo 'session '^$id^' does not exist'
	exit 'no such session'
}



@@ 43,13 43,9 @@ if(! ~ $#* 0)
	usage

# Start LPA if it isn't already running
if(! test -f /srv/lpa){
	if(! ~ $id 0)
		nosession
	lpafs
}
if not
	mount /srv/lpa /mnt/lpa
lpafs
# Make /mnt/lpa available to sam and rio..
plumb 'Local lpafs'

if(~ $printlist 1){
	echo `{cd /mnt/lpa; ls | grep -v '^new$'}

M parse.c => parse.c +1 -3
@@ 161,12 161,10 @@ parseprog(TokenList *t)
			child = parsefuncdef(t);
		else
			child = parseexpr(t, nil);
		print("After expr: %d\n", peek(t));
		if(peek(t) != TokEnd)
			parseseps(t, 1);
		addchild(prog, child);
	}
	print("got prog, peek is: %d\n", peek(t));
	return prog;
}



@@ 324,7 322,7 @@ end:
		addchild(strand, val);
		val = strand;
	}
	

	return val;
}


M scan.c => scan.c +0 -6
@@ 92,11 92,5 @@ next:
		cp += n;
	}
	newtok(tokens, TokEnd);
	if(tokens){
		print("token tags: ");
		for(uvlong i = 0; i < tokens->count; i++)
			print("%d ", tokens->tokens[i].tag);
		print("\n");
	}
	return tokens;
}
\ No newline at end of file

M session.c => session.c +0 -1
@@ 56,7 56,6 @@ error:
			if(err)
				goto error;

			debugast(ast, 0);
			appendlog(s, "got an AST but can't evaluate it yet\n");
		}
	}

M value.c => value.c +40 -4
@@ 6,6 6,9 @@
#include "fns.h"

/* Anything that can have a name in LPA: Arrays, functions, ... */

static Array *evalconstast(Ast *);

char *
printval(void *v)
{


@@ 34,10 37,11 @@ parseval(char *buf, char **errp)
	ast = parse(tokens, errp);
	if(ast == nil)
		goto end;

	debugast(ast, 0);
	/* Check that the ast is either a single function definition,
	 * or a single constant.
	 * or a constant (stranding is OK).
	 */
	
	if(!(ast->tag == AstProg && ast->childcount == 1)){
		*errp = "Expected single value or function definition";
		goto end;


@@ 46,15 50,47 @@ parseval(char *buf, char **errp)
	ast = ast->children[0];
	switch(ast->tag){
	case AstConst:
		val = ast->val;
	case AstStrand:
		val = evalconstast(ast);
		if(val == nil)
			*errp = "Expected constant expression";
		break;
	case AstFunc:
		*errp = "Functions not supported yet";
		break;
	default:
		*errp = "Expected constant or function definition";
		goto end;
		break;
	}
end:
	return val;
}

static Array *
evalconstast(Ast *ast)
{
	Array *val;
	switch(ast->tag){
	case AstConst:
		val = ast->val;
		break;
	case AstStrand:
		val = allocarray(TypeArray, 1, ast->childcount);
		setshape(val, 0, ast->childcount);
		for(uvlong i = 0; i < ast->childcount; i++){
			Array *x = evalconstast(ast->children[i]);
			if(x)
				setarray(val, i, x);
			else{
				val = nil; /* abort */
				break;
			}
		}
		if(val)
			val = simplifyarray(val);
		break;
	default:
		val = nil;
	}
	return val;
}
\ No newline at end of file