shithub: lpa

Download patch

ref: 7434af4553ec451105b72cb221d214266bc034bb
parent: a70728e1cc959755252df483ef9c755bf03e5a25
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Thu Jul 25 15:15:26 EDT 2024

Add a few checks around function calls

--- a/dat.h
+++ b/dat.h
@@ -219,7 +219,6 @@
 	IStrand,
 	IMonadic,
 	IDyadic,
-	ICall,
 	IClear,
 	IParse,
 	IDone,
@@ -267,10 +266,19 @@
 	CallFrame *frames;
 };
 
+enum Valence
+{
+	Monadic = 1<<1,
+	Dyadic = 1<<2,
+};
+
 typedef struct Function Function;
 struct Function
 {
 	Ast *ast;
+	int valence;
+	int hasresult;
+
 	uvlong symbol;
 	ByteCode *code;
 	int prim;
--- a/eval.c
+++ b/eval.c
@@ -73,6 +73,11 @@
 		{
 			Function *fn = alloc(DataFunction);
 			fn->ast = a;
+			if(fn->ast->funcleftarg)
+				fn->valence = Dyadic;
+			else if(fn->ast->funcrightarg)
+				fn->valence = Monadic;
+
 			fn->symbol = sym(m->symtab, a->funcname->name);
 			fn->code = alloc(DataByteCode);
 			emitbyte(fn->code, IPushConst);
@@ -84,10 +89,11 @@
 			for(i = 0; i < fn->ast->funclocals->childcount; i++)
 				emitlocal(fn->code, m->symtab, fn->ast->funclocals->children[i], 0);
 			for(i = 0; i < a->childcount; i++){
-				if(i != 0)
-					emitbyte(fn->code, IClear);
 				codegensub(s, m, fn->code, a->children[i]);
+				emitbyte(fn->code, IClear);
 			}
+			if(fn->ast->funcresult)
+				codegensub(s, m, fn->code, fn->ast->funcresult);
 			emitbyte(fn->code, IReturn);
 
 			emitbyte(c, IPushConst);
@@ -124,19 +130,13 @@
 	case AstMonadic:
 		codegensub(s, m, c, a->right);
 		codegensub(s, m, c, a->func);
-		if(a->func->tag == AstPrim)
-			emitbyte(c, IMonadic);
-		else
-			emitbyte(c, ICall);
+		emitbyte(c, IMonadic);
 		break;
 	case AstDyadic:
 		codegensub(s, m, c, a->right);
 		codegensub(s, m, c, a->left);
 		codegensub(s, m, c, a->func);
-		if(a->func->tag == AstPrim)
-			emitbyte(c, IDyadic);
-		else
-			emitbyte(c, ICall);
+		emitbyte(c, IDyadic);
 		break;
 	case AstPrim:
 		emitbyte(c, IPushPrim);
@@ -181,13 +181,16 @@
 }
 
 static void
-pushcall(CallStack *s, ByteCode *c, uvlong o)
+pushcall(CallStack *s, ByteCode *newcode, ByteCode **c, uvlong *o)
 {
 	s->count++;
 	s->frames = allocextra(s, s->count * sizeof(CallFrame));
-	s->frames[s->count-1].code = c;
-	s->frames[s->count-1].offset = o;
+	s->frames[s->count-1].code = *c;
+	s->frames[s->count-1].offset = *o;
 	s->frames[s->count-1].locals = alloc(DataLocalList);
+
+	*c = newcode;
+	*o = 0;
 }
 
 static void
@@ -248,12 +251,20 @@
 			{
 				Function *f = alloc(DataFunction);
 				f->prim = v;
+				f->valence = primvalence(v);
 				pushval(values, f);
 			}
 			break;
 		case ILookup:
 			o += getuvlong(c->instrs+o, &v);
-			pushval(values, symval(m->symtab, v)); /* TODO: value error? */
+			{
+				void *val = symval(m->symtab, v);
+				if(val == nil){
+					appendlog(s, "VALUE ERROR\n");
+					return nil;
+				}
+				pushval(values, val);
+			}
 			break;
 		case IStrand:
 			o += getuvlong(c->instrs+o, &v);
@@ -267,32 +278,36 @@
 			}
 			break;
 		case IMonadic:
-			{
-				Function *f = popval(values);
+			func = popval(values);
+			if(!(func->valence & Monadic)){
+				appendlog(s, "ERROR: Function not monadic!\n");
+				return nil;
+			}
+
+			if(func->code)
+				pushcall(calls, func->code, &c, &o);
+			else{
 				Array *y = popval(values);
-				Array *z = primmonad(f->prim, y);
+				Array *z = primmonad(func->prim, y);
 				pushval(values, z);
 			}
 			break;
 		case IDyadic:
-			{
-				Function *f = popval(values);
+			func = popval(values);
+			if(!(func->valence & Dyadic)){
+				appendlog(s, "ERROR: Function not dyadic!\n");
+				return nil;
+			}
+
+			if(func->code)
+				pushcall(calls, func->code, &c, &o);
+			else{
 				Array *x = popval(values);
 				Array *y = popval(values);
-				Array *z = primdyad(f->prim, x, y);
+				Array *z = primdyad(func->prim, x, y);
 				pushval(values, z);
 			}
 			break;
-		case ICall:
-			func = popval(values);
-			newcode = func->code;
-call:
-			pushcall(calls, c, o);
-			c = newcode;
-			o = 0;
-			print("CALLED:\n");
-			debugbc(c);
-			break;
 		case IClear: /* TODO: get rid of this instruction. It shouldn't be there, and it is wrong */
 			while(values->count > 0)
 				popval(values);
@@ -313,7 +328,7 @@
 					newcode = alloc(DataByteCode);
 					codegensub(s, m, newcode, a);
 					emitbyte(newcode, IReturn);
-					goto call;
+					pushcall(calls, newcode, &c, &o);
 				}
 			}
 			break;
@@ -322,8 +337,6 @@
 			break;
 		case IReturn:
 			popcall(calls, m->symtab, &c, &o);
-			print("RETURNED TO (%ulld)\n", o);
-			debugbc(c);
 			break;
 		case IAssign:
 			o += getuvlong(c->instrs+o, &v);
@@ -346,4 +359,4 @@
 	if(values->count != 0)
 		r = popval(values);
 	return r;
-}
\ No newline at end of file
+}
--- a/fns.h
+++ b/fns.h
@@ -31,6 +31,7 @@
 /* prim.c */
 char *primsymb(int);
 int primclass(int);
+int primvalence(int);
 int primid(char *);
 Array *primmonad(int, Array *);
 Array *primdyad(int, Array *, Array *);
--- a/prim.c
+++ b/prim.c
@@ -39,6 +39,17 @@
 }
 
 int
+primvalence(int id)
+{
+	int valence = 0;
+	if(primspecs[id].monad)
+		valence |= Monadic;
+	if(primspecs[id].dyad)
+		valence |= Dyadic;
+	return valence;
+}
+
+int
 primid(char *s)
 {
 	for(int i = 0; i < nelem(primspecs); i++){
--- a/util.c
+++ b/util.c
@@ -159,13 +159,10 @@
 			print("STRAND %ulld\n", v);
 			break;
 		case IMonadic:
-			print("MONADIC PRIM\n");
+			print("MONADIC CALL\n");
 			break;
 		case IDyadic:
-			print("DYADIC PRIM\n");
-			break;
-		case ICall:
-			print("CALL\n");
+			print("DYADIC CALL\n");
 			break;
 		case IClear:
 			print("CLEAR\n");