shithub: MicroHs

Download patch

ref: f46aa044dc8fce17244821fc9d3c6cd0dc3a91fb
parent: 9fc3bc673e725264675a6c990265efe8d24055f8
author: Lennart Augustsson <lennart@augustsson.net>
date: Fri Nov 10 12:42:52 EST 2023

Change how missing FFI functions are reported.

--- a/src/runtime/eval.c
+++ b/src/runtime/eval.c
@@ -147,7 +147,7 @@
 
 #define ERR(s) do { fprintf(stderr, "ERR: %s\n", s); exit(1); } while(0)
 
-enum node_tag { T_FREE, T_IND, T_AP, T_INT, T_DBL, T_HDL, T_PTR, T_S, T_K, T_I, T_B, T_C,
+enum node_tag { T_FREE, T_IND, T_AP, T_INT, T_DBL, T_HDL, T_PTR, T_BADDYN, T_S, T_K, T_I, T_B, T_C,
                 T_A, T_Y, T_SS, T_BB, T_CC, T_P, T_R, T_O, T_T, T_BK,
                 T_ADD, T_SUB, T_MUL, T_QUOT, T_REM, T_SUBR, T_UQUOT, T_UREM, T_NEG,
                 T_AND, T_OR, T_XOR, T_INV, T_SHL, T_SHR, T_ASHR,
@@ -992,9 +992,27 @@
   for(int i = 0; i < sizeof(ffi_table) / sizeof(ffi_table[0]); i++)
     if (strcmp(ffi_table[i].ffi_name, name) == 0)
       return (value_t)i;
-  ERR("lookupFFIname");
+  return -1;
 }
 
+NODEPTR
+ffiNode(const char *buf)
+{
+  NODEPTR r;
+  value_t i = lookupFFIname(buf);
+  if (i < 0) {
+    /* lookup failed, generate a node that will dynamically generate an error */
+    r = alloc_node(T_BADDYN);
+    char *fun = malloc(strlen(buf) + 1);
+    strcpy(fun, buf);
+    STR(r) = fun;
+  } else {
+    r = alloc_node(T_IO_CCALL);
+    SETVALUE(r, i);
+  }
+  return r;
+}
+
 /* If the next input character is c, then consume it, else leave it alone. */
 int
 gobble(BFILE *f, int c)
@@ -1200,8 +1218,7 @@
     /* An FFI name */
     for (int j = 0; (buf[j] = getNT(f)); j++)
       ;
-    r = alloc_node(T_IO_CCALL);
-    SETVALUE(r, lookupFFIname(buf));
+    r = ffiNode(buf);
     return r;
   default:
     buf[0] = c;
@@ -1382,6 +1399,7 @@
       fputc('"', f);
       break;
     }
+  case T_BADDYN: fprintf(f, "^%s", STR(n)); break;
   case T_HDL:
     if (HANDLE(n) == stdin)
       fprintf(f, "IO.stdin");
@@ -1661,7 +1679,7 @@
 #if SANITY
   if (GETTAG(n) != T_PTR) {
     fprintf(stderr, "bad ptr tag %d\n", GETTAG(n));
-    ERR("evalhandle");
+    ERR("evalptr");
   }
 #endif
   return PTR(n);
@@ -1877,6 +1895,7 @@
     case T_DBL:  RET;
     case T_HDL:  RET;
     case T_PTR:  RET;
+    case T_BADDYN: fprintf(stderr, "Unknown FFI function %s\n", STR(n)); ERR("FFI");
 
     case T_S:    GCCHECK(2); CHKARG3; GOAP(new_ap(x, z), new_ap(y, z));                     /* S x y z = x z (y z) */
     case T_SS:   GCCHECK(3); CHKARG4; GOAP(new_ap(x, new_ap(y, w)), new_ap(z, w));          /* S' x y z w = x (y w) (z w) */
@@ -1961,7 +1980,7 @@
       GOIND(s);
 
     /* Retag a word sized value, keeping the bits */
-#define CONV(t) do { CHECK(1); x = evali(ARG(TOP(0))); GCCHECK(1); y = alloc_node(T_DBL); SETVALUE(y, GETVALUE(x)); POP(1); n = TOP(-1); GOIND(y); } while(0)
+#define CONV(t) do { CHECK(1); x = evali(ARG(TOP(0))); GCCHECK(1); y = alloc_node(t); SETVALUE(y, GETVALUE(x)); POP(1); n = TOP(-1); GOIND(y); } while(0)
     case T_TODBL: CONV(T_DBL);
     case T_TOINT: CONV(T_INT);
     case T_TOPTR: CONV(T_PTR);
@@ -2060,8 +2079,7 @@
       CHECK(1);
       msg = evalstring(ARG(TOP(0)));
       GCCHECK(1);
-      x = alloc_node(T_IO_CCALL);
-      SETVALUE(x, lookupFFIname(msg));
+      x = ffiNode(msg);
       free(msg);
       POP(1);
       n = TOP(-1);
@@ -2101,6 +2119,7 @@
   int hdr;
   FILE *hdl;
   char *name;
+  void *ptr;
 
 /* IO operations need all arguments, anything else should not happen. */
 #define CHECKIO(n) do { if (stack_ptr - stk != (n+1)) {ERR("CHECKIO");}; } while(0)
@@ -2321,8 +2340,8 @@
 
     case T_FREEPTR:
       CHECKIO(1);
-      hdl = evalptr(ARG(TOP(1)));
-      free(hdl);
+      ptr = evalptr(ARG(TOP(1)));
+      free(ptr);
       RETIO(combUnit);
 
     case T_NEWCASTRING:
--