libscript.h (6173B)
1 #ifndef LIBSCRIPT_H 2 #define LIBSCRIPT_H 3 4 #include <assert.h> 5 #include <errno.h> 6 #include <stdalign.h> 7 #include <stdarg.h> 8 #include <stddef.h> 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 /* utilities 15 * =========================================================================== 16 */ 17 18 #define SCRIPT_TO_PARENT(child_ptr, T, member) \ 19 ((child_ptr) ? (T *) ((uintptr_t) child_ptr - offsetof(T, member)) : NULL) 20 21 struct script_flystr { 22 uint64_t v; 23 }; 24 25 struct script_list_node { 26 struct script_list_node *prev, *next; 27 }; 28 29 #define SCRIPT_FROM_NODE(node, T, member) SCRIPT_TO_PARENT(node, T, member) 30 31 #define SCRIPT_NODE_ITER(node) \ 32 for (struct script_list_node *it = (node); it; it = it->next) 33 34 #define SCRIPT_NODE_RITER(node) \ 35 for (struct script_list_node *it = (node); it; it = it->prev) 36 37 struct script_list { 38 struct script_list_node *head, *tail; 39 }; 40 41 #define SCRIPT_LIST_ITER(list) SCRIPT_NODE_ITER((list)->head) 42 #define SCRIPT_LIST_RITER(list) SCRIPT_NODE_RITER((list)->tail) 43 44 /* lexer 45 * =========================================================================== 46 */ 47 48 enum script_token_type { 49 SCR_TOKEN_EOF, 50 51 /* punctuation */ 52 SCR_TOKEN_LPAREN = '(', 53 SCR_TOKEN_RPAREN = ')', 54 SCR_TOKEN_LBRACK = '[', 55 SCR_TOKEN_RBRACK = ']', 56 SCR_TOKEN_LBRACE = '{', 57 SCR_TOKEN_RBRACE = '}', 58 59 SCR_TOKEN_LANGLE = '<', 60 SCR_TOKEN_RANGLE = '>', 61 SCR_TOKEN_LSLASH = '\\', 62 SCR_TOKEN_RSLASH = '/', 63 64 SCR_TOKEN_COLON = ':', 65 SCR_TOKEN_SEMICOLON = ';', 66 SCR_TOKEN_DOT = '.', 67 SCR_TOKEN_COMMA = ',', 68 69 SCR_TOKEN_EQUALS = '=', 70 SCR_TOKEN_PLUS = '+', 71 SCR_TOKEN_MINUS = '-', 72 SCR_TOKEN_STAR = '*', 73 74 _SCR_TOKEN_MULTICHAR = 128, /* helper to bump enum values ouside of ascii range */ 75 76 /* multi-char punctuation */ 77 SCR_TOKEN_DOUBLE_COLON, 78 SCR_TOKEN_DOUBLE_EQUALS, 79 80 /* literals */ 81 SCR_TOKEN_IDENT, 82 SCR_TOKEN_LITERAL_INT, 83 84 /* keywords */ 85 SCR_TOKEN_U8, 86 SCR_TOKEN_U16, 87 SCR_TOKEN_U32, 88 SCR_TOKEN_U64, 89 90 SCR_TOKEN_S8, 91 SCR_TOKEN_S16, 92 SCR_TOKEN_S32, 93 SCR_TOKEN_S64, 94 95 SCR_TOKEN_F32, 96 SCR_TOKEN_F64, 97 98 SCR_TOKEN_C8, 99 100 SCR_TOKEN_RETURN, 101 102 SCR_TOKEN_IF, 103 SCR_TOKEN_ELSE, 104 SCR_TOKEN_WHILE, 105 }; 106 107 extern char const * 108 script_token_type_str(enum script_token_type type); 109 110 struct script_token { 111 enum script_token_type type; 112 113 union { 114 struct script_flystr ident; 115 uint64_t literal_int; 116 }; 117 }; 118 119 /* parser 120 * =========================================================================== 121 */ 122 123 enum script_type { 124 SCR_TYPE_U8, 125 SCR_TYPE_U16, 126 SCR_TYPE_U32, 127 SCR_TYPE_U64, 128 129 SCR_TYPE_S8, 130 SCR_TYPE_S16, 131 SCR_TYPE_S32, 132 SCR_TYPE_S64, 133 134 SCR_TYPE_F32, 135 SCR_TYPE_F64, 136 137 SCR_TYPE_C8, 138 }; 139 140 struct script_typeinfo { 141 enum script_type type; 142 143 size_t size; 144 size_t alignment; 145 }; 146 147 enum script_expr_type { 148 SCR_EXPR_IDENT, 149 SCR_EXPR_LITERAL_INT, 150 SCR_EXPR_ASSIGNMENT, 151 SCR_EXPR_BINARY_OP, 152 }; 153 154 struct script_expr { 155 enum script_expr_type type; 156 157 struct script_typeinfo *typeinfo; 158 159 union { 160 struct script_flystr ident; 161 162 uint64_t literal_int; 163 164 struct { 165 struct script_flystr ident; 166 struct script_expr *rhs; 167 } assignment; 168 169 struct { 170 enum { 171 SCR_BINARY_OP_ADD, 172 SCR_BINARY_OP_SUB, 173 SCR_BINARY_OP_MUL, 174 SCR_BINARY_OP_DIV, 175 SCR_BINARY_OP_EQU, 176 } type; 177 178 struct script_expr *lhs, *rhs; 179 } binary_op; 180 }; 181 }; 182 183 enum script_stmt_type { 184 SCR_STMT_BLOCK, 185 SCR_STMT_DECL, 186 SCR_STMT_EXPR, 187 SCR_STMT_IF_ELSE, 188 SCR_STMT_WHILE_LOOP, 189 SCR_STMT_RET, 190 }; 191 192 struct script_stmt { 193 enum script_stmt_type type; 194 195 union { 196 struct { 197 struct script_list children; 198 } block; 199 200 struct { 201 struct script_flystr ident; 202 struct script_typeinfo *typeinfo; 203 struct script_expr *expr; 204 } decl; 205 206 struct script_expr *expr; 207 208 struct { 209 struct script_expr *cond; 210 struct script_stmt *if_body, *else_body; 211 } if_else; 212 213 struct { 214 struct script_expr *cond; 215 struct script_stmt *while_body; 216 } while_loop; 217 218 struct { 219 struct script_expr *expr; 220 } ret; 221 }; 222 223 struct script_list_node list_node; 224 }; 225 226 enum script_symbol_type { 227 SCR_SYMBOL_VARIABLE, 228 }; 229 230 struct script_symbol { 231 enum script_symbol_type type; 232 233 struct script_flystr ident; 234 struct script_symbol *parent_scope; 235 236 union { 237 struct { 238 struct script_typeinfo *typeinfo; 239 uintptr_t addr; 240 } variable; 241 }; 242 243 struct script_list_node list_node; 244 }; 245 246 /* ir 247 * =========================================================================== 248 */ 249 250 enum script_ir_opcode { 251 SCR_IR_LOAD, 252 SCR_IR_STORE, 253 254 SCR_IR_PUSH, 255 SCR_IR_POP, 256 SCR_IR_RET, 257 258 SCR_IR_CMP, 259 SCR_IR_JMP, 260 SCR_IR_JNE, 261 SCR_IR_JEQ, 262 263 SCR_IR_ADD, 264 SCR_IR_SUB, 265 SCR_IR_MUL, 266 SCR_IR_DIV, 267 }; 268 269 extern char const * 270 script_ir_opcode_str(enum script_ir_opcode opcode); 271 272 enum script_ir_type { 273 SCR_IR_TYPE_U8, 274 SCR_IR_TYPE_U16, 275 SCR_IR_TYPE_U32, 276 SCR_IR_TYPE_U64, 277 278 SCR_IR_TYPE_S8, 279 SCR_IR_TYPE_S16, 280 SCR_IR_TYPE_S32, 281 SCR_IR_TYPE_S64, 282 283 SCR_IR_TYPE_F32, 284 SCR_IR_TYPE_F64, 285 286 SCR_IR_TYPE_C8, 287 288 SCR_IR_TYPE_PTR, 289 }; 290 291 extern char const * 292 script_ir_type_str(enum script_ir_type type); 293 294 struct script_ir_typeinfo { 295 enum script_ir_type type; 296 size_t size, alignment; 297 }; 298 299 enum script_ir_operand_type { 300 SCR_IR_OPERAND_LITERAL, 301 SCR_IR_OPERAND_ADDRESS, 302 SCR_IR_OPERAND_OFFSET, 303 }; 304 305 struct script_ir_operand { 306 enum script_ir_operand_type type; 307 union { 308 uint64_t literal; 309 uintptr_t address; 310 int64_t offset; 311 }; 312 }; 313 314 #define SCRIPT_IR_INST_MAX_OPERANDS 1 315 316 struct script_ir_inst { 317 enum script_ir_opcode opcode; 318 struct script_ir_typeinfo *typeinfo; 319 struct script_ir_operand operands[SCRIPT_IR_INST_MAX_OPERANDS]; 320 size_t operand_count; 321 }; 322 323 /* libscript 324 * =========================================================================== 325 */ 326 327 #define SCRIPT_COMPILE_SCRATCH_BYTES 1024 328 329 #define SCRIPT_COMPILE_MAX_IDENTS 4096 330 331 #define SCRIPT_COMPILE_MAX_TOKS 8192 332 #define SCRIPT_COMPILE_MAX_SYMS 2048 333 334 #define SCRIPT_COMPILE_MAX_STMTS 4096 335 #define SCRIPT_COMPILE_MAX_EXPRS 4096 336 337 #define SCRIPT_COMPILE_MAX_EXPR_DEPTH 16 338 339 #define SCRIPT_COMPILE_MAX_IR_INSTRS 4096 340 341 struct script_program { 342 struct { 343 struct script_ir_inst *ptr; 344 size_t len; 345 } instructions; 346 347 size_t max_heap_bytes; 348 }; 349 350 extern int 351 script_compile(char *src, size_t src_len, void *mem, size_t mem_len, 352 struct script_program *out, FILE *errstream, int verbose); 353 354 #endif /* LIBSCRIPT_H */