Fixed the code style in *.c files to two spaces indentation and add a linter named funstx to Fun. (0.39.0)
This commit is contained in:
parent
33001a7ad2
commit
03b2532474
237 changed files with 17550 additions and 13911 deletions
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @file find.c
|
||||
* @file find.c
|
||||
* @brief Implements the OP_FIND opcode for finding substrings in the VM.
|
||||
*
|
||||
* This file handles the OP_FIND instruction, which finds the index of a substring
|
||||
|
|
@ -33,15 +33,15 @@
|
|||
*/
|
||||
|
||||
case OP_FIND: {
|
||||
Value needle = pop_value(vm);
|
||||
Value hay = pop_value(vm);
|
||||
if (hay.type != VAL_STRING || needle.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: FIND expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
int idx = bi_find(&hay, &needle);
|
||||
free_value(hay);
|
||||
free_value(needle);
|
||||
push_value(vm, make_int(idx));
|
||||
break;
|
||||
Value needle = pop_value(vm);
|
||||
Value hay = pop_value(vm);
|
||||
if (hay.type != VAL_STRING || needle.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: FIND expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
int idx = bi_find(&hay, &needle);
|
||||
free_value(hay);
|
||||
free_value(needle);
|
||||
push_value(vm, make_int(idx));
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,43 +15,43 @@
|
|||
#endif
|
||||
|
||||
case OP_REGEX_MATCH: {
|
||||
Value pattern = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || pattern.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: REGEX_MATCH expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
Value pattern = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || pattern.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: REGEX_MATCH expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifndef __unix__
|
||||
/* Not supported on non-UNIX: return 0 gracefully */
|
||||
free_value(pattern);
|
||||
int truth = 0;
|
||||
free_value(str);
|
||||
push_value(vm, make_int(truth));
|
||||
break;
|
||||
/* Not supported on non-UNIX: return 0 gracefully */
|
||||
free_value(pattern);
|
||||
int truth = 0;
|
||||
free_value(str);
|
||||
push_value(vm, make_int(truth));
|
||||
break;
|
||||
#else
|
||||
regex_t rx;
|
||||
int rc = regcomp(&rx, pattern.s ? pattern.s : "", REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
/* invalid regex -> false */
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
regmatch_t m;
|
||||
int ok = regexec(&rx, str.s ? str.s : "", 1, &m, 0) == 0;
|
||||
int truth = 0;
|
||||
if (ok) {
|
||||
/* full match means the match spans whole string */
|
||||
if (m.rm_so == 0 && str.s) {
|
||||
size_t slen = strlen(str.s);
|
||||
truth = (m.rm_eo == (regoff_t)slen) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
regfree(&rx);
|
||||
regex_t rx;
|
||||
int rc = regcomp(&rx, pattern.s ? pattern.s : "", REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
/* invalid regex -> false */
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, make_int(truth));
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
regmatch_t m;
|
||||
int ok = regexec(&rx, str.s ? str.s : "", 1, &m, 0) == 0;
|
||||
int truth = 0;
|
||||
if (ok) {
|
||||
/* full match means the match spans whole string */
|
||||
if (m.rm_so == 0 && str.s) {
|
||||
size_t slen = strlen(str.s);
|
||||
truth = (m.rm_eo == (regoff_t)slen) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
regfree(&rx);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, make_int(truth));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,105 +12,108 @@
|
|||
/* Regex global replace opcode using POSIX regex */
|
||||
#ifdef __unix__
|
||||
#include <regex.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
case OP_REGEX_REPLACE: {
|
||||
Value repl = pop_value(vm);
|
||||
Value pattern = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || pattern.type != VAL_STRING || repl.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: REGEX_REPLACE expects (string, string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
Value repl = pop_value(vm);
|
||||
Value pattern = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || pattern.type != VAL_STRING || repl.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: REGEX_REPLACE expects (string, string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifndef __unix__
|
||||
/* Not supported: return original string */
|
||||
/* Not supported: return original string */
|
||||
Value out = make_string(str.s ? str.s : "");
|
||||
free_value(repl);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
#else
|
||||
regex_t rx;
|
||||
int rc = regcomp(&rx, pattern.s ? pattern.s : "", REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
/* invalid regex -> return original */
|
||||
Value out = make_string(str.s ? str.s : "");
|
||||
free_value(repl);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
#else
|
||||
regex_t rx;
|
||||
int rc = regcomp(&rx, pattern.s ? pattern.s : "", REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
/* invalid regex -> return original */
|
||||
Value out = make_string(str.s ? str.s : "");
|
||||
free_value(repl);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, out);
|
||||
}
|
||||
|
||||
const char *s = str.s ? str.s : "";
|
||||
const char *r = repl.s ? repl.s : "";
|
||||
|
||||
size_t out_cap = strlen(s) + 1;
|
||||
char *outbuf = (char *)malloc(out_cap);
|
||||
size_t out_len = 0;
|
||||
size_t pos = 0;
|
||||
|
||||
enum { MAX_CAP = 16 };
|
||||
regmatch_t caps[MAX_CAP];
|
||||
|
||||
while (1) {
|
||||
if (regexec(&rx, s + pos, MAX_CAP, caps, 0) != 0) {
|
||||
/* no more matches: append the rest */
|
||||
size_t rest = strlen(s + pos);
|
||||
if (out_len + rest + 1 > out_cap) {
|
||||
out_cap = out_len + rest + 1;
|
||||
outbuf = (char *)realloc(outbuf, out_cap);
|
||||
}
|
||||
memcpy(outbuf + out_len, s + pos, rest + 1);
|
||||
out_len += rest;
|
||||
break;
|
||||
}
|
||||
int mstart = (int)caps[0].rm_so;
|
||||
int mend = (int)caps[0].rm_eo;
|
||||
if (mstart < 0 || mend < mstart) {
|
||||
/* Shouldn't happen, avoid infinite loop */
|
||||
break;
|
||||
}
|
||||
/* append prefix */
|
||||
size_t pre_len = (size_t)mstart;
|
||||
if (out_len + pre_len + 1 > out_cap) {
|
||||
out_cap = (out_len + pre_len + 1) * 2;
|
||||
outbuf = (char *)realloc(outbuf, out_cap);
|
||||
}
|
||||
memcpy(outbuf + out_len, s + pos, pre_len);
|
||||
out_len += pre_len;
|
||||
|
||||
/* append replacement (no backref expansion for simplicity) */
|
||||
size_t rlen = strlen(r);
|
||||
if (out_len + rlen + 1 > out_cap) {
|
||||
out_cap = (out_len + rlen + 1) * 2;
|
||||
outbuf = (char *)realloc(outbuf, out_cap);
|
||||
}
|
||||
memcpy(outbuf + out_len, r, rlen);
|
||||
out_len += rlen;
|
||||
|
||||
/* advance */
|
||||
pos += (size_t)mend;
|
||||
if (mend == 0) { /* prevent zero-length match infinite loop */
|
||||
if (pos < strlen(s)) {
|
||||
if (out_len + 1 > out_cap) {
|
||||
out_cap = out_len + 2;
|
||||
outbuf = (char *)realloc(outbuf, out_cap);
|
||||
}
|
||||
outbuf[out_len++] = s[pos++];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *s = str.s ? str.s : "";
|
||||
const char *r = repl.s ? repl.s : "";
|
||||
|
||||
size_t out_cap = strlen(s) + 1;
|
||||
char *outbuf = (char*)malloc(out_cap);
|
||||
size_t out_len = 0;
|
||||
size_t pos = 0;
|
||||
|
||||
enum { MAX_CAP = 16 };
|
||||
regmatch_t caps[MAX_CAP];
|
||||
|
||||
while (1) {
|
||||
if (regexec(&rx, s + pos, MAX_CAP, caps, 0) != 0) {
|
||||
/* no more matches: append the rest */
|
||||
size_t rest = strlen(s + pos);
|
||||
if (out_len + rest + 1 > out_cap) {
|
||||
out_cap = out_len + rest + 1;
|
||||
outbuf = (char*)realloc(outbuf, out_cap);
|
||||
}
|
||||
memcpy(outbuf + out_len, s + pos, rest + 1);
|
||||
out_len += rest;
|
||||
break;
|
||||
}
|
||||
int mstart = (int)caps[0].rm_so;
|
||||
int mend = (int)caps[0].rm_eo;
|
||||
if (mstart < 0 || mend < mstart) {
|
||||
/* Shouldn't happen, avoid infinite loop */
|
||||
break;
|
||||
}
|
||||
/* append prefix */
|
||||
size_t pre_len = (size_t)mstart;
|
||||
if (out_len + pre_len + 1 > out_cap) {
|
||||
out_cap = (out_len + pre_len + 1) * 2;
|
||||
outbuf = (char*)realloc(outbuf, out_cap);
|
||||
}
|
||||
memcpy(outbuf + out_len, s + pos, pre_len);
|
||||
out_len += pre_len;
|
||||
|
||||
/* append replacement (no backref expansion for simplicity) */
|
||||
size_t rlen = strlen(r);
|
||||
if (out_len + rlen + 1 > out_cap) {
|
||||
out_cap = (out_len + rlen + 1) * 2;
|
||||
outbuf = (char*)realloc(outbuf, out_cap);
|
||||
}
|
||||
memcpy(outbuf + out_len, r, rlen);
|
||||
out_len += rlen;
|
||||
|
||||
/* advance */
|
||||
pos += (size_t)mend;
|
||||
if (mend == 0) { /* prevent zero-length match infinite loop */
|
||||
if (pos < strlen(s)) {
|
||||
if (out_len + 1 > out_cap) { out_cap = out_len + 2; outbuf = (char*)realloc(outbuf, out_cap);}
|
||||
outbuf[out_len++] = s[pos++];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Value out = make_string(outbuf ? outbuf : "");
|
||||
if (outbuf) free(outbuf);
|
||||
regfree(&rx);
|
||||
free_value(repl);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
Value out = make_string(outbuf ? outbuf : "");
|
||||
if (outbuf) free(outbuf);
|
||||
regfree(&rx);
|
||||
free_value(repl);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,19 +12,34 @@
|
|||
/* Regex search (first match) opcode using POSIX regex */
|
||||
#ifdef __unix__
|
||||
#include <regex.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
case OP_REGEX_SEARCH: {
|
||||
Value pattern = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || pattern.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: REGEX_SEARCH expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
Value pattern = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || pattern.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: REGEX_SEARCH expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifndef __unix__
|
||||
/* Return default empty result on unsupported platforms */
|
||||
/* Return default empty result on unsupported platforms */
|
||||
Value m = make_map_empty();
|
||||
(void)map_set(&m, "match", make_string(""));
|
||||
(void)map_set(&m, "start", make_int(-1));
|
||||
(void)map_set(&m, "end", make_int(-1));
|
||||
Value emptyArr = make_array_from_values(NULL, 0);
|
||||
(void)map_set(&m, "groups", emptyArr);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, m);
|
||||
break;
|
||||
#else
|
||||
regex_t rx;
|
||||
int rc = regcomp(&rx, pattern.s ? pattern.s : "", REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
/* invalid regex -> empty result */
|
||||
Value m = make_map_empty();
|
||||
(void)map_set(&m, "match", make_string(""));
|
||||
(void)map_set(&m, "start", make_int(-1));
|
||||
|
|
@ -35,79 +50,71 @@ case OP_REGEX_SEARCH: {
|
|||
free_value(str);
|
||||
push_value(vm, m);
|
||||
break;
|
||||
#else
|
||||
regex_t rx;
|
||||
int rc = regcomp(&rx, pattern.s ? pattern.s : "", REG_EXTENDED);
|
||||
if (rc != 0) {
|
||||
/* invalid regex -> empty result */
|
||||
Value m = make_map_empty();
|
||||
(void)map_set(&m, "match", make_string(""));
|
||||
(void)map_set(&m, "start", make_int(-1));
|
||||
(void)map_set(&m, "end", make_int(-1));
|
||||
Value emptyArr = make_array_from_values(NULL, 0);
|
||||
(void)map_set(&m, "groups", emptyArr);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, m);
|
||||
break;
|
||||
}
|
||||
/* capture up to, say, 10 groups (including whole match) */
|
||||
enum { MAX_CAP = 16 };
|
||||
regmatch_t caps[MAX_CAP];
|
||||
int ok = regexec(&rx, str.s ? str.s : "", MAX_CAP, caps, 0) == 0;
|
||||
Value outMap = make_map_empty();
|
||||
if (!ok) {
|
||||
(void)map_set(&outMap, "match", make_string(""));
|
||||
(void)map_set(&outMap, "start", make_int(-1));
|
||||
(void)map_set(&outMap, "end", make_int(-1));
|
||||
Value emptyArr = make_array_from_values(NULL, 0);
|
||||
(void)map_set(&outMap, "groups", emptyArr);
|
||||
} else {
|
||||
int s = (int)caps[0].rm_so;
|
||||
int e = (int)caps[0].rm_eo;
|
||||
char *matchStr = NULL;
|
||||
if (str.s && s >= 0 && e >= s) {
|
||||
int len = e - s;
|
||||
matchStr = (char *)malloc((size_t)len + 1);
|
||||
if (matchStr) {
|
||||
memcpy(matchStr, str.s + s, (size_t)len);
|
||||
matchStr[len] = '\0';
|
||||
}
|
||||
}
|
||||
/* capture up to, say, 10 groups (including whole match) */
|
||||
enum { MAX_CAP = 16 };
|
||||
regmatch_t caps[MAX_CAP];
|
||||
int ok = regexec(&rx, str.s ? str.s : "", MAX_CAP, caps, 0) == 0;
|
||||
Value outMap = make_map_empty();
|
||||
if (!ok) {
|
||||
(void)map_set(&outMap, "match", make_string(""));
|
||||
(void)map_set(&outMap, "start", make_int(-1));
|
||||
(void)map_set(&outMap, "end", make_int(-1));
|
||||
Value emptyArr = make_array_from_values(NULL, 0);
|
||||
(void)map_set(&outMap, "groups", emptyArr);
|
||||
} else {
|
||||
int s = (int)caps[0].rm_so;
|
||||
int e = (int)caps[0].rm_eo;
|
||||
char *matchStr = NULL;
|
||||
if (str.s && s >= 0 && e >= s) {
|
||||
int len = e - s;
|
||||
matchStr = (char*)malloc((size_t)len + 1);
|
||||
if (matchStr) { memcpy(matchStr, str.s + s, (size_t)len); matchStr[len] = '\0'; }
|
||||
}
|
||||
(void)map_set(&outMap, "match", make_string(matchStr ? matchStr : ""));
|
||||
if (matchStr) free(matchStr);
|
||||
(void)map_set(&outMap, "start", make_int(s));
|
||||
(void)map_set(&outMap, "end", make_int(e));
|
||||
/* groups 1..n */
|
||||
Value groupsArr = make_array_from_values(NULL, 0);
|
||||
/* Count groups available */
|
||||
int groupCount = 0;
|
||||
for (int i = 1; i < MAX_CAP; ++i) {
|
||||
if (caps[i].rm_so == -1 || caps[i].rm_eo == -1) break;
|
||||
groupCount++;
|
||||
}
|
||||
if (groupCount > 0) {
|
||||
Value *vals = (Value*)calloc((size_t)groupCount, sizeof(Value));
|
||||
int vi = 0;
|
||||
for (int i = 1; i <= groupCount; ++i) {
|
||||
int gs = (int)caps[i].rm_so;
|
||||
int ge = (int)caps[i].rm_eo;
|
||||
char *gstr = NULL;
|
||||
if (str.s && gs >= 0 && ge >= gs) {
|
||||
int gl = ge - gs;
|
||||
gstr = (char*)malloc((size_t)gl + 1);
|
||||
if (gstr) { memcpy(gstr, str.s + gs, (size_t)gl); gstr[gl] = '\0'; }
|
||||
}
|
||||
vals[vi++] = make_string(gstr ? gstr : "");
|
||||
if (gstr) free(gstr);
|
||||
}
|
||||
groupsArr = make_array_from_values(vals, groupCount);
|
||||
for (int i = 0; i < groupCount; ++i) free_value(vals[i]);
|
||||
free(vals);
|
||||
}
|
||||
(void)map_set(&outMap, "groups", groupsArr);
|
||||
(void)map_set(&outMap, "match", make_string(matchStr ? matchStr : ""));
|
||||
if (matchStr) free(matchStr);
|
||||
(void)map_set(&outMap, "start", make_int(s));
|
||||
(void)map_set(&outMap, "end", make_int(e));
|
||||
/* groups 1..n */
|
||||
Value groupsArr = make_array_from_values(NULL, 0);
|
||||
/* Count groups available */
|
||||
int groupCount = 0;
|
||||
for (int i = 1; i < MAX_CAP; ++i) {
|
||||
if (caps[i].rm_so == -1 || caps[i].rm_eo == -1) break;
|
||||
groupCount++;
|
||||
}
|
||||
regfree(&rx);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, outMap);
|
||||
break;
|
||||
if (groupCount > 0) {
|
||||
Value *vals = (Value *)calloc((size_t)groupCount, sizeof(Value));
|
||||
int vi = 0;
|
||||
for (int i = 1; i <= groupCount; ++i) {
|
||||
int gs = (int)caps[i].rm_so;
|
||||
int ge = (int)caps[i].rm_eo;
|
||||
char *gstr = NULL;
|
||||
if (str.s && gs >= 0 && ge >= gs) {
|
||||
int gl = ge - gs;
|
||||
gstr = (char *)malloc((size_t)gl + 1);
|
||||
if (gstr) {
|
||||
memcpy(gstr, str.s + gs, (size_t)gl);
|
||||
gstr[gl] = '\0';
|
||||
}
|
||||
}
|
||||
vals[vi++] = make_string(gstr ? gstr : "");
|
||||
if (gstr) free(gstr);
|
||||
}
|
||||
groupsArr = make_array_from_values(vals, groupCount);
|
||||
for (int i = 0; i < groupCount; ++i)
|
||||
free_value(vals[i]);
|
||||
free(vals);
|
||||
}
|
||||
(void)map_set(&outMap, "groups", groupsArr);
|
||||
}
|
||||
regfree(&rx);
|
||||
free_value(pattern);
|
||||
free_value(str);
|
||||
push_value(vm, outMap);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @file split.c
|
||||
* @file split.c
|
||||
* @brief Implements the OP_SPLIT opcode for splitting strings in the VM.
|
||||
*
|
||||
* This file handles the OP_SPLIT instruction, which splits a string into an array
|
||||
|
|
@ -33,15 +33,15 @@
|
|||
*/
|
||||
|
||||
case OP_SPLIT: {
|
||||
Value sep = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || sep.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: SPLIT expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
Value out = bi_split(&str, &sep);
|
||||
free_value(str);
|
||||
free_value(sep);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
Value sep = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || sep.type != VAL_STRING) {
|
||||
fprintf(stderr, "Runtime type error: SPLIT expects (string, string)\n");
|
||||
exit(1);
|
||||
}
|
||||
Value out = bi_split(&str, &sep);
|
||||
free_value(str);
|
||||
free_value(sep);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @file substr.c
|
||||
* @file substr.c
|
||||
* @brief Implements the OP_SUBSTR opcode for extracting substrings in the VM.
|
||||
*
|
||||
* This file handles the OP_SUBSTR instruction, which extracts a substring from a string
|
||||
|
|
@ -34,17 +34,17 @@
|
|||
*/
|
||||
|
||||
case OP_SUBSTR: {
|
||||
Value lenv = pop_value(vm);
|
||||
Value startv = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || startv.type != VAL_INT || lenv.type != VAL_INT) {
|
||||
fprintf(stderr, "Runtime type error: SUBSTR expects (string, int, int)\n");
|
||||
exit(1);
|
||||
}
|
||||
Value out = bi_substr(&str, (int)startv.i, (int)lenv.i);
|
||||
free_value(str);
|
||||
free_value(startv);
|
||||
free_value(lenv);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
Value lenv = pop_value(vm);
|
||||
Value startv = pop_value(vm);
|
||||
Value str = pop_value(vm);
|
||||
if (str.type != VAL_STRING || startv.type != VAL_INT || lenv.type != VAL_INT) {
|
||||
fprintf(stderr, "Runtime type error: SUBSTR expects (string, int, int)\n");
|
||||
exit(1);
|
||||
}
|
||||
Value out = bi_substr(&str, (int)startv.i, (int)lenv.i);
|
||||
free_value(str);
|
||||
free_value(startv);
|
||||
free_value(lenv);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue