@@ -285,19 +285,27 @@ VAL MKSTR(VM* vm, const char* str) {
285285 Closure* cl = allocate(sizeof(Closure) + // Type) + sizeof(char*) +
286286 sizeof(char)*len, 0);
287287 SETTY(cl, CT_STRING);
288− cl -> info.str = (char*)cl + sizeof(Closure);
288+ cl->info.str.str = (char*)cl + sizeof(Closure);
289289 if (str == NULL) {
290− cl->info.str = NULL;
290+ cl->info.str.str = NULL;
291291 } else {
292− strcpy(cl -> info.str, str);
292+ strcpy(cl->info.str.str, str);
293293 }
294+ cl->info.str.len = len > 0 ? len : 0;
294295 return cl;
295296}
296297
297298char* GETSTROFF(VAL stroff) {
298299 // Assume STROFF
299300 StrOffset* root = stroff->info.str_offset;
300− return (root->str->info.str + root->offset);
301+ return (root->str->info.str.str + root->offset);
302+}
303+
304+size_t GETSTROFFLEN(VAL stroff) {
305+ // Assume STROFF
306+ // we're working in char* here so no worries about utf8 char length
307+ StrOffset* root = stroff->info.str_offset;
308+ return (root->str->info.str.len - root->offset);
301309}
302310
303311VAL MKCDATA(VM* vm, CHeapItem * item) {
@@ -342,12 +350,26 @@ VAL MKFLOATc(VM* vm, double val) {
342350}
343351
344352VAL MKSTRc(VM* vm, char* str) {
353+ int len = strlen(str);
354+
355+ Closure* cl = allocate(sizeof(Closure) + // Type) + sizeof(char*) +
356+ sizeof(char)*len+1, 1);
357+ SETTY(cl, CT_STRING);
358+ cl -> info.str.str = (char*)cl + sizeof(Closure);
359+
360+ strcpy(cl->info.str.str, str);
361+ cl->info.str.len = len;
362+ return cl;
363+}
364+
365+VAL MKSTRclen(VM* vm, char* str, int len) {
345366 Closure* cl = allocate(sizeof(Closure) + // Type) + sizeof(char*) +
346− sizeof(char)*strlen(str)+1, 1);
367+ sizeof(char)*len+1, 1);
347368 SETTY(cl, CT_STRING);
348− cl -> info.str = (char*)cl + sizeof(Closure);
369+ cl -> info.str.str = (char*)cl + sizeof(Closure);
349370
350− strcpy(cl -> info.str, str);
371+ strcpy(cl->info.str.str, str);
372+ cl->info.str.len = len;
351373 return cl;
352374}
353375
@@ -397,6 +419,13 @@ VAL MKB64(VM* vm, uint64_t bits64) {
397419 return cl;
398420}
399421
422+void idris_trace(VM* vm, const char* func, int line) {
423+ printf("At %s:%d\n", func, line);
424+ dumpStack(vm);
425+ puts("");
426+ fflush(stdout);
427+}
428+
400429void dumpStack(VM* vm) {
401430 int i = 0;
402431 VAL* root;
@@ -404,7 +433,8 @@ void dumpStack(VM* vm) {
404433 for (root = vm->valstack; root < vm->valstack_top; ++root, ++i) {
405434 printf("%d: ", i);
406435 dumpVal(*root);
407− if (*root >= (VAL)(vm->heap.heap) && *root < (VAL)(vm->heap.end)) { printf("OK"); }
436+ if (*root >= (VAL)(vm->heap.heap) && *root < (VAL)(vm->heap.end)) { printf(" OK"); }
437+ if (root == vm->valstack_base) { printf(" <--- base"); }
408438 printf("\n");
409439 }
410440 printf("RET: ");
@@ -428,7 +458,7 @@ void dumpVal(VAL v) {
428458 printf("] ");
429459 break;
430460 case CT_STRING:
431− printf("STR[%s]", v->info.str);
461+ printf("STR[%s]", v->info.str.str);
432462 break;
433463 case CT_FWD:
434464 printf("CT_FWD ");
@@ -490,8 +520,9 @@ VAL idris_castIntStr(VM* vm, VAL i) {
490520 int x = (int) GETINT(i);
491521 Closure* cl = allocate(sizeof(Closure) + sizeof(char)*16, 0);
492522 SETTY(cl, CT_STRING);
493− cl -> info.str = (char*)cl + sizeof(Closure);
494− sprintf(cl -> info.str, "%d", x);
523+ cl->info.str.str = (char*)cl + sizeof(Closure);
524+ sprintf(cl->info.str.str, "%d", x);
525+ cl->info.str.len = strlen(cl->info.str.str);
495526 return cl;
496527}
497528
@@ -503,32 +534,33 @@ VAL idris_castBitsStr(VM* vm, VAL i) {
503534 case CT_BITS8:
504535 // max length 8 bit unsigned int str 3 chars (256)
505536 cl = allocate(sizeof(Closure) + sizeof(char)*4, 0);
506− cl->info.str = (char*)cl + sizeof(Closure);
507− sprintf(cl->info.str, "%" PRIu8, (uint8_t)i->info.bits8);
537+ cl->info.str.str = (char*)cl + sizeof(Closure);
538+ sprintf(cl->info.str.str, "%" PRIu8, (uint8_t)i->info.bits8);
508539 break;
509540 case CT_BITS16:
510541 // max length 16 bit unsigned int str 5 chars (65,535)
511542 cl = allocate(sizeof(Closure) + sizeof(char)*6, 0);
512− cl->info.str = (char*)cl + sizeof(Closure);
513− sprintf(cl->info.str, "%" PRIu16, (uint16_t)i->info.bits16);
543+ cl->info.str.str = (char*)cl + sizeof(Closure);
544+ sprintf(cl->info.str.str, "%" PRIu16, (uint16_t)i->info.bits16);
514545 break;
515546 case CT_BITS32:
516547 // max length 32 bit unsigned int str 10 chars (4,294,967,295)
517548 cl = allocate(sizeof(Closure) + sizeof(char)*11, 0);
518− cl->info.str = (char*)cl + sizeof(Closure);
519− sprintf(cl->info.str, "%" PRIu32, (uint32_t)i->info.bits32);
549+ cl->info.str.str = (char*)cl + sizeof(Closure);
550+ sprintf(cl->info.str.str, "%" PRIu32, (uint32_t)i->info.bits32);
520551 break;
521552 case CT_BITS64:
522553 // max length 64 bit unsigned int str 20 chars (18,446,744,073,709,551,615)
523554 cl = allocate(sizeof(Closure) + sizeof(char)*21, 0);
524− cl->info.str = (char*)cl + sizeof(Closure);
525− sprintf(cl->info.str, "%" PRIu64, (uint64_t)i->info.bits64);
555+ cl->info.str.str = (char*)cl + sizeof(Closure);
556+ sprintf(cl->info.str.str, "%" PRIu64, (uint64_t)i->info.bits64);
526557 break;
527558 default:
528559 fprintf(stderr, "Fatal Error: ClosureType %d, not an integer type", ty);
529560 exit(EXIT_FAILURE);
530561 }
531562
563+ cl->info.str.len = strlen(cl->info.str.str);
532564 SETTY(cl, CT_STRING);
533565 return cl;
534566}
@@ -545,8 +577,10 @@ VAL idris_castStrInt(VM* vm, VAL i) {
545577VAL idris_castFloatStr(VM* vm, VAL i) {
546578 Closure* cl = allocate(sizeof(Closure) + sizeof(char)*32, 0);
547579 SETTY(cl, CT_STRING);
548− cl -> info.str = (char*)cl + sizeof(Closure);
549− snprintf(cl -> info.str, 32, "%.16g", GETFLOAT(i));
580+ cl->info.str.str = (char*)cl + sizeof(Closure);
581+ snprintf(cl->info.str.str, 32, "%.16g", GETFLOAT(i));
582+
583+ cl->info.str.len = strlen(cl->info.str.str);
550584 return cl;
551585}
552586
@@ -559,11 +593,13 @@ VAL idris_concat(VM* vm, VAL l, VAL r) {
559593 char *ls = GETSTR(l);
560594 // dumpVal(l);
561595 // printf("\n");
562− Closure* cl = allocate(sizeof(Closure) + strlen(ls) + strlen(rs) + 1, 0);
596+ Closure* cl = allocate(sizeof(Closure) + GETSTRLEN(l) + GETSTRLEN(r) + 1, 0);
563597 SETTY(cl, CT_STRING);
564− cl -> info.str = (char*)cl + sizeof(Closure);
565− strcpy(cl -> info.str, ls);
566− strcat(cl -> info.str, rs);
598+ cl->info.str.str = (char*)cl + sizeof(Closure);
599+ strcpy(cl->info.str.str, ls);
600+ strcat(cl->info.str.str, rs);
601+
602+ cl->info.str.len = GETSTRLEN(l) + GETSTRLEN(r);
567603 return cl;
568604}
569605
@@ -670,21 +706,26 @@ VAL idris_strTail(VM* vm, VAL str) {
670706VAL idris_strCons(VM* vm, VAL x, VAL xs) {
671707 char *xstr = GETSTR(xs);
672708 int xval = GETINT(x);
709+ int xlen = GETSTRLEN(xs);
710+
673711 if ((xval & 0x80) == 0) { // ASCII char
674712 Closure* cl = allocate(sizeof(Closure) +
675− strlen(xstr) + 2, 0);
713+ xlen + 2, 0);
676714 SETTY(cl, CT_STRING);
677− cl -> info.str = (char*)cl + sizeof(Closure);
678− cl -> info.str[0] = (char)(GETINT(x));
679− strcpy(cl -> info.str+1, xstr);
715+ cl->info.str.str = (char*)cl + sizeof(Closure);
716+ cl->info.str.str[0] = (char)(GETINT(x));
717+ strcpy(cl->info.str.str+1, xstr);
718+ cl->info.str.len = xlen + 1;
680719 return cl;
681720 } else {
682721 char *init = idris_utf8_fromChar(xval);
683− Closure* cl = allocate(sizeof(Closure) + strlen(init) + strlen(xstr) + 1, 0);
722+ int newlen = strlen(init) + xlen;
723+ Closure* cl = allocate(sizeof(Closure) + newlen + 1, 0);
684724 SETTY(cl, CT_STRING);
685− cl -> info.str = (char*)cl + sizeof(Closure);
686− strcpy(cl -> info.str, init);
687− strcat(cl -> info.str, xstr);
725+ cl->info.str.str = (char*)cl + sizeof(Closure);
726+ strcpy(cl->info.str.str, init);
727+ strcat(cl->info.str.str, xstr);
728+ cl->info.str.len = newlen;
688729 free(init);
689730 return cl;
690731 }
@@ -701,7 +742,7 @@ VAL idris_substr(VM* vm, VAL offset, VAL length, VAL str) {
701742 char* str_val = GETSTR(str);
702743
703744 // If the substring is a suffix, use idris_strShift to avoid reallocating
704− if (offset_val + length_val >= strlen(str_val)) {
745+ if (offset_val + length_val >= GETSTRLEN(str)) {
705746 return idris_strShift(vm, str, offset_val);
706747 }
707748 else {
@@ -709,20 +750,23 @@ VAL idris_substr(VM* vm, VAL offset, VAL length, VAL str) {
709750 char *end = idris_utf8_advance(start, length_val);
710751 Closure* newstr = allocate(sizeof(Closure) + (end - start) +1, 0);
711752 SETTY(newstr, CT_STRING);
712− newstr -> info.str = (char*)newstr + sizeof(Closure);
713− memcpy(newstr -> info.str, start, end - start);
714− *(newstr -> info.str + (end - start) + 1) = '\0';
753+ newstr->info.str.str = (char*)newstr + sizeof(Closure);
754+ memcpy(newstr->info.str.str, start, end - start);
755+ *(newstr->info.str.str + (end - start) + 1) = '\0';
756+ newstr->info.str.len = strlen(newstr->info.str.str);
715757 return newstr;
716758 }
717759}
718760
719761VAL idris_strRev(VM* vm, VAL str) {
720762 char *xstr = GETSTR(str);
721− Closure* cl = allocate(sizeof(Closure) +
722− strlen(xstr) + 1, 0);
763+ int xlen = GETSTRLEN(str);
764+
765+ Closure* cl = allocate(sizeof(Closure) + xlen + 1, 0);
723766 SETTY(cl, CT_STRING);
724− cl->info.str = (char*)cl + sizeof(Closure);
725− idris_utf8_rev(xstr, cl->info.str);
767+ cl->info.str.str = (char*)cl + sizeof(Closure);
768+ cl->info.str.len = xlen;
769+ idris_utf8_rev(xstr, cl->info.str.str);
726770 return cl;
727771}
728772
@@ -832,7 +876,7 @@ VAL doCopyTo(VM* vm, VAL x) {
832876 cl = MKFLOATc(vm, x->info.f);
833877 break;
834878 case CT_STRING:
835− cl = MKSTRc(vm, x->info.str);
879+ cl = MKSTRc(vm, x->info.str.str);
836880 break;
837881 case CT_BIGINT:
838882 cl = MKBIGMc(vm, x->info.ptr);