1 /* 2 * Copyright (c) 2021 Calvin Rose 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to 6 * deal in the Software without restriction, including without limitation the 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 * sell copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 * IN THE SOFTWARE. 21 */ 22 23 #ifndef JANET_COMPILE_H 24 #define JANET_COMPILE_H 25 26 #ifndef JANET_AMALG 27 #include "features.h" 28 #include <janet.h> 29 #include "regalloc.h" 30 #endif 31 32 /* Levels for compiler warnings */ 33 typedef enum { 34 JANET_C_LINT_RELAXED, 35 JANET_C_LINT_NORMAL, 36 JANET_C_LINT_STRICT 37 } JanetCompileLintLevel; 38 39 /* Tags for some functions for the prepared inliner */ 40 #define JANET_FUN_DEBUG 1 41 #define JANET_FUN_ERROR 2 42 #define JANET_FUN_APPLY 3 43 #define JANET_FUN_YIELD 4 44 #define JANET_FUN_RESUME 5 45 #define JANET_FUN_IN 6 46 #define JANET_FUN_PUT 7 47 #define JANET_FUN_LENGTH 8 48 #define JANET_FUN_ADD 9 49 #define JANET_FUN_SUBTRACT 10 50 #define JANET_FUN_MULTIPLY 11 51 #define JANET_FUN_DIVIDE 12 52 #define JANET_FUN_BAND 13 53 #define JANET_FUN_BOR 14 54 #define JANET_FUN_BXOR 15 55 #define JANET_FUN_LSHIFT 16 56 #define JANET_FUN_RSHIFT 17 57 #define JANET_FUN_RSHIFTU 18 58 #define JANET_FUN_BNOT 19 59 #define JANET_FUN_GT 20 60 #define JANET_FUN_LT 21 61 #define JANET_FUN_GTE 22 62 #define JANET_FUN_LTE 23 63 #define JANET_FUN_EQ 24 64 #define JANET_FUN_NEQ 25 65 #define JANET_FUN_PROP 26 66 #define JANET_FUN_GET 27 67 #define JANET_FUN_NEXT 28 68 #define JANET_FUN_MODULO 29 69 #define JANET_FUN_REMAINDER 30 70 #define JANET_FUN_CMP 31 71 #define JANET_FUN_CANCEL 32 72 73 /* Compiler typedefs */ 74 typedef struct JanetCompiler JanetCompiler; 75 typedef struct FormOptions FormOptions; 76 typedef struct SlotTracker SlotTracker; 77 typedef struct JanetScope JanetScope; 78 typedef struct JanetSlot JanetSlot; 79 typedef struct JanetFopts JanetFopts; 80 typedef struct JanetFunOptimizer JanetFunOptimizer; 81 typedef struct JanetSpecial JanetSpecial; 82 83 #define JANET_SLOT_CONSTANT 0x10000 84 #define JANET_SLOT_NAMED 0x20000 85 #define JANET_SLOT_MUTABLE 0x40000 86 #define JANET_SLOT_REF 0x80000 87 #define JANET_SLOT_RETURNED 0x100000 88 #define JANET_SLOT_DEP_NOTE 0x200000 89 #define JANET_SLOT_DEP_WARN 0x400000 90 #define JANET_SLOT_DEP_ERROR 0x800000 91 #define JANET_SLOT_SPLICED 0x1000000 92 93 #define JANET_SLOTTYPE_ANY 0xFFFF 94 95 /* A stack slot */ 96 struct JanetSlot { 97 Janet constant; /* If the slot has a constant value */ 98 int32_t index; 99 int32_t envindex; /* 0 is local, positive number is an upvalue */ 100 uint32_t flags; 101 }; 102 103 #define JANET_SCOPE_FUNCTION 1 104 #define JANET_SCOPE_ENV 2 105 #define JANET_SCOPE_TOP 4 106 #define JANET_SCOPE_UNUSED 8 107 #define JANET_SCOPE_CLOSURE 16 108 #define JANET_SCOPE_WHILE 32 109 110 /* A symbol and slot pair */ 111 typedef struct SymPair { 112 JanetSlot slot; 113 const uint8_t *sym; 114 int keep; 115 } SymPair; 116 117 /* A lexical scope during compilation */ 118 struct JanetScope { 119 120 /* For debugging */ 121 const char *name; 122 123 /* Scopes are doubly linked list */ 124 JanetScope *parent; 125 JanetScope *child; 126 127 /* Constants for this funcdef */ 128 Janet *consts; 129 130 /* Map of symbols to slots. Use a simple linear scan for symbols. */ 131 SymPair *syms; 132 133 /* FuncDefs */ 134 JanetFuncDef **defs; 135 136 /* Regsiter allocator */ 137 JanetcRegisterAllocator ra; 138 139 /* Upvalue allocator */ 140 JanetcRegisterAllocator ua; 141 142 /* Referenced closure environments. The values at each index correspond 143 * to which index to get the environment from in the parent. The environment 144 * that corresponds to the direct parent's stack will always have value 0. */ 145 int32_t *envs; 146 147 int32_t bytecode_start; 148 int flags; 149 }; 150 151 /* Compilation state */ 152 struct JanetCompiler { 153 154 /* Pointer to current scope */ 155 JanetScope *scope; 156 157 uint32_t *buffer; 158 JanetSourceMapping *mapbuffer; 159 160 /* Hold the environment */ 161 JanetTable *env; 162 163 /* Name of source to attach to generated functions */ 164 const uint8_t *source; 165 166 /* The result of compilation */ 167 JanetCompileResult result; 168 169 /* Keep track of where we are in the source */ 170 JanetSourceMapping current_mapping; 171 172 /* Prevent unbounded recursion */ 173 int recursion_guard; 174 175 /* Collect linting results */ 176 JanetArray *lints; 177 }; 178 179 #define JANET_FOPTS_TAIL 0x10000 180 #define JANET_FOPTS_HINT 0x20000 181 #define JANET_FOPTS_DROP 0x40000 182 183 /* Options for compiling a single form */ 184 struct JanetFopts { 185 JanetCompiler *compiler; 186 JanetSlot hint; 187 uint32_t flags; /* bit set of accepted primitive types */ 188 }; 189 190 /* Get the default form options */ 191 JanetFopts janetc_fopts_default(JanetCompiler *c); 192 193 /* For optimizing builtin normal functions. */ 194 struct JanetFunOptimizer { 195 int (*can_optimize)(JanetFopts opts, JanetSlot *args); 196 JanetSlot(*optimize)(JanetFopts opts, JanetSlot *args); 197 }; 198 199 /* A grouping of a named special and the corresponding compiler fragment */ 200 struct JanetSpecial { 201 const char *name; 202 JanetSlot(*compile)(JanetFopts opts, int32_t argn, const Janet *argv); 203 }; 204 205 /****************************************************/ 206 207 /* Get an optimizer if it exists, otherwise NULL */ 208 const JanetFunOptimizer *janetc_funopt(uint32_t flags); 209 210 /* Get a special. Return NULL if none exists */ 211 const JanetSpecial *janetc_special(const uint8_t *name); 212 213 void janetc_freeslot(JanetCompiler *c, JanetSlot s); 214 void janetc_nameslot(JanetCompiler *c, const uint8_t *sym, JanetSlot s); 215 JanetSlot janetc_farslot(JanetCompiler *c); 216 217 /* Throw away some code after checking that it is well formed. */ 218 void janetc_throwaway(JanetFopts opts, Janet x); 219 220 /* Get a target slot for emitting an instruction. Will always return 221 * a local slot. */ 222 JanetSlot janetc_gettarget(JanetFopts opts); 223 224 /* Get a bunch of slots for function arguments */ 225 JanetSlot *janetc_toslots(JanetCompiler *c, const Janet *vals, int32_t len); 226 227 /* Get a bunch of slots for function arguments */ 228 JanetSlot *janetc_toslotskv(JanetCompiler *c, Janet ds); 229 230 /* Push slots load via janetc_toslots. */ 231 int32_t janetc_pushslots(JanetCompiler *c, JanetSlot *slots); 232 233 /* Free slots loaded via janetc_toslots */ 234 void janetc_freeslots(JanetCompiler *c, JanetSlot *slots); 235 236 /* Generate the return instruction for a slot. */ 237 JanetSlot janetc_return(JanetCompiler *c, JanetSlot s); 238 239 /* Store an error */ 240 void janetc_error(JanetCompiler *c, const uint8_t *m); 241 void janetc_cerror(JanetCompiler *c, const char *m); 242 243 /* Linting */ 244 void janetc_lintf(JanetCompiler *C, JanetCompileLintLevel level, const char *format, ...); 245 246 /* Dispatch to correct form compiler */ 247 JanetSlot janetc_value(JanetFopts opts, Janet x); 248 249 /* Push and pop from the scope stack */ 250 void janetc_scope(JanetScope *s, JanetCompiler *c, int flags, const char *name); 251 void janetc_popscope(JanetCompiler *c); 252 void janetc_popscope_keepslot(JanetCompiler *c, JanetSlot retslot); 253 JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c); 254 255 /* Create a destory slots */ 256 JanetSlot janetc_cslot(Janet x); 257 258 /* Search for a symbol */ 259 JanetSlot janetc_resolve(JanetCompiler *c, const uint8_t *sym); 260 261 #endif 262