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