mirror of
https://github.com/janet-lang/janet
synced 2024-12-25 07:50:27 +00:00
Move strtod to core, and rename parse-number, parse-integer, and
parse-real functions to scan-number, scan-integer, and scan-real. Add very basic format function for formatting strings for printing.
This commit is contained in:
parent
e4434f74b6
commit
1e4f221170
@ -57,6 +57,7 @@ src/core/math.c
|
||||
src/core/native.c
|
||||
src/core/os.c
|
||||
src/core/string.c
|
||||
src/core/strtod.c
|
||||
src/core/struct.c
|
||||
src/core/symcache.c
|
||||
src/core/table.c
|
||||
@ -83,7 +84,6 @@ src/mainclient/line.h
|
||||
set(PARSER_SOURCES
|
||||
src/parser/ast.c
|
||||
src/parser/parse.c
|
||||
src/parser/strtod.c
|
||||
)
|
||||
|
||||
set(TESTLIB_SOURCES
|
||||
|
@ -37,8 +37,12 @@ static const DstReg cfuns[] = {
|
||||
{"string", dst_core_string},
|
||||
{"symbol", dst_core_symbol},
|
||||
{"buffer", dst_core_buffer},
|
||||
{"format", dst_core_format},
|
||||
{"table", dst_core_table},
|
||||
{"array", dst_core_array},
|
||||
{"scan-number", dst_core_scannumber},
|
||||
{"scan-integer", dst_core_scaninteger},
|
||||
{"scan-real", dst_core_scanreal},
|
||||
{"tuple", dst_core_tuple},
|
||||
{"struct", dst_core_struct},
|
||||
{"buffer", dst_core_buffer},
|
||||
|
@ -218,15 +218,20 @@ static int cfun_concat(DstArgs args) {
|
||||
return dst_return(args, args.v[0]);
|
||||
}
|
||||
|
||||
static const DstReg cfuns[] = {
|
||||
{"array-pop", cfun_pop},
|
||||
{"array-peek", cfun_peek},
|
||||
{"array-push", cfun_push},
|
||||
{"array-setcount", cfun_setcount},
|
||||
{"array-ensure", cfun_ensure},
|
||||
{"array-slice", cfun_slice},
|
||||
{"array-concat", cfun_concat},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Load the array module */
|
||||
int dst_lib_array(DstArgs args) {
|
||||
DstTable *env = dst_env_arg(args);
|
||||
dst_env_def(env, "array-pop", dst_wrap_cfunction(cfun_pop));
|
||||
dst_env_def(env, "array-peek", dst_wrap_cfunction(cfun_peek));
|
||||
dst_env_def(env, "array-push", dst_wrap_cfunction(cfun_push));
|
||||
dst_env_def(env, "array-setcount", dst_wrap_cfunction(cfun_setcount));
|
||||
dst_env_def(env, "array-ensure", dst_wrap_cfunction(cfun_ensure));
|
||||
dst_env_def(env, "array-slice", dst_wrap_cfunction(cfun_slice));
|
||||
dst_env_def(env, "array-concat", dst_wrap_cfunction(cfun_concat));
|
||||
dst_env_cfuns(env, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,6 +95,82 @@ int dst_core_buffer(DstArgs args) {
|
||||
return dst_return(args, dst_wrap_buffer(b));
|
||||
}
|
||||
|
||||
int dst_core_format(DstArgs args) {
|
||||
const uint8_t *format;
|
||||
int32_t i, len, n;
|
||||
DstBuffer buf;
|
||||
dst_minarity(args, 1);
|
||||
dst_arg_bytes(format, len, args, 0);
|
||||
n = 1;
|
||||
dst_buffer_init(&buf, len);
|
||||
for (i = 0; i < len; i++) {
|
||||
uint8_t c = format[i];
|
||||
if (c != '%') {
|
||||
dst_buffer_push_u8(&buf, c);
|
||||
} else {
|
||||
if (++i == len) break;
|
||||
c = format[i];
|
||||
switch (c) {
|
||||
default:
|
||||
dst_buffer_push_u8(&buf, c);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
if (n >= args.n) goto noarg;
|
||||
dst_buffer_push_string(&buf, dst_to_string(args.v[n++]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*args.ret = dst_wrap_string(dst_string(buf.data, buf.count));
|
||||
dst_buffer_deinit(&buf);
|
||||
return 0;
|
||||
noarg:
|
||||
dst_buffer_deinit(&buf);
|
||||
return dst_throw(args, "not enough arguments to format");
|
||||
}
|
||||
|
||||
int dst_core_scannumber(DstArgs args) {
|
||||
const uint8_t *data;
|
||||
Dst x;
|
||||
int32_t len;
|
||||
dst_fixarity(args, 1);
|
||||
dst_arg_bytes(data, len, args, 0);
|
||||
x = dst_scan_number(data, len);
|
||||
if (!dst_checktype(x, DST_INTEGER) && !dst_checktype(x, DST_REAL)) {
|
||||
return dst_throw(args, "error parsing number");
|
||||
}
|
||||
return dst_return(args, x);
|
||||
}
|
||||
|
||||
int dst_core_scaninteger(DstArgs args) {
|
||||
const uint8_t *data;
|
||||
int32_t len, ret;
|
||||
int err = 0;
|
||||
dst_fixarity(args, 1);
|
||||
dst_arg_bytes(data, len, args, 0);
|
||||
ret = dst_scan_integer(data, len, &err);
|
||||
if (err) {
|
||||
return dst_throw(args, "error parsing integer");
|
||||
}
|
||||
return dst_return(args, dst_wrap_integer(ret));
|
||||
}
|
||||
|
||||
int dst_core_scanreal(DstArgs args) {
|
||||
const uint8_t *data;
|
||||
int32_t len;
|
||||
double ret;
|
||||
int err = 0;
|
||||
dst_fixarity(args, 1);
|
||||
dst_arg_bytes(data, len, args, 0);
|
||||
ret = dst_scan_real(data, len, &err);
|
||||
if (err) {
|
||||
return dst_throw(args, "error parsing real");
|
||||
}
|
||||
return dst_return(args, dst_wrap_real(ret));
|
||||
}
|
||||
|
||||
int dst_core_tuple(DstArgs args) {
|
||||
return dst_return(args, dst_wrap_tuple(dst_tuple_n(args.v, args.n)));
|
||||
}
|
||||
@ -137,7 +213,7 @@ int dst_core_gensym(DstArgs args) {
|
||||
}
|
||||
|
||||
int dst_core_length(DstArgs args) {
|
||||
dst_checkmany(args, 0, DST_TFLAG_LENGTHABLE);
|
||||
dst_fixarity(args, 1);
|
||||
return dst_return(args, dst_wrap_integer(dst_length(args.v[0])));
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@ static struct DstScanRes dst_scan_impl(
|
||||
/* underscores are ignored - can be used for separator */
|
||||
} else {
|
||||
int digit = digit_lookup[*str & 0x7F];
|
||||
if (digit >= res.base) goto error;
|
||||
if (*str > 127 || digit >= res.base) goto error;
|
||||
if (res.seenpoint) res.ex--;
|
||||
if (res.mant > 0x00ffffffffffffff)
|
||||
res.ex++;
|
||||
@ -242,7 +242,7 @@ static struct DstScanRes dst_scan_impl(
|
||||
while (str < end && *str == '0') str++;
|
||||
while (str < end && ee < (INT32_MAX / 40)) {
|
||||
int digit = digit_lookup[*str & 0x7F];
|
||||
if (digit >= res.base) goto error;
|
||||
if (*str > 127 || digit >= res.base) goto error;
|
||||
ee = res.base * ee + digit;
|
||||
str++;
|
||||
seenadigit = 1;
|
@ -36,6 +36,11 @@ extern "C" {
|
||||
|
||||
#include "dsttypes.h"
|
||||
|
||||
/* Number scanning */
|
||||
Dst dst_scan_number(const uint8_t *src, int32_t len);
|
||||
int32_t dst_scan_integer(const uint8_t *str, int32_t len, int *err);
|
||||
double dst_scan_real(const uint8_t *str, int32_t len, int *err);
|
||||
|
||||
/* Array functions */
|
||||
DstArray *dst_array(int32_t capacity);
|
||||
DstArray *dst_array_init(DstArray *array, int32_t capacity);
|
||||
@ -250,6 +255,13 @@ int dst_typeabstract_err(DstArgs args, int32_t n, DstAbstractType *at);
|
||||
dst_check(A, N, TYPE);\
|
||||
DEST = dst_unwrap_##NAME((A).v[(N)]); } while (0)
|
||||
|
||||
#define dst_arg_bytes(DESTBYTES, DESTLEN, A, N) do {\
|
||||
if ((A).n <= (N)) return dst_typemany_err(A, N, DST_TFLAG_BYTES);\
|
||||
if (dst_chararray_view((A).v[(N)], &(DESTBYTES), &(DESTLEN))) {\
|
||||
dst_typemany_err(A, N, DST_TFLAG_BYTES);\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
#define dst_arg_fiber(DEST, A, N) _dst_arg(DST_FIBER, fiber, DEST, A, N)
|
||||
#define dst_arg_integer(DEST, A, N) _dst_arg(DST_INTEGER, integer, DEST, A, N)
|
||||
#define dst_arg_real(DEST, A, N) _dst_arg(DST_REAL, real, DEST, A, N)
|
||||
|
@ -84,6 +84,10 @@ int dst_core_describe(DstArgs args);
|
||||
int dst_core_string(DstArgs args);
|
||||
int dst_core_symbol(DstArgs args);
|
||||
int dst_core_buffer(DstArgs args);
|
||||
int dst_core_format(DstArgs args);
|
||||
int dst_core_scannumber(DstArgs args);
|
||||
int dst_core_scaninteger(DstArgs args);
|
||||
int dst_core_scanreal(DstArgs args);
|
||||
int dst_core_tuple(DstArgs args);
|
||||
int dst_core_array(DstArgs args);
|
||||
int dst_core_table(DstArgs args);
|
||||
|
@ -38,11 +38,6 @@ Dst dst_ast_unwrap(Dst x);
|
||||
typedef struct DstParseState DstParseState;
|
||||
typedef struct DstParser DstParser;
|
||||
|
||||
/* Number scanning */
|
||||
Dst dst_scan_number(const uint8_t *src, int32_t len);
|
||||
int32_t dst_scan_integer(const uint8_t *str, int32_t len, int *err);
|
||||
double dst_scan_real(const uint8_t *str, int32_t len, int *err);
|
||||
|
||||
enum DstParserStatus {
|
||||
DST_PARSE_ROOT,
|
||||
DST_PARSE_ERROR,
|
||||
|
@ -102,7 +102,7 @@ typedef enum DstType {
|
||||
#define DST_TFLAG_BOOLEAN (DST_TFLAG_TRUE | DST_TFLAG_FALSE)
|
||||
#define DST_TFLAG_NUMBER (DST_TFLAG_REAL | DST_TFLAG_INTEGER)
|
||||
#define DST_TFLAG_CALLABLE (DST_TFLAG_FUNCTION | DST_TFLAG_CFUNCTION)
|
||||
#define DST_TFLAG_CHARS (DST_TFLAG_STRING | DST_TFLAG_SYMBOL | DST_TFLAG_BUFFER)
|
||||
#define DST_TFLAG_BYTES (DST_TFLAG_STRING | DST_TFLAG_SYMBOL | DST_TFLAG_BUFFER)
|
||||
#define DST_TFLAG_INDEXED (DST_TFLAG_ARRAY | DST_TFLAG_TUPLE)
|
||||
#define DST_TFLAG_DICTIONARY (DST_TFLAG_TABLE | DST_TFLAG_STRUCT)
|
||||
#define DST_TFLAG_LENGTHABLE (DST_TFLAG_CHARS | DST_TFLAG_INDEXED | DST_TFLAG_DICTIONARY)
|
||||
|
@ -86,7 +86,7 @@ The table contains 256 bits, where each bit is 1
|
||||
if the corresponding ascci code is a symbol char, and 0
|
||||
if not. The upper characters are also considered symbol
|
||||
chars and are then checked for utf-8 compliance. */
|
||||
static uint32_t symchars[8] = {
|
||||
static const uint32_t symchars[8] = {
|
||||
0x00000000, 0xF7ffec72, 0xd7ffffff, 0x57fffffe,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
|
||||
};
|
||||
@ -703,49 +703,6 @@ static int cfun_node(DstArgs args) {
|
||||
return dst_return(args, dst_wrap_tuple(dst_tuple_end(tup)));
|
||||
}
|
||||
|
||||
static int cfun_parsenumber(DstArgs args) {
|
||||
const uint8_t *data;
|
||||
Dst x;
|
||||
int32_t len;
|
||||
if (args.n != 1) return dst_throw(args, "expected string or buffer");
|
||||
if (!dst_chararray_view(args.v[0], &data, &len))
|
||||
return dst_throw(args, "expected string or buffer");
|
||||
x = dst_scan_number(data, len);
|
||||
if (!dst_checktype(x, DST_INTEGER) && !dst_checktype(x, DST_REAL)) {
|
||||
return dst_throw(args, "error parsing number");
|
||||
}
|
||||
return dst_return(args, x);
|
||||
}
|
||||
|
||||
static int cfun_parseint(DstArgs args) {
|
||||
const uint8_t *data;
|
||||
int32_t len, ret;
|
||||
int err = 0;
|
||||
if (args.n != 1) return dst_throw(args, "expected string or buffer");
|
||||
if (!dst_chararray_view(args.v[0], &data, &len))
|
||||
return dst_throw(args, "expected string or buffer");
|
||||
ret = dst_scan_integer(data, len, &err);
|
||||
if (err) {
|
||||
return dst_throw(args, "error parsing integer");
|
||||
}
|
||||
return dst_return(args, dst_wrap_integer(ret));
|
||||
}
|
||||
|
||||
static int cfun_parsereal(DstArgs args) {
|
||||
const uint8_t *data;
|
||||
int32_t len;
|
||||
double ret;
|
||||
int err = 0;
|
||||
if (args.n != 1) return dst_throw(args, "expected string or buffer");
|
||||
if (!dst_chararray_view(args.v[0], &data, &len))
|
||||
return dst_throw(args, "expected string or buffer");
|
||||
ret = dst_scan_real(data, len, &err);
|
||||
if (err) {
|
||||
return dst_throw(args, "error parsing real");
|
||||
}
|
||||
return dst_return(args, dst_wrap_real(ret));
|
||||
}
|
||||
|
||||
static const DstReg cfuns[] = {
|
||||
{"parser", cfun_parser},
|
||||
{"parser-produce", cfun_produce},
|
||||
@ -757,9 +714,6 @@ static const DstReg cfuns[] = {
|
||||
{"ast-unwrap1", cfun_unwrap1},
|
||||
{"ast-wrap", cfun_wrap},
|
||||
{"ast-node", cfun_node},
|
||||
{"parse-number", cfun_parsenumber},
|
||||
{"parse-int", cfun_parseint},
|
||||
{"parse-real", cfun_parsereal},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user