rpn_lang.c (4084B)
1 #include <kit/frontend.h> 2 3 #include <stddef.h> 4 #include <stdint.h> 5 6 typedef struct RpnFrontend { 7 KitCompiler* c; 8 } RpnFrontend; 9 10 static KitFrontendState* rpn_new(KitCompiler* c) { 11 KitHeap* h = kit_compiler_context(c)->heap; 12 RpnFrontend* fe = (RpnFrontend*)h->alloc(h, sizeof(*fe), _Alignof(RpnFrontend)); 13 if (!fe) return NULL; 14 fe->c = c; 15 return (KitFrontendState*)fe; 16 } 17 18 static void rpn_free(KitFrontendState* st) { 19 RpnFrontend* fe = (RpnFrontend*)st; 20 KitHeap* h; 21 if (!fe) return; 22 h = kit_compiler_context(fe->c)->heap; 23 h->free(h, fe, sizeof(*fe)); 24 } 25 26 static void rpn_skip_ws(const char** p, const char* end) { 27 while (*p < end && (**p == ' ' || **p == '\t' || **p == '\r' || **p == '\n')) 28 ++(*p); 29 } 30 31 static int rpn_read_int(const char** p, const char* end, int64_t* out) { 32 int neg = 0; 33 int any = 0; 34 int64_t v = 0; 35 if (*p < end && **p == '-') { 36 neg = 1; 37 ++(*p); 38 } 39 while (*p < end && **p >= '0' && **p <= '9') { 40 any = 1; 41 v = v * 10 + (int64_t)(**p - '0'); 42 ++(*p); 43 } 44 if (!any) return 0; 45 *out = neg ? -v : v; 46 return 1; 47 } 48 49 static KitStatus rpn_compile_cg(KitFrontendState* st, 50 const KitFrontendCompileOptions* opts, 51 const KitSourceInput* input, KitCg* cg) { 52 RpnFrontend* fe = (RpnFrontend*)st; 53 const char* p = input->bytes.s; 54 const char* end = p + input->bytes.len; 55 KitCgTypeId i32_ty = kit_cg_type_builtin(fe->c, KIT_CG_BUILTIN_I32); 56 KitCgTypeId func_ty; 57 KitCgFuncResult result; 58 KitCgFuncSig sig; 59 KitCgDecl decl; 60 KitCgSym main_sym; 61 int depth = 0; 62 (void)opts; 63 64 result.type = i32_ty; 65 result.attrs.flags = 0; 66 result.attrs.align = 0; 67 result.attrs.dereferenceable_size = 0; 68 sig.result = result; 69 sig.params = NULL; 70 sig.nparams = 0; 71 sig.call_conv = KIT_CG_CC_TARGET_C; 72 sig.abi_variadic = false; 73 func_ty = kit_cg_type_func(fe->c, sig); 74 75 decl = (KitCgDecl){0}; 76 decl.kind = KIT_CG_DECL_FUNC; 77 decl.linkage_name = 78 kit_cg_c_linkage_name(fe->c, kit_sym_intern(fe->c, KIT_SLICE_LIT("main"))); 79 decl.display_name = kit_sym_intern(fe->c, KIT_SLICE_LIT("main")); 80 decl.type = func_ty; 81 decl.sym.bind = KIT_SB_GLOBAL; 82 decl.sym.visibility = KIT_CG_VIS_DEFAULT; 83 decl.sym.flags = 0; 84 decl.as.func.flags = 0; 85 decl.as.func.inline_policy = KIT_CG_INLINE_DEFAULT; 86 87 main_sym = kit_cg_decl(cg, decl); 88 if (main_sym == KIT_CG_SYM_NONE) return KIT_ERR; 89 kit_cg_func_begin(cg, main_sym); 90 while (p < end) { 91 int64_t v; 92 rpn_skip_ws(&p, end); 93 if (p >= end) break; 94 if ((*p >= '0' && *p <= '9') || 95 (*p == '-' && p + 1 < end && p[1] >= '0' && p[1] <= '9')) { 96 if (!rpn_read_int(&p, end, &v)) return KIT_MALFORMED; 97 kit_cg_push_int(cg, (uint64_t)(int32_t)v, i32_ty); 98 ++depth; 99 continue; 100 } 101 if (*p == '+' || *p == '-' || *p == '*') { 102 char op = *p++; 103 if (depth < 2) return KIT_MALFORMED; 104 if (op == '+') 105 kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0); 106 else if (op == '-') 107 kit_cg_int_binop(cg, KIT_CG_INT_SUB, 0); 108 else 109 kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0); 110 --depth; 111 continue; 112 } 113 return KIT_MALFORMED; 114 } 115 if (depth != 1) return KIT_MALFORMED; 116 kit_cg_ret(cg); 117 kit_cg_func_end(cg); 118 return KIT_OK; 119 } 120 121 static const KitSlice rpn_exts[] = {KIT_SLICE_LIT("rpn")}; 122 static const KitSlice rpn_names[] = {KIT_SLICE_LIT("rpn")}; 123 124 const KitFrontendVTable kit_rpn_frontend_vtable = { 125 .new_frontend = rpn_new, 126 .compile_cg = rpn_compile_cg, 127 .compile_obj = NULL, 128 .free_frontend = rpn_free, 129 .extensions = rpn_exts, 130 .nextensions = (uint32_t)(sizeof rpn_exts / sizeof rpn_exts[0]), 131 .extension_kinds = NULL, 132 .names = rpn_names, 133 .nnames = (uint32_t)(sizeof rpn_names / sizeof rpn_names[0]), 134 .commit = NULL, 135 .abort = NULL, 136 .caps = {false, KIT_FRONTEND_LTO_CG, false}, 137 .parse_options = NULL, 138 .free_options = NULL, 139 }; 140 141 KitStatus kit_rpn_register_frontends(KitFrontendRegistry* registry) { 142 return kit_frontend_registry_add(registry, &kit_rpn_frontend_vtable, NULL); 143 }