1/* 2Copyright (C) 2011-2014, Parrot Foundation. 3 4=head1 NAME 5 6src/pmc/imccompiler.pmc - IMCCompiler PMC 7 8=head1 DESCRIPTION 9 10A compiler object to wrap IMCC, the internal PIR and PASM compiler. 11 12=head2 Functions 13 14=cut 15 16*/ 17 18#include "imcc/embed.h" 19#include "imcc/yyscanner.h" 20#include "pmc/pmc_sub.h" 21 22/* HEADERIZER BEGIN: static */ 23/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 24 25/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 26/* HEADERIZER END: static */ 27 28#define BEGIN_IMCC_COMPILE(i) \ 29 do { \ 30 UINTVAL __regs_used[4] = {3, 3, 3, 3}; \ 31 PMC * const __newcontext = Parrot_push_context((i), __regs_used); \ 32 PackFile_ByteCode * const __old_bc = (i)->code; \ 33 Parrot_block_GC_mark((i)); \ 34 Parrot_pcc_set_HLL((i), __newcontext, 0); \ 35 Parrot_pcc_set_sub((i), __newcontext, 0); \ 36 37#define END_IMCC_COMPILE(i) \ 38 Parrot_pop_context((i)); \ 39 Parrot_unblock_GC_mark((i)); \ 40 (i)->code = __old_bc; \ 41 } while (0) 42 43#define ERROR_IMCC_COMPILE(i) \ 44 Parrot_pop_context((i)); \ 45 Parrot_unblock_GC_mark((i)); \ 46 (i)->code = __old_bc; \ 47 48/* HEADERIZER HFILE: none */ 49 50pmclass IMCCompiler auto_attrs provides HLLCompiler provide invokable { 51 ATTR void *imcc_info; 52 ATTR INTVAL is_pasm; /* 0 = PIR, 1 = PASM */ 53 ATTR INTVAL current_eval; 54 55 VTABLE void init() :no_wb { 56 UNUSED(SELF) 57 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION, 58 "IMCCompiler: Must initialize with an integer argument 0 (PIR) or 1 (PASM)"); 59 } 60 61 VTABLE void init_pmc(PMC *init) :manual_wb { 62 const INTVAL type = VTABLE_get_integer(INTERP, init); 63 VTABLE_init_int(INTERP, SELF, type); 64 } 65 66 VTABLE void init_int(INTVAL is_pasm) { 67 Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 68 if (is_pasm != 0 && is_pasm != 1) 69 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION, 70 "IMCCompiler: Must have type 0 (PIR) or 1 (PASM)"); 71 attrs->is_pasm = is_pasm; 72 attrs->imcc_info = (void*) imcc_new(INTERP); 73 attrs->current_eval = 0; 74 } 75 76 /* provided to emulate the current NCI compreg */ 77 /* DEPRECATED. See TT #1967 */ 78 VTABLE opcode_t* invoke(void* next) :no_wb { 79 Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 80 imc_info_t * const imcc = (imc_info_t*) attrs->imcc_info; 81 PMC * const ctx = CURRENT_CONTEXT(INTERP); 82 PMC * cont = INTERP->current_cont; 83 PMC * const call_object = Parrot_pcc_get_signature(interp, ctx); 84 PackFile_ByteCode * const cur_code = interp->code; 85 STRING * code = STRINGNULL; 86 PMC * result = PMCNULL; 87 const UINTVAL regs_used[4] = {3, 3, 3, 3}; 88 PMC * const newcontext = Parrot_push_context(interp, regs_used); 89 90 Parrot_block_GC_mark(interp); 91 Parrot_pcc_set_sub(interp, newcontext, 0); 92 93 Parrot_pcc_fill_params_from_c_args(INTERP, call_object, "S", &code); 94 imcc_reset(imcc); 95 result = imcc_compile_string(imcc, code, attrs->is_pasm); 96 if (PMC_IS_NULL(result)) { 97 STRING * const msg = imcc_last_error_message(imcc); 98 const INTVAL errcode = imcc_last_error_code(imcc); 99 Parrot_unblock_GC_mark(interp); 100 Parrot_ex_throw_from_c_args(INTERP, NULL, errcode, "%Ss", msg); 101 } 102 103 Parrot_pop_context(interp); 104 Parrot_unblock_GC_mark(interp); 105 106 /* Handle the case where we we've been tailcalled into. See NCI.invoke 107 for more details */ 108 if (!PMC_IS_NULL(cont) 109 && (PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) { 110 cont = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp)); 111 next = VTABLE_invoke(INTERP, cont, next); 112 } 113 114 Parrot_pcc_set_call_from_c_args(INTERP, call_object, "P", result); 115 interp->code = cur_code; 116 return (opcode_t*)next; 117 } 118 119 VTABLE void *get_pointer() :no_wb { 120 const Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 121 UNUSED(INTERP) 122 return attrs->imcc_info; 123 } 124 125 VTABLE INTVAL get_integer() :no_wb { 126 const Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 127 UNUSED(INTERP) 128 return attrs->is_pasm; 129 } 130 131 VTABLE STRING *get_string() :no_wb { 132 const Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 133 if (attrs->is_pasm) 134 return CONST_STRING(INTERP, "PASM"); 135 else 136 return CONST_STRING(INTERP, "PIR"); 137 } 138 139 VTABLE void destroy() :no_wb { 140 Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 141 UNUSED(INTERP) 142 imcc_destroy((imc_info_t*)(attrs->imcc_info)); 143 attrs->imcc_info = NULL; 144 } 145 146 METHOD compile(STRING *source, 147 STRING *path :optional, INTVAL has_path :opt_flag, 148 STRING *target :named("target") :optional, INTVAL has_target :opt_flag, 149 PMC *outer_ctx :named("outer_ctx") :optional, INTVAL has_ctx :opt_flag) :no_wb 150 { 151 Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 152 PMC * pf; 153 imc_info_t * const imcc = (imc_info_t*)attrs->imcc_info; 154 155 if (has_target) 156 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION, 157 "IMCCompiler: compiler does not support the target option"); 158 159 BEGIN_IMCC_COMPILE(interp); 160 161 /* TODO: Handle outer_ctx */ 162 pf = imcc_compile_string(imcc, source, attrs->is_pasm); 163 if (PMC_IS_NULL(pf)) { 164 STRING * const msg = imcc_last_error_message(imcc); 165 INTVAL code = imcc_last_error_code(imcc); 166 ERROR_IMCC_COMPILE(interp); 167 Parrot_ex_throw_from_c_args(INTERP, NULL, code, "%Ss", msg); 168 } 169 if (has_path) 170 VTABLE_set_string_native(INTERP, pf, path); 171 172 END_IMCC_COMPILE(interp); 173 174 RETURN(PMC *pf); 175 } 176 177 METHOD compile_file(STRING *filename, 178 STRING *path :optional, INTVAL has_path :opt_flag, 179 STRING *target :named("target") :optional, INTVAL has_target :opt_flag, 180 PMC *outer_ctx :named("outer_ctx") :optional, INTVAL has_ctx :opt_flag) :no_wb 181 { 182 Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 183 PMC * pf = PMCNULL; 184 imc_info_t * const imcc = (imc_info_t*)attrs->imcc_info; 185 186 if (has_target) 187 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION, 188 "IMCCompiler: compiler does not support the target option"); 189 190 BEGIN_IMCC_COMPILE(interp); 191 192 /* TODO: Handle outer_ctx */ 193 pf = imcc_compile_file(imcc, filename, attrs->is_pasm); 194 if (PMC_IS_NULL(pf)) { 195 STRING * const msg = imcc_last_error_message(imcc); 196 const INTVAL code = imcc_last_error_code(imcc); 197 ERROR_IMCC_COMPILE(interp); 198 Parrot_ex_throw_from_c_args(INTERP, NULL, code, "%Ss", msg); 199 } 200 201 if (has_path) 202 VTABLE_set_string_native(INTERP, pf, path); 203 204 END_IMCC_COMPILE(interp); 205 206 RETURN(PMC *pf); 207 } 208 209 /*METHOD eval(STRING *source, 210 STRING *target :named("target") :optional, INTVAL has_target :opt_flag, 211 PMC *outer_ctx :named("outer_ctx") :optional, INTVAL has_ctx :opt_flag) :no_wb 212 { 213 Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 214 PMC * pf = PMCNULL; 215 imc_info_t * const imcc = (imc_info_t*)attrs->imcc_info; 216 if (has_target) 217 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION, 218 "IMCCompiler: compiler does not support the target option"); 219 pf = imcc_compile_string(imcc, source, attrs->is_pasm); 220 }*/ 221 222 METHOD preprocess(STRING *code) :no_wb { 223 const Parrot_IMCCompiler_attributes * const attrs = PARROT_IMCCOMPILER(SELF); 224 imc_info_t * const imcc = (imc_info_t*)attrs->imcc_info; 225 imcc_preprocess(imcc, code); 226 } 227 228 /*METHOD parse_name(STRING *name) :no_wb { 229 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_UNIMPLEMENTED, 230 "IMCCompiler: parse_name is not supported"); 231 }*/ 232 233 /* TODO: This */ 234 /*METHOD load_module(STRING *name) :no_wb { 235 236 }*/ 237 238 /* TODO: This */ 239 /*METHOD get_module(STRING *name) :no_wb { 240 241 }*/ 242 243 /* TODO: This */ 244 /*METHOD get_exports(PMC *module) :no_wb { 245 246 }*/ 247} 248 249/* 250 * Local variables: 251 * c-file-style: "parrot" 252 * End: 253 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' : 254 */ 255