~pmikkelsen/lpa

785a9258b6f284d369b8e018e7f9dccf682a4479 — Peter Mikkelsen 2 months ago 5a13bf8
More general work
8 files changed, 205 insertions(+), 28 deletions(-)

M array.c
M dat.h
M eval.c
M fns.h
M mkfile
M parse.c
A prim.c
M scan.c
M array.c => array.c +73 -0
@@ 151,6 151,75 @@ printarray(Array *a)
	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.. */
{


@@ 167,6 236,10 @@ printfunc(Function *f) /* Doesn't really belong here.. */
		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;
}

M dat.h => dat.h +0 -6
@@ 101,12 101,6 @@ struct Enumeration
	void **items;
};

enum Primitive
{
	PrimPlus,
	PrimMinus,
};

enum TokenTag
{
	TokNumber,

M eval.c => eval.c +18 -3
@@ 105,6 105,11 @@ codegensub(Session *s, Module *m, ByteCode *c, Ast *a)
		emitbyte(c, ILookup);
		emituvlong(c, sym(m->symtab, a->name));
		break;
	case AstAssign:
		codegensub(s, m, c, a->right);
		emitbyte(c, IAssign);
		emituvlong(c, sym(m->symtab, a->left->name));
		break;
	case AstConst:
		emitbyte(c, IPushConst);
		emitptr(c, a->val); /* TODO: better to have consts array and emit index? */


@@ 262,11 267,21 @@ evalbc(Session *s, Module *m, ByteCode *c)
			}
			break;
		case IMonadic:
			appendlog(s, "NOTE: monadic call acts like ⊢\n");
			{
				Function *f = popval(values);
				Array *y = popval(values);
				Array *z = primmonad(f->prim, y);
				pushval(values, z);
			}
			break;
		case IDyadic:
			appendlog(s, "NOTE: dyadic call acts like ⊢\n");
			popval(values);
			{
				Function *f = popval(values);
				Array *x = popval(values);
				Array *y = popval(values);
				Array *z = primdyad(f->prim, x, y);
				pushval(values, z);
			}
			break;
		case ICall:
			func = popval(values);

M fns.h => fns.h +7 -0
@@ 28,6 28,13 @@ Enumeration *enummodules(Session *s);
/* parse.c */
Ast *parse(TokenList *, Symtab *, char **);

/* prim.c */
char *primsymb(int);
int primclass(int);
int primid(char *);
Array *primmonad(int, Array *);
Array *primdyad(int, Array *, Array *);

/* scan.c */
TokenList *scan(char *, char **);


M mkfile => mkfile +1 -0
@@ 10,6 10,7 @@ OFILES=\
	memory.$O\
	module.$O\
	parse.$O\
	prim.$O\
	scan.$O\
	session.$O\
	symtab.$O\

M parse.c => parse.c +7 -3
@@ 141,10 141,10 @@ nameclass(char *name, Symtab *s, Ast *func)
			break;
		/* more cases here in the future */
		}
	}else{
		/* TODO: Check if the name exist in the locallist */
		class = NameclassUndef;
	}

	/* TODO: Check if the name exist in the locallist */

	return class;
}



@@ 265,10 265,14 @@ parseexpr(TokenList *t, Symtab *symtab, Ast *func)

		if(t->tokens[i].tag != TokName)
			continue;
		if((i+1) < end && t->tokens[i+1].tag == TokLarrow)
			continue; /* assignment */

		name = t->tokens[i].name;
		class = nameclass(name, symtab, func);
		t->tokens[i].nameclass = class;
		if(class == 0){ /* We don't know how to parse it until runtime */
			print("nameclass 0 name: %s funcname: %s\n", name, func ? func->funcname->name : "<no func>");
			if(symtab)
				error(t, "could not resolve nameclasses");


A prim.c => prim.c +92 -0
@@ 0,0 1,92 @@
#include <u.h>
#include <libc.h>
#include <thread.h>

#include "dat.h"
#include "fns.h"

/* NOTE: In LPA, system functions are treated as primitives as well */

/* monadic functions */
static Array *primfn_same(Array *);

/* dyadic functions */
static Array *primfn_left(Array *, Array *);
static Array *primfn_right(Array *, Array *);

struct {
	char *spelling;
	int nameclass;
	Array *(*monad)(Array *);
	Array *(*dyad)(Array *, Array *);
} primspecs[] = {
	"⊢", NameclassFunc, primfn_same, primfn_right,
	"⊣", NameclassFunc, primfn_same, primfn_left,
	"+", NameclassFunc, nil, nil,
	"-", NameclassFunc, nil, nil,
};

char *
primsymb(int id)
{
	return primspecs[id].spelling;
}

int
primclass(int id)
{
	return primspecs[id].nameclass;
}

int
primid(char *s)
{
	for(int i = 0; i < nelem(primspecs); i++){
		char *x = primspecs[i].spelling;
		if(strncmp(s, x, strlen(x)) == 0)
			return i;
	}
	return -1;
}

Array *
primmonad(int id, Array *y)
{
	if(primspecs[id].monad)
		return primspecs[id].monad(y);
	else{
		print("primitive %s has no monadic definition! (acts like ⊢)\n", primsymb(id));
		return y;
	}
}

Array *
primdyad(int id, Array *x, Array *y)
{
	if(primspecs[id].dyad)
		return primspecs[id].dyad(x, y);
	else{
		print("primitive %s has no dyadic definition! (acts like ⊣)\n", primsymb(id));
		return x;
	}
}

/* monadic functions */
static Array *
primfn_same(Array *a)
{
	return a;
}

/* dyadic functions */
static Array *
primfn_left(Array *x, Array *)
{
	return x;
}

static Array *
primfn_right(Array *, Array *y)
{
	return y;
}
\ No newline at end of file

M scan.c => scan.c +7 -16
@@ 5,14 5,6 @@
#include "dat.h"
#include "fns.h"

struct {
	Rune spelling;
	int id;
} primspecs[] = {
	L'+', PrimPlus,
	L'-', PrimMinus,
};

Token *
newtok(TokenList *tokens, int tag)
{


@@ 30,7 22,7 @@ TokenList *
scan(char *buf, char **errp)
{
	Rune r;
	int n;
	int n, id;
	TokenList *tokens = alloc(DataTokenList);
	Token *tok;
	char *cp = buf;


@@ 55,13 47,12 @@ scan(char *buf, char **errp)
			newtok(tokens, new);
			goto next;
		}
		for(int i = 0; i < nelem(primspecs); i++){
			if(r == primspecs[i].spelling){
				tok = newtok(tokens, TokPrimitive);
				tok->prim = primspecs[i].id;
				tok->nameclass = NameclassFunc;
				goto next;
			}
		if((id = primid(cp)) != -1){
			n = strlen(primsymb(id));
			tok = newtok(tokens, TokPrimitive);
			tok->prim = id;
			tok->nameclass = primclass(id);
			goto next;
		}
		if(isspacerune(r))
			goto next;