/* * Copyright (c) 2017 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_COMPILE_H #define DST_COMPILE_H #include #include #include "opcodes.h" /* Compiler typedefs */ typedef struct DstCompiler DstCompiler; typedef struct FormOptions FormOptions; typedef struct SlotTracker SlotTracker; typedef struct DstScope DstScope; typedef struct DstSlot DstSlot; typedef struct DstFormOptions DstFormOptions; typedef struct DstCFunctionOptimizer DstCFunctionOptimizer; #define DST_SLOT_CONSTANT 0x10000 #define DST_SLOT_NAMED 0x20000 #define DST_SLOT_RETURNED 0x40000 #define DST_SLOT_NIL 0x80000 #define DST_SLOT_MUTABLE 0x100000 #define DST_SLOT_NOTEMPTY 0x200000 #define DST_SLOTTYPE_ANY 0xFFFF /* A stack slot */ struct DstSlot { int32_t index; int32_t envindex; /* 0 is local, positive number is an upvalue */ uint32_t flags; DstValue constant; /* If the slot has a constant value */ }; /* Most forms that return a constant will not generate any bytecode */ /* Special forms that need support */ /* cond * while (continue, break) * quote * fn * def * var * varset * do */ #define DST_SCOPE_FUNCTION 1 #define DST_SCOPE_LASTSLOT 2 #define DST_SCOPE_FIRSTSLOT 4 #define DST_SCOPE_ENV 8 /* Hold a bunch of slots together */ typedef struct DstSlotPool DstSlotPool; struct DstSlotPool { DstSlot *s; int32_t count; int32_t cap; int32_t free; }; /* A lexical scope during compilation */ struct DstScope { int32_t level; DstArray constants; /* Constants for the funcdef */ DstTable constantrev; /* Map constants -> constant inidices */ DstTable symbols; /* Map symbols -> Slot pointers */ /* Hold all slots in use. Data structures that store * slots should link them to this datatstructure */ DstSlotPool slots; DstSlotPool unorderedslots; /* Referenced closure environents. The values at each index correspond * to which index to get the environment from in the parent. The enironment * that corresponds to the direct parent's stack will always have value 0. */ int32_t *envs; int32_t envcount; int32_t envcap; int32_t bytecode_start; uint32_t flags; }; #define dst_compile_topscope(c) ((c)->scopes + (c)->scopecount - 1) /* Compilation state */ struct DstCompiler { jmp_buf on_error; int recursion_guard; int32_t scopecount; int32_t scopecap; DstScope *scopes; int32_t buffercap; int32_t buffercount; uint32_t *buffer; int32_t (*mapbuffer)[2]; DstCompileResults results; }; #define DST_FOPTS_TAIL 0x10000 #define DST_FOPTS_FORCESLOT 0x20000 /* Compiler state */ struct DstFormOptions { DstCompiler *compiler; DstValue x; const DstValue *sourcemap; uint32_t flags; /* bit set of accepted primitive types */ }; /* A grouping of optimizations on a cfunction given certain conditions * on the arguments (such as all constants, or some known types). The appropriate * optimizations should be tried before compiling a normal function call. */ struct DstCFunctionOptimizer { DstCFunction cfun; DstSlot (*optimize)(DstFormOptions opts, int32_t argn, const DstValue *argv); }; typedef struct DstSpecial { const char *name; DstSlot (*compile)(DstFormOptions opts, int32_t argn, const DstValue *argv); } DstSpecial; /* An array of optimizers sorted by key */ extern DstCFunctionOptimizer dst_compiler_optimizers[255]; /* An array of special forms */ extern DstSpecial dst_compiler_specials[16]; void dst_compile_slotpool_init(DstSlotPool *pool); void dst_compile_slotpool_deinit(DstSlotPool *pool); DstSlot *dst_compile_slotpool_alloc(DstSlotPool *pool); void dst_compile_slotpool_extend(DstSlotPool *pool, int32_t extra); void dst_compile_slotpool_free(DstSlotPool *pool, DstSlot *s); void dst_compile_slotpool_freeindex(DstSlotPool *pool, int32_t index); /* Dispatch to correct form compiler */ DstSlot *dst_compile_value(DstFormOptions opts); /* Compile special forms */ DstSlot *dst_compile_do(DstFormOptions opts, int32_t argn, const DstValue *argv); DstSlot *dst_compile_fn(DstFormOptions opts, int32_t argn, const DstValue *argv); DstSlot *dst_compile_cond(DstFormOptions opts, int32_t argn, const DstValue *argv); DstSlot *dst_compile_while(DstFormOptions opts, int32_t argn, const DstValue *argv); DstSlot *dst_compile_quote(DstFormOptions opts, int32_t argn, const DstValue *argv); DstSlot *dst_compile_def(DstFormOptions opts, int32_t argn, const DstValue *argv); DstSlot *dst_compile_var(DstFormOptions opts, int32_t argn, const DstValue *argv); DstSlot *dst_compile_varset(DstFormOptions opts, int32_t argn, const DstValue *argv); /****************************************************/ void dst_compile_error(DstCompiler *c, const DstValue *sourcemap, const uint8_t *m); void dst_compile_cerror(DstCompiler *c, const DstValue *sourcemap, const char *m); /* Use these to get sub options. They will traverse the source map so * compiler errors make sense. Then modify the returned options. */ DstFormOptions dst_compile_getopts_index(DstFormOptions opts, int32_t index); DstFormOptions dst_compile_getopts_key(DstFormOptions opts, DstValue key); DstFormOptions dst_compile_getopts_value(DstFormOptions opts, DstValue key); void dst_compile_scope(DstCompiler *c, int newfn); void dst_compile_popscope(DstCompiler *c); DstSlot *dst_compile_constantslot(DstCompiler *c, DstValue x); void dst_compile_freeslot(DstCompiler *c, DstSlot *slot); /* Search for a symbol */ DstSlot *dst_compile_resolve(DstCompiler *c, const DstValue *sourcemap, const uint8_t *sym); /* Emit instructions. */ void dst_compile_emit(DstCompiler *c, const DstValue *sourcemap, uint32_t instr); #endif