mirror of
https://github.com/janet-lang/janet
synced 2025-01-12 08:30:26 +00:00
Version 2 of new source mapping.
This commit is contained in:
parent
bb406133de
commit
2e472ec9a3
574
3
574
3
@ -1,574 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Calvin Rose
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DST_TYPES_H_defined
|
||||
#define DST_TYPES_H_defined
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dstconfig.h"
|
||||
|
||||
/* Names of all of the types */
|
||||
extern const char *const dst_type_names[16];
|
||||
|
||||
/* Fiber signals */
|
||||
typedef enum {
|
||||
DST_SIGNAL_OK,
|
||||
DST_SIGNAL_ERROR,
|
||||
DST_SIGNAL_DEBUG,
|
||||
DST_SIGNAL_YIELD,
|
||||
DST_SIGNAL_USER0,
|
||||
DST_SIGNAL_USER1,
|
||||
DST_SIGNAL_USER2,
|
||||
DST_SIGNAL_USER3,
|
||||
DST_SIGNAL_USER4,
|
||||
DST_SIGNAL_USER5,
|
||||
DST_SIGNAL_USER6,
|
||||
DST_SIGNAL_USER7,
|
||||
DST_SIGNAL_USER8,
|
||||
DST_SIGNAL_USER9
|
||||
} DstSignal;
|
||||
|
||||
/* Fiber statuses - mostly corresponds to signals. */
|
||||
typedef enum {
|
||||
DST_STATUS_DEAD,
|
||||
DST_STATUS_ERROR,
|
||||
DST_STATUS_DEBUG,
|
||||
DST_STATUS_PENDING,
|
||||
DST_STATUS_USER0,
|
||||
DST_STATUS_USER1,
|
||||
DST_STATUS_USER2,
|
||||
DST_STATUS_USER3,
|
||||
DST_STATUS_USER4,
|
||||
DST_STATUS_USER5,
|
||||
DST_STATUS_USER6,
|
||||
DST_STATUS_USER7,
|
||||
DST_STATUS_USER8,
|
||||
DST_STATUS_USER9,
|
||||
DST_STATUS_NEW,
|
||||
DST_STATUS_ALIVE
|
||||
} DstFiberStatus;
|
||||
|
||||
#ifdef DST_NANBOX
|
||||
typedef union Dst Dst;
|
||||
#else
|
||||
typedef struct Dst Dst;
|
||||
#endif
|
||||
|
||||
/* All of the dst types */
|
||||
typedef struct DstFunction DstFunction;
|
||||
typedef struct DstArray DstArray;
|
||||
typedef struct DstBuffer DstBuffer;
|
||||
typedef struct DstTable DstTable;
|
||||
typedef struct DstFiber DstFiber;
|
||||
|
||||
/* Other structs */
|
||||
typedef struct DstAbstractHeader DstAbstractHeader;
|
||||
typedef struct DstFuncDef DstFuncDef;
|
||||
typedef struct DstFuncEnv DstFuncEnv;
|
||||
typedef struct DstKV DstKV;
|
||||
typedef struct DstStackFrame DstStackFrame;
|
||||
typedef struct DstAbstractType DstAbstractType;
|
||||
typedef struct DstArgs DstArgs;
|
||||
typedef struct DstReg DstReg;
|
||||
typedef struct DstSourceMapping DstSourceMapping;
|
||||
typedef int (*DstCFunction)(DstArgs args);
|
||||
|
||||
/* Basic types for all Dst Values */
|
||||
typedef enum DstType {
|
||||
DST_NIL,
|
||||
DST_FALSE,
|
||||
DST_TRUE,
|
||||
DST_FIBER,
|
||||
DST_INTEGER,
|
||||
DST_REAL,
|
||||
DST_STRING,
|
||||
DST_SYMBOL,
|
||||
DST_ARRAY,
|
||||
DST_TUPLE,
|
||||
DST_TABLE,
|
||||
DST_STRUCT,
|
||||
DST_BUFFER,
|
||||
DST_FUNCTION,
|
||||
DST_CFUNCTION,
|
||||
DST_ABSTRACT
|
||||
} DstType;
|
||||
|
||||
#define DST_COUNT_TYPES (DST_ABSTRACT + 1)
|
||||
|
||||
/* Type flags */
|
||||
#define DST_TFLAG_NIL (1 << DST_NIL)
|
||||
#define DST_TFLAG_FALSE (1 << DST_FALSE)
|
||||
#define DST_TFLAG_TRUE (1 << DST_TRUE)
|
||||
#define DST_TFLAG_FIBER (1 << DST_FIBER)
|
||||
#define DST_TFLAG_INTEGER (1 << DST_INTEGER)
|
||||
#define DST_TFLAG_REAL (1 << DST_REAL)
|
||||
#define DST_TFLAG_STRING (1 << DST_STRING)
|
||||
#define DST_TFLAG_SYMBOL (1 << DST_SYMBOL)
|
||||
#define DST_TFLAG_ARRAY (1 << DST_ARRAY)
|
||||
#define DST_TFLAG_TUPLE (1 << DST_TUPLE)
|
||||
#define DST_TFLAG_TABLE (1 << DST_TABLE)
|
||||
#define DST_TFLAG_STRUCT (1 << DST_STRUCT)
|
||||
#define DST_TFLAG_BUFFER (1 << DST_BUFFER)
|
||||
#define DST_TFLAG_FUNCTION (1 << DST_FUNCTION)
|
||||
#define DST_TFLAG_CFUNCTION (1 << DST_CFUNCTION)
|
||||
#define DST_TFLAG_ABSTRACT (1 << DST_ABSTRACT)
|
||||
|
||||
/* Some abstractions */
|
||||
#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_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)
|
||||
|
||||
/* We provide two possible implemenations of Dsts. The preferred
|
||||
* nanboxing approach, and the standard C version. Code in the rest of the
|
||||
* application must interact through exposed interface. */
|
||||
|
||||
/* Required interface for Dst */
|
||||
/* wrap and unwrap for all types */
|
||||
/* Get type quickly */
|
||||
/* Check against type quickly */
|
||||
/* Small footprint */
|
||||
/* 32 bit integer support */
|
||||
|
||||
/* dst_type(x)
|
||||
* dst_checktype(x, t)
|
||||
* dst_wrap_##TYPE(x)
|
||||
* dst_unwrap_##TYPE(x)
|
||||
* dst_truthy(x)
|
||||
* dst_memclear(p, n) - clear memory for hash tables to nils
|
||||
* dst_u64(x) - get 64 bits of payload for hashing
|
||||
*/
|
||||
|
||||
#ifdef DST_NANBOX
|
||||
|
||||
#include <math.h>
|
||||
|
||||
union Dst {
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
double real;
|
||||
};
|
||||
|
||||
#define dst_u64(x) ((x).u64)
|
||||
|
||||
/* This representation uses 48 bit pointers. The trade off vs. the LuaJIT style
|
||||
* 47 bit payload representaion is that the type bits are no long contiguous. Type
|
||||
* checking can still be fast, but typewise polymorphism takes a bit longer. However,
|
||||
* hopefully we can avoid some annoying problems that occur when trying to use 47 bit pointers
|
||||
* in a 48 bit address space (Linux on ARM). If DST_NANBOX_47 is set, use 47 bit tagged pointers. */
|
||||
|
||||
/* |.......Tag.......|.......................Payload..................| */
|
||||
/* Non-double: t|11111111111|1ttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */
|
||||
/* Types of NIL, TRUE, and FALSE must have payload set to all 1s. */
|
||||
|
||||
/* Double (no NaNs): x xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */
|
||||
|
||||
#if defined (DST_NANBOX_47) || defined (DST_32)
|
||||
|
||||
#define DST_NANBOX_TAGBITS 0xFFFF800000000000llu
|
||||
#define DST_NANBOX_PAYLOADBITS 0x00007FFFFFFFFFFFllu
|
||||
|
||||
|
||||
#define dst_nanbox_lowtag(type) \
|
||||
((uint64_t)(type) | 0x1FFF0)
|
||||
|
||||
#define dst_nanbox_tag(type) \
|
||||
(dst_nanbox_lowtag(type) << 47)
|
||||
|
||||
#define dst_type(x) \
|
||||
(isnan((x).real) \
|
||||
? (((x).u64 >> 47) & 0xF) \
|
||||
: DST_REAL)
|
||||
|
||||
#else /* defined (DST_NANBOX_47) || defined (DST_32) */
|
||||
|
||||
#define DST_NANBOX_TAGBITS 0xFFFF000000000000llu
|
||||
#define DST_NANBOX_PAYLOADBITS 0x0000FFFFFFFFFFFFllu
|
||||
|
||||
#define dst_nanbox_lowtag(type) \
|
||||
((((uint64_t)(type) & 0x1) << 15) | 0x7FF8 | ((type) >> 1))
|
||||
|
||||
#define dst_nanbox_tag(type) \
|
||||
(dst_nanbox_lowtag(type) << 48)
|
||||
|
||||
#define dst_type(x) \
|
||||
(isnan((x).real) \
|
||||
? (((x).u64 >> 47) & 0xE) | ((x).u64 >> 63) \
|
||||
: DST_REAL)
|
||||
|
||||
#endif /* defined (DST_NANBOX_47) || defined (DST_32) */
|
||||
|
||||
/* 32 bit mode will not use the full payload for pointers. */
|
||||
#ifdef DST_32
|
||||
|
||||
#define DST_NANBOX_POINTERBITS 0xFFFFFFFFllu
|
||||
#else
|
||||
#define DST_NANBOX_POINTERBITS DST_NANBOX_PAYLOADBITS
|
||||
#endif
|
||||
|
||||
#define dst_nanbox_checkauxtype(x, type) \
|
||||
(((x).u64 & DST_NANBOX_TAGBITS) == dst_nanbox_tag((type)))
|
||||
|
||||
#define dst_nanbox_isreal(x) \
|
||||
(!isnan((x).real) || dst_nanbox_checkauxtype((x), DST_REAL))
|
||||
|
||||
#define dst_checktype(x, t) \
|
||||
(((t) == DST_REAL) \
|
||||
? dst_nanbox_isreal(x) \
|
||||
: dst_nanbox_checkauxtype((x), (t)))
|
||||
|
||||
void *dst_nanbox_to_pointer(Dst x);
|
||||
void dst_nanbox_memempty(DstKV *mem, int32_t count);
|
||||
void *dst_nanbox_memalloc_empty(int32_t count);
|
||||
Dst dst_nanbox_from_pointer(void *p, uint64_t tagmask);
|
||||
Dst dst_nanbox_from_cpointer(const void *p, uint64_t tagmask);
|
||||
Dst dst_nanbox_from_double(double d);
|
||||
Dst dst_nanbox_from_bits(uint64_t bits);
|
||||
|
||||
#define dst_memempty(mem, len) dst_nanbox_memempty((mem), (len))
|
||||
#define dst_memalloc_empty(count) dst_nanbox_memalloc_empty(count)
|
||||
|
||||
/* Todo - check for single mask operation */
|
||||
#define dst_truthy(x) \
|
||||
(!(dst_checktype((x), DST_NIL) || dst_checktype((x), DST_FALSE)))
|
||||
|
||||
#define dst_nanbox_from_payload(t, p) \
|
||||
dst_nanbox_from_bits(dst_nanbox_tag(t) | (p))
|
||||
|
||||
#define dst_nanbox_wrap_(p, t) \
|
||||
dst_nanbox_from_pointer((p), dst_nanbox_tag(t))
|
||||
|
||||
#define dst_nanbox_wrap_c(p, t) \
|
||||
dst_nanbox_from_cpointer((p), dst_nanbox_tag(t))
|
||||
|
||||
/* Wrap the simple types */
|
||||
#define dst_wrap_nil() dst_nanbox_from_payload(DST_NIL, 1)
|
||||
#define dst_wrap_true() dst_nanbox_from_payload(DST_TRUE, 1)
|
||||
#define dst_wrap_false() dst_nanbox_from_payload(DST_FALSE, 1)
|
||||
#define dst_wrap_boolean(b) dst_nanbox_from_payload((b) ? DST_TRUE : DST_FALSE, 1)
|
||||
#define dst_wrap_integer(i) dst_nanbox_from_payload(DST_INTEGER, (uint32_t)(i))
|
||||
#define dst_wrap_real(r) dst_nanbox_from_double(r)
|
||||
|
||||
/* Unwrap the simple types */
|
||||
#define dst_unwrap_boolean(x) \
|
||||
(dst_checktype(x, DST_TRUE))
|
||||
#define dst_unwrap_integer(x) \
|
||||
((int32_t)((x).u64 & 0xFFFFFFFFlu))
|
||||
#define dst_unwrap_real(x) ((x).real)
|
||||
|
||||
/* Wrap the pointer types */
|
||||
#define dst_wrap_struct(s) dst_nanbox_wrap_c((s), DST_STRUCT)
|
||||
#define dst_wrap_tuple(s) dst_nanbox_wrap_c((s), DST_TUPLE)
|
||||
#define dst_wrap_fiber(s) dst_nanbox_wrap_((s), DST_FIBER)
|
||||
#define dst_wrap_array(s) dst_nanbox_wrap_((s), DST_ARRAY)
|
||||
#define dst_wrap_table(s) dst_nanbox_wrap_((s), DST_TABLE)
|
||||
#define dst_wrap_buffer(s) dst_nanbox_wrap_((s), DST_BUFFER)
|
||||
#define dst_wrap_string(s) dst_nanbox_wrap_c((s), DST_STRING)
|
||||
#define dst_wrap_symbol(s) dst_nanbox_wrap_c((s), DST_SYMBOL)
|
||||
#define dst_wrap_abstract(s) dst_nanbox_wrap_((s), DST_ABSTRACT)
|
||||
#define dst_wrap_function(s) dst_nanbox_wrap_((s), DST_FUNCTION)
|
||||
#define dst_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_CFUNCTION)
|
||||
|
||||
/* Unwrap the pointer types */
|
||||
#define dst_unwrap_struct(x) ((const DstKV *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_tuple(x) ((const Dst *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_fiber(x) ((DstFiber *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_array(x) ((DstArray *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_table(x) ((DstTable *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_buffer(x) ((DstBuffer *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_string(x) ((const uint8_t *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_symbol(x) ((const uint8_t *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_abstract(x) (dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_pointer(x) (dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_function(x) ((DstFunction *)dst_nanbox_to_pointer(x))
|
||||
#define dst_unwrap_cfunction(x) ((DstCFunction)dst_nanbox_to_pointer(x))
|
||||
|
||||
/* End of [#ifdef DST_NANBOX] */
|
||||
#else
|
||||
|
||||
/* A general dst value type */
|
||||
struct Dst {
|
||||
union {
|
||||
uint64_t u64;
|
||||
double real;
|
||||
int32_t integer;
|
||||
void *pointer;
|
||||
const void *cpointer;
|
||||
} as;
|
||||
DstType type;
|
||||
};
|
||||
|
||||
#define dst_u64(x) ((x).as.u64)
|
||||
#define dst_memempty(mem, count) memset((mem), 0, sizeof(DstKV) * (count))
|
||||
#define dst_memalloc_empty(count) calloc((count), sizeof(DstKV))
|
||||
#define dst_type(x) ((x).type)
|
||||
#define dst_checktype(x, t) ((x).type == (t))
|
||||
#define dst_truthy(x) \
|
||||
((x).type != DST_NIL && (x).type != DST_FALSE)
|
||||
|
||||
#define dst_unwrap_struct(x) ((const DstKV *)(x).as.pointer)
|
||||
#define dst_unwrap_tuple(x) ((const Dst *)(x).as.pointer)
|
||||
#define dst_unwrap_fiber(x) ((DstFiber *)(x).as.pointer)
|
||||
#define dst_unwrap_array(x) ((DstArray *)(x).as.pointer)
|
||||
#define dst_unwrap_table(x) ((DstTable *)(x).as.pointer)
|
||||
#define dst_unwrap_buffer(x) ((DstBuffer *)(x).as.pointer)
|
||||
#define dst_unwrap_string(x) ((const uint8_t *)(x).as.pointer)
|
||||
#define dst_unwrap_symbol(x) ((const uint8_t *)(x).as.pointer)
|
||||
#define dst_unwrap_abstract(x) ((x).as.pointer)
|
||||
#define dst_unwrap_pointer(x) ((x).as.pointer)
|
||||
#define dst_unwrap_function(x) ((DstFunction *)(x).as.pointer)
|
||||
#define dst_unwrap_cfunction(x) ((DstCFunction)(x).as.pointer)
|
||||
#define dst_unwrap_boolean(x) ((x).type == DST_TRUE)
|
||||
#define dst_unwrap_integer(x) ((x).as.integer)
|
||||
#define dst_unwrap_real(x) ((x).as.real)
|
||||
|
||||
Dst dst_wrap_nil(void);
|
||||
Dst dst_wrap_real(double x);
|
||||
Dst dst_wrap_integer(int32_t x);
|
||||
Dst dst_wrap_true(void);
|
||||
Dst dst_wrap_false(void);
|
||||
Dst dst_wrap_boolean(int x);
|
||||
Dst dst_wrap_string(const uint8_t *x);
|
||||
Dst dst_wrap_symbol(const uint8_t *x);
|
||||
Dst dst_wrap_array(DstArray *x);
|
||||
Dst dst_wrap_tuple(const Dst *x);
|
||||
Dst dst_wrap_struct(const DstKV *x);
|
||||
Dst dst_wrap_fiber(DstFiber *x);
|
||||
Dst dst_wrap_buffer(DstBuffer *x);
|
||||
Dst dst_wrap_function(DstFunction *x);
|
||||
Dst dst_wrap_cfunction(DstCFunction x);
|
||||
Dst dst_wrap_table(DstTable *x);
|
||||
Dst dst_wrap_abstract(void *x);
|
||||
|
||||
/* End of tagged union implementation */
|
||||
#endif
|
||||
|
||||
/* Hold components of arguments passed to DstCFunction. */
|
||||
struct DstArgs {
|
||||
int32_t n;
|
||||
Dst *v;
|
||||
Dst *ret;
|
||||
};
|
||||
|
||||
/* Fiber flags */
|
||||
#define DST_FIBER_FLAG_SIGNAL_WAITING (1 << 30)
|
||||
|
||||
/* Fiber signal masks. */
|
||||
#define DST_FIBER_MASK_ERROR 2
|
||||
#define DST_FIBER_MASK_DEBUG 4
|
||||
#define DST_FIBER_MASK_YIELD 8
|
||||
|
||||
#define DST_FIBER_MASK_USER0 (16 << 0)
|
||||
#define DST_FIBER_MASK_USER1 (16 << 1)
|
||||
#define DST_FIBER_MASK_USER2 (16 << 2)
|
||||
#define DST_FIBER_MASK_USER3 (16 << 3)
|
||||
#define DST_FIBER_MASK_USER4 (16 << 4)
|
||||
#define DST_FIBER_MASK_USER5 (16 << 5)
|
||||
#define DST_FIBER_MASK_USER6 (16 << 6)
|
||||
#define DST_FIBER_MASK_USER7 (16 << 7)
|
||||
#define DST_FIBER_MASK_USER8 (16 << 8)
|
||||
#define DST_FIBER_MASK_USER9 (16 << 9)
|
||||
|
||||
#define DST_FIBER_MASK_USERN(N) (16 << (N))
|
||||
#define DST_FIBER_MASK_USER 0x3FF0
|
||||
|
||||
#define DST_FIBER_STATUS_MASK 0xFF0000
|
||||
#define DST_FIBER_STATUS_OFFSET 16
|
||||
|
||||
/* A lightweight green thread in dst. Does not correspond to
|
||||
* operating system threads. */
|
||||
struct DstFiber {
|
||||
Dst *data;
|
||||
DstFiber *child; /* Keep linked list of fibers for restarting pending fibers */
|
||||
DstFunction *root; /* First value */
|
||||
int32_t frame; /* Index of the stack frame */
|
||||
int32_t stackstart; /* Beginning of next args */
|
||||
int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */
|
||||
int32_t capacity;
|
||||
int32_t maxstack; /* Arbitrary defined limit for stack overflow */
|
||||
uint32_t flags; /* Various flags */
|
||||
};
|
||||
|
||||
/* Mark if a stack frame is a tail call for debugging */
|
||||
#define DST_STACKFRAME_TAILCALL 1
|
||||
|
||||
/* A stack frame on the fiber. Is stored along with the stack values. */
|
||||
struct DstStackFrame {
|
||||
DstFunction *func;
|
||||
uint32_t *pc;
|
||||
DstFuncEnv *env;
|
||||
int32_t prevframe;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/* Number of Dsts a frame takes up in the stack */
|
||||
#define DST_FRAME_SIZE ((sizeof(DstStackFrame) + sizeof(Dst) - 1) / sizeof(Dst))
|
||||
|
||||
/* A dynamic array type. */
|
||||
struct DstArray {
|
||||
Dst *data;
|
||||
int32_t count;
|
||||
int32_t capacity;
|
||||
};
|
||||
|
||||
/* A bytebuffer type. Used as a mutable string or string builder. */
|
||||
struct DstBuffer {
|
||||
uint8_t *data;
|
||||
int32_t count;
|
||||
int32_t capacity;
|
||||
};
|
||||
|
||||
/* A mutable associative data type. Backed by a hashtable. */
|
||||
struct DstTable {
|
||||
DstKV *data;
|
||||
DstTable *proto;
|
||||
int32_t count;
|
||||
int32_t capacity;
|
||||
int32_t deleted;
|
||||
};
|
||||
|
||||
/* A key value pair in a struct or table */
|
||||
struct DstKV {
|
||||
Dst key;
|
||||
Dst value;
|
||||
};
|
||||
|
||||
/* Some function defintion flags */
|
||||
#define DST_FUNCDEF_FLAG_VARARG 1
|
||||
#define DST_FUNCDEF_FLAG_NEEDSENV 4
|
||||
|
||||
struct DstSourceMapping {
|
||||
int32_t start;
|
||||
int32_t end;
|
||||
};
|
||||
|
||||
/* A function definition. Contains information needed to instantiate closures. */
|
||||
struct DstFuncDef {
|
||||
int32_t *environments; /* Which environments to capture from parent. */
|
||||
Dst *constants;
|
||||
DstFuncDef **defs;
|
||||
uint32_t *bytecode;
|
||||
|
||||
/* Various debug information */
|
||||
DstSourceMapping *sourcemap;
|
||||
const uint8_t *source;
|
||||
const uint8_t *sourcepath;
|
||||
const uint8_t *name;
|
||||
|
||||
uint32_t flags;
|
||||
int32_t slotcount; /* The amount of stack space required for the function */
|
||||
int32_t arity; /* Not including varargs */
|
||||
int32_t constants_length;
|
||||
int32_t bytecode_length;
|
||||
int32_t environments_length;
|
||||
int32_t defs_length;
|
||||
};
|
||||
|
||||
/* A fuction environment */
|
||||
struct DstFuncEnv {
|
||||
union {
|
||||
DstFiber *fiber;
|
||||
Dst *values;
|
||||
} as;
|
||||
int32_t length; /* Size of environment */
|
||||
int32_t offset; /* Stack offset when values still on stack. If offset is <= 0, then
|
||||
environment is no longer on the stack. */
|
||||
};
|
||||
|
||||
/* A function */
|
||||
struct DstFunction {
|
||||
DstFuncDef *def;
|
||||
DstFuncEnv *envs[];
|
||||
};
|
||||
|
||||
/* Parser types */
|
||||
typedef struct {
|
||||
Dst key;
|
||||
int32_t start;
|
||||
int32_t end;
|
||||
} DstParseKV;
|
||||
|
||||
typedef struct {
|
||||
DstParseKV *kvs;
|
||||
int32_t capacity;
|
||||
int32_t count;
|
||||
} DstParseMap;
|
||||
|
||||
typedef struct DstParseState DstParseState;
|
||||
typedef struct DstParser DstParser;
|
||||
|
||||
enum DstParserStatus {
|
||||
DST_PARSE_ROOT,
|
||||
DST_PARSE_ERROR,
|
||||
DST_PARSE_FULL,
|
||||
DST_PARSE_PENDING
|
||||
};
|
||||
|
||||
/* A dst parser */
|
||||
struct DstParser {
|
||||
Dst* args;
|
||||
const char *error;
|
||||
const uint8_t *sourcelink;
|
||||
DstParseState *states;
|
||||
uint8_t *buf;
|
||||
|
||||
DstParseMap map; /* optional map */
|
||||
size_t argcount;
|
||||
size_t argcap;
|
||||
size_t statecount;
|
||||
size_t statecap;
|
||||
size_t bufcount;
|
||||
size_t bufcap;
|
||||
size_t index;
|
||||
int lookback;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* Defines an abstract type */
|
||||
struct DstAbstractType {
|
||||
const char *name;
|
||||
int (*gc)(void *data, size_t len);
|
||||
int (*gcmark)(void *data, size_t len);
|
||||
};
|
||||
|
||||
/* Contains information about userdata */
|
||||
struct DstAbstractHeader {
|
||||
const DstAbstractType *type;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct DstReg {
|
||||
const char *name;
|
||||
DstCFunction cfun;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DST_TYPES_H_defined */
|
2
Makefile
2
Makefile
@ -32,7 +32,7 @@ BINDIR=$(PREFIX)/bin
|
||||
# TODO - when api is finalized, only export public symbols instead of using rdynamic
|
||||
# which exports all symbols. Saves a few KB in binary.
|
||||
|
||||
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -s -O2
|
||||
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -O2
|
||||
CLIBS=-lm -ldl
|
||||
PREFIX=/usr/local
|
||||
DST_TARGET=dst
|
||||
|
18
examples/error.dst
Normal file
18
examples/error.dst
Normal file
@ -0,0 +1,18 @@
|
||||
# An example file that errors out. Run with ./dst examples/error.dst
|
||||
# to see stack trace for runtime errors.
|
||||
|
||||
(defn bark [x]
|
||||
(print "Woof!")
|
||||
(print x)
|
||||
(error x)
|
||||
(print "Woof!"))
|
||||
|
||||
(defn bork [x]
|
||||
(bark (* 2 x))
|
||||
(bark (* 3 x)))
|
||||
|
||||
(defn pupper []
|
||||
(bork 3)
|
||||
1)
|
||||
|
||||
(pupper)
|
@ -931,15 +931,17 @@ respectively.
|
||||
This function can be used to implement a repl very easily, simply
|
||||
pass a function that reads line from stdin to chunks, and print to
|
||||
onvalue."
|
||||
[env chunks onvalue onerr]
|
||||
[env chunks onvalue onerr where]
|
||||
|
||||
# Are we done yet?
|
||||
(var going true)
|
||||
|
||||
# The parser object
|
||||
(def p (parser.new 1))
|
||||
(if where (parser.set-source p where))
|
||||
|
||||
# Fiber stream of characters
|
||||
(var byteindex 0)
|
||||
(def chars (coro
|
||||
(def buf @"")
|
||||
(var len 1)
|
||||
@ -948,6 +950,7 @@ onvalue."
|
||||
(chunks buf p)
|
||||
(:= len (length buf))
|
||||
(loop [i :range [0 len]]
|
||||
(++ byteindex)
|
||||
(yield (get buf i))))
|
||||
0))
|
||||
|
||||
@ -956,31 +959,36 @@ onvalue."
|
||||
(while going
|
||||
(switch (parser.status p)
|
||||
:full (yield (parser.produce p))
|
||||
:error (onerr "parse" (parser.error p))
|
||||
:error (onerr where "parse" (string (parser.error p) " at byte index " byteindex))
|
||||
(switch (fiber.status chars)
|
||||
:new (parser.byte p (resume chars))
|
||||
:pending (parser.byte p (resume chars))
|
||||
(:= going false))))
|
||||
(when (not= :root (parser.status p))
|
||||
(onerr "parse" "unexpected end of source"))))
|
||||
(onerr where "parse" "unexpected end of source"))))
|
||||
|
||||
# Evaluate 1 source form
|
||||
(defn eval1 [source]
|
||||
(var good true)
|
||||
(def f (fiber.new (fn []
|
||||
(def res (compile source env))
|
||||
(def res (compile source env p))
|
||||
(if (= (type res) :function)
|
||||
(res)
|
||||
(do
|
||||
(:= good false)
|
||||
(onerr "compile" (get res :error))))) :a))
|
||||
(def {:error err :error-start errs :error-end erre} res)
|
||||
(onerr where "compile"
|
||||
(if (<= 0 errs)
|
||||
(string err " at (" errs ":" erre ")")
|
||||
err)))))
|
||||
:a))
|
||||
(def res (resume f))
|
||||
(when good
|
||||
(def sig (fiber.status f))
|
||||
(if going
|
||||
(if (= sig :dead)
|
||||
(onvalue res)
|
||||
(onerr "runtime" res f)))))
|
||||
(onerr where "runtime" res f)))))
|
||||
|
||||
# Run loop
|
||||
(def oldenv *env*)
|
||||
@ -991,8 +999,8 @@ onvalue."
|
||||
env)
|
||||
|
||||
(defn default-error-handler
|
||||
[t x f]
|
||||
(file.write stdout (string t " error: "))
|
||||
[source t x f]
|
||||
(file.write stdout (string t " error in " source ": "))
|
||||
(if (bytes? x)
|
||||
(do (file.write stdout x)
|
||||
(file.write stdout "\n"))
|
||||
@ -1014,11 +1022,12 @@ onvalue."
|
||||
(if name
|
||||
(file.write stdout " " name)
|
||||
(when func (file.write stdout " " func)))
|
||||
(if source (file.write stdout " [" source "]"))
|
||||
(cond
|
||||
source-start (file.write stdout " at byte range ("
|
||||
(string source-start) ":" (string source-end) ")")
|
||||
pc (file.write stdout " at (pc=" (string pc) ")"))
|
||||
(if source
|
||||
(do
|
||||
(file.write stdout " [" source "]")
|
||||
(if source-start (file.write stdout " at byte range ("
|
||||
(string source-start) ":" (string source-end) ")")))
|
||||
(if pc (file.write stdout " at (pc=" (string pc) ")")))
|
||||
(when tail (file.write stdout " (tailcall)"))
|
||||
(file.write stdout "\n"))))
|
||||
|
||||
@ -1033,7 +1042,7 @@ environment is needed, use run-context."
|
||||
(if ret
|
||||
(buffer.push-string buf ret)))
|
||||
(var returnval nil)
|
||||
(run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler)
|
||||
(run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler "eval")
|
||||
returnval)
|
||||
|
||||
(def module.paths @[
|
||||
@ -1097,7 +1106,7 @@ returned from compiling and running the file."
|
||||
(error (string "circular dependency: module " path " is loading")))
|
||||
(def {
|
||||
:exit exit-on-error
|
||||
} args)
|
||||
} (or args {}))
|
||||
(def check (get cache path))
|
||||
(if check check (do
|
||||
(def newenv (make-env))
|
||||
@ -1110,8 +1119,9 @@ returned from compiling and running the file."
|
||||
(defn chunks [buf] (file.read f 1024 buf))
|
||||
(run-context newenv chunks identity
|
||||
(if exit-on-error
|
||||
(fn [a b c] (default-error-handler a b c) (os.exit 1))
|
||||
default-error-handler))
|
||||
(fn [a b c d] (default-error-handler a b c d) (os.exit 1))
|
||||
default-error-handler)
|
||||
path)
|
||||
(file.close f)
|
||||
(put loading path nil)
|
||||
newenv)
|
||||
@ -1161,7 +1171,7 @@ get a chunk of source code. Should return nil for end of file."
|
||||
(put newenv '_ @{:value x})
|
||||
(pp x)))
|
||||
(default onerr default-error-handler)
|
||||
(run-context newenv getchunk onvalue onerr))
|
||||
(run-context newenv getchunk onvalue onerr "repl"))
|
||||
|
||||
(defn all-symbols
|
||||
"Get all symbols available in the current environment."
|
||||
|
@ -32,6 +32,9 @@
|
||||
|
||||
void dstc_ast_push(DstCompiler *c, Dst x) {
|
||||
DstSourceMapping mapping;
|
||||
if (c->result.status == DST_COMPILE_ERROR) {
|
||||
return;
|
||||
}
|
||||
if (c->parser) {
|
||||
int found = dst_parser_lookup(c->parser, x, &mapping);
|
||||
if (!found) {
|
||||
@ -51,6 +54,9 @@ void dstc_ast_push(DstCompiler *c, Dst x) {
|
||||
}
|
||||
|
||||
void dstc_ast_pop(DstCompiler *c) {
|
||||
if (c->result.status == DST_COMPILE_ERROR) {
|
||||
return;
|
||||
}
|
||||
dst_v_pop(c->ast_stack);
|
||||
}
|
||||
|
||||
@ -941,7 +947,7 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) {
|
||||
|
||||
/* Get source from parser */
|
||||
if (c->parser && (c->parser->flags & DST_PARSEFLAG_SOURCEMAP)) {
|
||||
def->source = dst_to_string(c->parser->source);
|
||||
def->source = c->parser->source;
|
||||
}
|
||||
|
||||
def->arity = 0;
|
||||
@ -968,9 +974,9 @@ static void dstc_init(DstCompiler *c, DstTable *env, DstParser *p) {
|
||||
/* Init result */
|
||||
c->result.error = NULL;
|
||||
c->result.status = DST_COMPILE_OK;
|
||||
c->result.funcdef = NULL;
|
||||
c->result.error_start = -1;
|
||||
c->result.error_end = -1;
|
||||
c->result.funcdef = NULL;
|
||||
}
|
||||
|
||||
/* Deinitialize a compiler struct */
|
||||
@ -1004,8 +1010,12 @@ DstCompileResult dst_compile(Dst source, DstTable *env, int flags, DstParser *p)
|
||||
|
||||
if (c.result.status == DST_COMPILE_OK) {
|
||||
DstFuncDef *def = dstc_pop_funcdef(&c);
|
||||
def->name = dst_cstring("[thunk]");
|
||||
def->name = dst_cstring("_thunk");
|
||||
c.result.funcdef = def;
|
||||
} else {
|
||||
DstSourceMapping m = dstc_ast(&c);
|
||||
c.result.error_start = m.start;
|
||||
c.result.error_end = m.end;
|
||||
}
|
||||
|
||||
dstc_deinit(&c);
|
||||
|
@ -31,7 +31,7 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len, const char *so
|
||||
int32_t index = 0;
|
||||
int dudeol = 0;
|
||||
int done = 0;
|
||||
Dst source = sourcePath ? dst_cstringv(sourcePath) : dst_wrap_nil();
|
||||
const uint8_t *source = sourcePath ? dst_cstring(sourcePath) : NULL;
|
||||
|
||||
dst_parser_init(&parser, sourcePath ? DST_PARSEFLAG_SOURCEMAP : 0);
|
||||
parser.source = source;
|
||||
|
160
src/core/parse.c
160
src/core/parse.c
@ -22,119 +22,34 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* custom equals and hash for parse map */
|
||||
static int32_t identity_hash(Dst x) {
|
||||
int32_t hash;
|
||||
if (sizeof(double) == sizeof(void *)) {
|
||||
/* Assuming 8 byte pointer */
|
||||
uint64_t i = dst_u64(x);
|
||||
hash = (int32_t)(i & 0xFFFFFFFF);
|
||||
/* Get a bit more entropy by shifting the low bits out */
|
||||
hash >>= 3;
|
||||
hash ^= (int32_t) (i >> 32);
|
||||
} else {
|
||||
/* Assuming 4 byte pointer (or smaller) */
|
||||
hash = (int32_t) ((char *)dst_unwrap_pointer(x) - (char *)0);
|
||||
hash >>= 2;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
static int identity_equals(Dst lhs, Dst rhs) {
|
||||
DstType lhs_type = dst_type(lhs);
|
||||
DstType rhs_type = dst_type(rhs);
|
||||
if (lhs_type != rhs_type) {
|
||||
return 0;
|
||||
}
|
||||
switch (lhs_type) {
|
||||
default:
|
||||
return 0;
|
||||
case DST_ARRAY:
|
||||
case DST_TUPLE:
|
||||
case DST_BUFFER:
|
||||
case DST_TABLE:
|
||||
case DST_STRUCT:
|
||||
return dst_unwrap_pointer(lhs) == dst_unwrap_pointer(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t pm_hashmapping(int32_t hash, int32_t cap) {
|
||||
return (int32_t)((uint32_t)hash % (uint32_t)cap);
|
||||
}
|
||||
|
||||
/* Find an empty slot in the parse map's hash table for the key */
|
||||
static DstParseKV *pm_findslot(DstParser *p, Dst key) {
|
||||
if (!p->pm_capacity)
|
||||
return NULL;
|
||||
int32_t hash = identity_hash(key);
|
||||
int32_t index = pm_hashmapping(hash, p->pm_capacity);
|
||||
for (int32_t j = index; j < p->pm_capacity; j++) {
|
||||
if (dst_checktype(p->pm_kvs[j].key, DST_NIL)) {
|
||||
return p->pm_kvs + j;
|
||||
}
|
||||
}
|
||||
for (int32_t j = 0; j < index; j++) {
|
||||
if (dst_checktype(p->pm_kvs[j].key, DST_NIL)) {
|
||||
return p->pm_kvs + j;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Rehash a parse map */
|
||||
static void pm_rehash(DstParser *p, int32_t newCapacity) {
|
||||
int32_t oldCapacity = p->pm_capacity;
|
||||
DstParseKV *oldKvs = p->pm_kvs;
|
||||
p->pm_kvs = malloc(sizeof(DstParseKV) * newCapacity);
|
||||
p->pm_capacity = newCapacity;
|
||||
if (!p->pm_kvs) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
for (int32_t i = 0; i < newCapacity; i++) {
|
||||
p->pm_kvs[i].key = dst_wrap_nil();
|
||||
}
|
||||
for (int32_t i = 0; i < oldCapacity; i++) {
|
||||
DstParseKV source_kv = oldKvs[i];
|
||||
if (!dst_checktype(source_kv.key, DST_NIL)) {
|
||||
DstParseKV *dest_kv = pm_findslot(p, source_kv.key);
|
||||
*dest_kv = source_kv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a value to the parsemap */
|
||||
static void pm_put(DstParser *p, Dst key, int32_t start, int32_t end) {
|
||||
/* guard against unsupported key types (noop) */
|
||||
if (!identity_equals(key, key)) return;
|
||||
int32_t newcount = p->pm_count + 1;
|
||||
if (newcount * 2 >= p->pm_capacity) {
|
||||
pm_rehash(p, 4 * newcount);
|
||||
int32_t nextid = p->pm_count;
|
||||
if (!dst_checktype(key, DST_TUPLE))
|
||||
return;
|
||||
dst_tuple_id(dst_unwrap_tuple(key)) = nextid;
|
||||
p->pm_count++;
|
||||
if (nextid >= p->pm_capacity) {
|
||||
int32_t newCapacity = 2 * nextid + 2;
|
||||
DstSourceMapping *newPms = realloc(p->pms, sizeof(DstSourceMapping) * newCapacity);
|
||||
if (!newPms) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
p->pms = newPms;
|
||||
}
|
||||
DstParseKV *dest = pm_findslot(p, key);
|
||||
dest->key = key;
|
||||
dest->start = start;
|
||||
dest->end = end;
|
||||
p->pm_count = newcount;
|
||||
p->pms[nextid].start = start;
|
||||
p->pms[nextid].end = end;
|
||||
}
|
||||
|
||||
/* Get a value from the parse map. The returned pointer
|
||||
* should be read and discarded immediately. */
|
||||
static DstParseKV *pm_get(DstParser *p, Dst ast) {
|
||||
if (!p->pm_capacity)
|
||||
static DstSourceMapping *pm_get(DstParser *p, Dst ast) {
|
||||
if (!dst_checktype(ast, DST_TUPLE))
|
||||
return NULL;
|
||||
int32_t hash = identity_hash(ast);
|
||||
int32_t index = pm_hashmapping(hash, p->pm_capacity);
|
||||
for (int32_t j = index; j < p->pm_capacity; j++) {
|
||||
if (identity_equals(p->pm_kvs[j].key, ast)) {
|
||||
return p->pm_kvs + j;
|
||||
}
|
||||
}
|
||||
for (int32_t j = 0; j < index; j++) {
|
||||
if (identity_equals(p->pm_kvs[j].key, ast)) {
|
||||
return p->pm_kvs + j;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
int32_t id = dst_tuple_id(dst_unwrap_tuple(ast));
|
||||
if (id < 0 || id >= p->pm_count)
|
||||
return NULL;
|
||||
return p->pms + id;
|
||||
}
|
||||
|
||||
/* Quote a value */
|
||||
@ -676,10 +591,9 @@ Dst dst_parser_produce(DstParser *parser) {
|
||||
}
|
||||
|
||||
int dst_parser_lookup(DstParser *parser, Dst key, DstSourceMapping *out) {
|
||||
DstParseKV *results = pm_get(parser, key);
|
||||
DstSourceMapping *results = pm_get(parser, key);
|
||||
if (results) {
|
||||
out->start = results->start;
|
||||
out->end = results->end;
|
||||
*out = *results;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -699,9 +613,9 @@ void dst_parser_init(DstParser *parser, int flags) {
|
||||
parser->index = 0;
|
||||
parser->lookback = -1;
|
||||
parser->flags = flags;
|
||||
parser->source = dst_wrap_nil();
|
||||
parser->source = NULL;
|
||||
|
||||
parser->pm_kvs = NULL;
|
||||
parser->pms = NULL;
|
||||
parser->pm_count = 0;
|
||||
parser->pm_capacity = 0;
|
||||
|
||||
@ -712,7 +626,7 @@ void dst_parser_deinit(DstParser *parser) {
|
||||
free(parser->args);
|
||||
free(parser->buf);
|
||||
free(parser->states);
|
||||
free(parser->pm_kvs);
|
||||
free(parser->pms);
|
||||
}
|
||||
|
||||
/* C functions */
|
||||
@ -721,16 +635,12 @@ static int parsermark(void *p, size_t size) {
|
||||
size_t i;
|
||||
DstParser *parser = (DstParser *)p;
|
||||
(void) size;
|
||||
dst_mark(parser->source);
|
||||
if (parser->source) {
|
||||
dst_mark(dst_wrap_string(parser->source));
|
||||
}
|
||||
for (i = 0; i < parser->argcount; i++) {
|
||||
dst_mark(parser->args[i]);
|
||||
}
|
||||
/* Mark parser map */
|
||||
for (int32_t i = 0; i < parser->pm_capacity; i++) {
|
||||
if (!dst_checktype(parser->pm_kvs[i].key, DST_NIL)) {
|
||||
dst_mark(parser->pm_kvs[i].key);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -897,7 +807,7 @@ static int cfun_lookup(DstArgs args) {
|
||||
DST_FIXARITY(args, 2);
|
||||
DST_CHECKABSTRACT(args, 0, &dst_parse_parsertype);
|
||||
p = (DstParser *) dst_unwrap_abstract(args.v[0]);
|
||||
DstParseKV *results = pm_get(p, args.v[1]);
|
||||
DstSourceMapping *results = pm_get(p, args.v[1]);
|
||||
if (results) {
|
||||
Dst t[2];
|
||||
t[0] = dst_wrap_integer(results->start);
|
||||
@ -907,6 +817,17 @@ static int cfun_lookup(DstArgs args) {
|
||||
DST_RETURN_NIL(args);
|
||||
}
|
||||
|
||||
static int cfun_setsource(DstArgs args) {
|
||||
DstParser *p;
|
||||
const uint8_t *source;
|
||||
DST_FIXARITY(args, 2);
|
||||
DST_CHECKABSTRACT(args, 0, &dst_parse_parsertype);
|
||||
p = (DstParser *) dst_unwrap_abstract(args.v[0]);
|
||||
DST_ARG_STRING(source, args, 1);
|
||||
p->source = source;
|
||||
DST_RETURN(args, args.v[0]);
|
||||
}
|
||||
|
||||
static const DstReg cfuns[] = {
|
||||
{"parser.new", cfun_parser},
|
||||
{"parser.produce", cfun_produce},
|
||||
@ -917,6 +838,7 @@ static const DstReg cfuns[] = {
|
||||
{"parser.flush", cfun_flush},
|
||||
{"parser.state", cfun_state},
|
||||
{"parser.lookup", cfun_lookup},
|
||||
{"parser.set-source", cfun_setsource},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,6 @@ DstKV *dst_struct_begin(int32_t count) {
|
||||
dst_struct_length(st) = count;
|
||||
dst_struct_capacity(st) = capacity;
|
||||
dst_struct_hash(st) = 0;
|
||||
(dst_struct_raw(st)[3]) = 0;
|
||||
return st;
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,10 @@
|
||||
* which should be filled with Dsts. The memory will not be collected until
|
||||
* dst_tuple_end is called. */
|
||||
Dst *dst_tuple_begin(int32_t length) {
|
||||
char *data = dst_gcalloc(DST_MEMORY_TUPLE, 2 * sizeof(int32_t) + length * sizeof(Dst));
|
||||
Dst *tuple = (Dst *)(data + (2 * sizeof(int32_t)));
|
||||
char *data = dst_gcalloc(DST_MEMORY_TUPLE, 4 * sizeof(int32_t) + length * sizeof(Dst));
|
||||
Dst *tuple = (Dst *)(data + (4 * sizeof(int32_t)));
|
||||
dst_tuple_length(tuple) = length;
|
||||
dst_tuple_id(tuple) = -1;
|
||||
return tuple;
|
||||
}
|
||||
|
||||
|
@ -78,9 +78,10 @@ int dst_buffer_push_u32(DstBuffer *buffer, uint32_t x);
|
||||
int dst_buffer_push_u64(DstBuffer *buffer, uint64_t x);
|
||||
|
||||
/* Tuple */
|
||||
#define dst_tuple_raw(t) ((int32_t *)(t) - 2)
|
||||
#define dst_tuple_raw(t) ((int32_t *)(t) - 4)
|
||||
#define dst_tuple_length(t) (dst_tuple_raw(t)[0])
|
||||
#define dst_tuple_hash(t) ((dst_tuple_raw(t)[1]))
|
||||
#define dst_tuple_id(t) ((dst_tuple_raw(t)[2]))
|
||||
Dst *dst_tuple_begin(int32_t length);
|
||||
const Dst *dst_tuple_end(Dst *tuple);
|
||||
const Dst *dst_tuple_n(Dst *values, int32_t n);
|
||||
|
@ -507,13 +507,6 @@ struct DstFunction {
|
||||
DstFuncEnv *envs[];
|
||||
};
|
||||
|
||||
/* Parser types */
|
||||
typedef struct {
|
||||
Dst key;
|
||||
int32_t start;
|
||||
int32_t end;
|
||||
} DstParseKV;
|
||||
|
||||
typedef struct DstParseState DstParseState;
|
||||
typedef struct DstParser DstParser;
|
||||
|
||||
@ -530,10 +523,10 @@ struct DstParser {
|
||||
const char *error;
|
||||
DstParseState *states;
|
||||
uint8_t *buf;
|
||||
DstParseKV *pm_kvs;
|
||||
const uint8_t *source; /* optional source path/string */
|
||||
DstSourceMapping *pms;
|
||||
int32_t pm_capacity;
|
||||
int32_t pm_count;
|
||||
Dst source; /* optional source path/string */
|
||||
size_t argcount;
|
||||
size_t argcap;
|
||||
size_t statecount;
|
||||
|
Loading…
Reference in New Issue
Block a user