shithub: lpa

Download patch

ref: ecef9816dc8f772ca7f93cfcfe914759065e358f
parent: 50104ba72987b26febfa4e398458d47db20e9bea
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Sun Jul 21 13:55:27 EDT 2024

Better printing of array values

--- a/array.c
+++ b/array.c
@@ -11,6 +11,7 @@
 
 struct Array
 {
+	int type;
 	int rank;
 	usize size;
 	usize *shape;
@@ -18,6 +19,7 @@
 		void *data;
 		vlong *intdata;
 		Rune *chardata;
+		Array **arraydata;
 	};
 };
 
@@ -31,6 +33,7 @@
 allocarray(int type, int rank, usize size)
 {
 	Array *a = alloc(DataArray);
+	a->type = type;
 	a->rank = rank;
 	a->size = size;
 
@@ -41,6 +44,9 @@
 	case TypeChar:
 		size *= sizeof(Rune);
 		break;
+	case TypeArray:
+		size *= sizeof(Array *);
+		break;
 	}
 
 	a->shape = allocextra(a, (sizeof(usize) * rank) + size);
@@ -56,22 +62,127 @@
 }
 
 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
--- a/dat.h
+++ b/dat.h
@@ -149,6 +149,7 @@
 {
 	TypeNumber,
 	TypeChar,
+	TypeArray,
 };
 
 typedef struct Array Array;
--- a/fns.h
+++ b/fns.h
@@ -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 *);
 
--- a/fs.c
+++ b/fs.c
@@ -613,6 +613,16 @@
 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();
--- a/lpa
+++ b/lpa
@@ -12,7 +12,7 @@
 }
 
 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 @@
 	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$'}
--- a/parse.c
+++ b/parse.c
@@ -161,12 +161,10 @@
 			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 @@
 		addchild(strand, val);
 		val = strand;
 	}
-	
+
 	return val;
 }
 
--- a/scan.c
+++ b/scan.c
@@ -92,11 +92,5 @@
 		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
--- a/session.c
+++ b/session.c
@@ -56,7 +56,6 @@
 			if(err)
 				goto error;
 
-			debugast(ast, 0);
 			appendlog(s, "got an AST but can't evaluate it yet\n");
 		}
 	}
--- a/value.c
+++ b/value.c
@@ -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 @@
 	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,7 +50,10 @@
 	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";
@@ -53,8 +60,37 @@
 		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