mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-19 17:21:59 +03:00
1dc7b74e4e
* [RefC] Suppress code generation for unnecessary arglist wrappers. * [RefC] cleanup dead code of arglist. * Removed Value_Arglist to reduce Closure's allocation overhead. * fix linter error * [RefC] make trampoline() safety. * [RefC] cleanup cStatementsFromANF to keep code simple. * fix linter error * fix linter error * In another time, another galaxy. THE LINTER INVADORS conquaer the all humanity and make them slaves. Under 2024, a only leaved job for every humans is adjusting spaces of source code, or just type gg0vG$== in vim. * [ test ] update golden value * added supports 32 params on closure. * [RefC] [Cleanup] removing duplicate codes. * [RefC] Switch calling conventions based on the number of arguments to avoid limits on the number of arguments and to reduce stack usage. * [RefC] Argument that are too large are placed on the heap, as are closures. * [RefC] use idris2_malloc instead of malloc. * [RefC] [Cleanup] Keep pure things pure. * [RefC] Mapped some special constructors to NULL. This reduces malloc cost and generates simpler code in ConCase. But not work yet. * [RefC] fix merge failure. * [RefC] stringOps.c replace NULL for NIL. * [RefC] cleanup * [RefC] ConstCase now generate simple if-then statements instead of using helpers. This reduces malloc/free costs. * fix indentation * fix whitespaces * [RefC] The name field in Value_Constructor was restored for tycon. But changed to static const*. Hopefully the C compiler will remove the common string constants. The smartest thing to do would be to create a dummy global variable and use its address as a tag, but that would depend on the C compiler to resolve conflicts. * [refc] a big changes of the space * [RefC] Little tricks to reduce temporary variables * spaces * [RefC] fix compiler warnings * [RefC] [test] Perform memory leak analysis, if valgrind is installed. * [RefC] Fix invalid memory read. Fix C compiler warnings. * [RefC] Fix invalid memory read of strSubstr. [test] Perform memory leak analysis, if valgrind is installed. * [test] fix junk line * linter * linter * linter * linter * [RefC] merge with erase_trivial_constuctors * merge w/ erase_trivial_constructors * Revert "merge w/ erase_trivial_constructors" This reverts commitbe593a3715
. * Revert "[RefC] merge with erase_trivial_constuctors" This reverts commit3c21eb45d8
. * merge w/ upstream/main * fix merge failure * rename * fix renaming * [RefC] fix merge fail * [RefC] renamed C functions for safty. * [RefC] cleanup * [RefC] Fix constructor tag of UnconsResult.CHARACTER. --------- Co-authored-by: Mathew Polzin <matt.polzin@gmail.com> Co-authored-by: Guillaume Allais <guillaume.allais@ens-lyon.org>
205 lines
5.4 KiB
C
205 lines
5.4 KiB
C
#include "stringOps.h"
|
|
#include "refc_util.h"
|
|
|
|
Value *tail(Value *input) {
|
|
Value_String *tailStr = IDRIS2_NEW_VALUE(Value_String);
|
|
tailStr->header.tag = STRING_TAG;
|
|
Value_String *s = (Value_String *)input;
|
|
int l = strlen(s->str);
|
|
if (l != 0) {
|
|
tailStr->str = malloc(l);
|
|
IDRIS2_REFC_VERIFY(tailStr->str, "malloc failed");
|
|
memset(tailStr->str, 0, l);
|
|
memcpy(tailStr->str, s->str + 1, l - 1);
|
|
return (Value *)tailStr;
|
|
} else {
|
|
tailStr->str = malloc(1);
|
|
IDRIS2_REFC_VERIFY(tailStr->str, "malloc failed");
|
|
tailStr->str[0] = '\0';
|
|
return (Value *)tailStr;
|
|
}
|
|
}
|
|
|
|
Value *reverse(Value *str) {
|
|
Value_String *retVal = IDRIS2_NEW_VALUE(Value_String);
|
|
retVal->header.tag = STRING_TAG;
|
|
Value_String *input = (Value_String *)str;
|
|
int l = strlen(input->str);
|
|
retVal->str = malloc(l + 1);
|
|
IDRIS2_REFC_VERIFY(retVal->str, "malloc failed");
|
|
memset(retVal->str, 0, l + 1);
|
|
char *p = retVal->str;
|
|
char *q = input->str + (l - 1);
|
|
for (int i = 0; i < l; i++) {
|
|
*p++ = *q--;
|
|
}
|
|
return (Value *)retVal;
|
|
}
|
|
|
|
Value *strIndex(Value *str, Value *i) {
|
|
char *s = ((Value_String *)str)->str;
|
|
int idx = idris2_vp_to_Int64(i);
|
|
return (Value *)idris2_mkChar(s[idx]);
|
|
}
|
|
|
|
Value *strCons(Value *c, Value *str) {
|
|
int l = strlen(((Value_String *)str)->str);
|
|
Value_String *retVal = idris2_mkEmptyString(l + 2);
|
|
retVal->str[0] = idris2_vp_to_Char(c);
|
|
memcpy(retVal->str + 1, ((Value_String *)str)->str, l);
|
|
return (Value *)retVal;
|
|
}
|
|
|
|
Value *strAppend(Value *a, Value *b) {
|
|
int la = strlen(((Value_String *)a)->str);
|
|
int lb = strlen(((Value_String *)b)->str);
|
|
Value_String *retVal = idris2_mkEmptyString(la + lb + 1);
|
|
memcpy(retVal->str, ((Value_String *)a)->str, la);
|
|
memcpy(retVal->str + la, ((Value_String *)b)->str, lb);
|
|
return (Value *)retVal;
|
|
}
|
|
|
|
Value *strSubstr(Value *start, Value *len, Value *s) {
|
|
char *input = ((Value_String *)s)->str;
|
|
int offset = idris2_vp_to_Int64(start); /* start and len was come from Nat. */
|
|
int l = idris2_vp_to_Int64(len);
|
|
|
|
int tailLen = strlen(input) - offset;
|
|
if (tailLen < l) {
|
|
l = tailLen;
|
|
}
|
|
|
|
Value_String *retVal = idris2_mkEmptyString(l + 1);
|
|
memcpy(retVal->str, input + offset, l);
|
|
|
|
return (Value *)retVal;
|
|
}
|
|
|
|
char *fastPack(Value *charList) {
|
|
Value_Constructor *current;
|
|
|
|
int l = 0;
|
|
current = (Value_Constructor *)charList;
|
|
while (current != NULL) {
|
|
l++;
|
|
current = (Value_Constructor *)current->args[1];
|
|
}
|
|
|
|
char *retVal = malloc(l + 1);
|
|
retVal[l] = 0;
|
|
|
|
int i = 0;
|
|
current = (Value_Constructor *)charList;
|
|
while (current != NULL) {
|
|
retVal[i++] = idris2_vp_to_Char(current->args[0]);
|
|
current = (Value_Constructor *)current->args[1];
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
Value *fastUnpack(char *str) {
|
|
if (str[0] == '\0') {
|
|
return NULL;
|
|
}
|
|
|
|
Value_Constructor *retVal = idris2_newConstructor(2, 1);
|
|
retVal->args[0] = idris2_mkChar(str[0]);
|
|
|
|
int i = 1;
|
|
Value_Constructor *current = (Value_Constructor *)retVal;
|
|
Value_Constructor *next;
|
|
while (str[i] != '\0') {
|
|
next = idris2_newConstructor(2, 1);
|
|
next->args[0] = idris2_mkChar(str[i]);
|
|
current->args[1] = (Value *)next;
|
|
|
|
i++;
|
|
current = next;
|
|
}
|
|
current->args[1] = NULL;
|
|
|
|
return (Value *)retVal;
|
|
}
|
|
|
|
char *fastConcat(Value *strList) {
|
|
Value_Constructor *current;
|
|
|
|
int totalLength = 0;
|
|
current = (Value_Constructor *)strList;
|
|
while (current != NULL) {
|
|
totalLength += strlen(((Value_String *)current->args[0])->str);
|
|
current = (Value_Constructor *)current->args[1];
|
|
}
|
|
|
|
char *retVal = malloc(totalLength + 1);
|
|
retVal[totalLength] = '\0';
|
|
|
|
char *currentStr;
|
|
int currentStrLen;
|
|
int offset = 0;
|
|
current = (Value_Constructor *)strList;
|
|
while (current != NULL) {
|
|
currentStr = ((Value_String *)current->args[0])->str;
|
|
currentStrLen = strlen(currentStr);
|
|
memcpy(retVal + offset, currentStr, currentStrLen);
|
|
|
|
offset += currentStrLen;
|
|
current = (Value_Constructor *)current->args[1];
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
typedef struct {
|
|
char *str;
|
|
int pos;
|
|
} String_Iterator;
|
|
|
|
Value *stringIteratorNew(char *str) {
|
|
int l = strlen(str);
|
|
|
|
String_Iterator *it = (String_Iterator *)malloc(sizeof(String_Iterator));
|
|
IDRIS2_REFC_VERIFY(it, "malloc failed");
|
|
it->str = (char *)malloc(l + 1);
|
|
it->pos = 0;
|
|
memcpy(it->str, str, l + 1); // Take a copy of str, in case it gets GCed
|
|
|
|
return (Value *)idris2_makeGCPointer(
|
|
it, (Value_Closure *)idris2_mkClosure(
|
|
(Value * (*)()) onCollectStringIterator, 2, 0));
|
|
}
|
|
|
|
Value *onCollectStringIterator(Value_Pointer *ptr, void *null) {
|
|
String_Iterator *it = (String_Iterator *)ptr->p;
|
|
free(it->str);
|
|
free(it);
|
|
return NULL;
|
|
}
|
|
|
|
Value *stringIteratorToString(void *a, char *str, Value *it_p,
|
|
Value_Closure *f) {
|
|
String_Iterator *it = ((Value_GCPointer *)it_p)->p->p;
|
|
Value *strVal = (Value *)idris2_mkString(it->str + it->pos);
|
|
return idris2_apply_closure(idris2_newReference((Value *)f), strVal);
|
|
}
|
|
|
|
// contrib/Data.String.Iterator.uncons :
|
|
// (str : String) -> (1 it : StringIterator str) -> UnconsResult str
|
|
Value *stringIteratorNext(char *s, Value *it_p) {
|
|
String_Iterator *it = (String_Iterator *)((Value_GCPointer *)it_p)->p->p;
|
|
char c = it->str[it->pos];
|
|
|
|
if (c == '\0')
|
|
return NULL; // EOF [nil]
|
|
|
|
it->pos++; // Ok to do this as StringIterator linear
|
|
|
|
// Character [cons]
|
|
Value_Constructor *retVal = (Value_Constructor *)idris2_newConstructor(2, 1);
|
|
retVal->args[0] = idris2_mkChar(c);
|
|
retVal->args[1] = idris2_newReference(it_p);
|
|
|
|
return (Value *)retVal;
|
|
}
|