Author: chromatic
Date: Tue Apr 10 00:50:50 2007
New Revision: 18104
Modified:
trunk/compilers/imcc/imc.h
trunk/compilers/imcc/main.c
Log:
[IMCC] More refactorings of IMCC's main entry point.
The biggest change is moving the lexer pointer into the interpreter's imc_info.
I don't really like this for the long term, but the separation of concerns is
better for now.
I've also broken out a few subroutines to clarify what occurs within IMCC's
main runloop. This means passing around a few more variables than is
absolutely necessary right now, but there may be more simplifications coming.
Modified: trunk/compilers/imcc/imc.h
==============================================================================
--- trunk/compilers/imcc/imc.h (original)
+++ trunk/compilers/imcc/imc.h Tue Apr 10 00:50:50 2007
@@ -237,6 +237,7 @@
int cnr;
int nargs;
int in_slice;
+ void *yyscanner;
} imc_info_t;
#define IMCC_INFO(i) (((Parrot_Interp)(i))->imc_info)
Modified: trunk/compilers/imcc/main.c
==============================================================================
--- trunk/compilers/imcc/main.c (original)
+++ trunk/compilers/imcc/main.c Tue Apr 10 00:50:50 2007
@@ -145,11 +145,11 @@
#define SET_TRACE(flag) Parrot_set_trace(interp, flag)
#define SET_CORE(core) interp->run_core |= core
-#define OPT_GC_DEBUG 128
-#define OPT_DESTROY_FLAG 129
-#define OPT_HELP_DEBUG 130
-#define OPT_PBC_OUTPUT 131
-#define OPT_RUNTIME_PREFIX 132
+#define OPT_GC_DEBUG 128
+#define OPT_DESTROY_FLAG 129
+#define OPT_HELP_DEBUG 130
+#define OPT_PBC_OUTPUT 131
+#define OPT_RUNTIME_PREFIX 132
static struct longopt_opt_decl options[] = {
{ '.', '.', (OPTION_flags)0, { "--wait" } },
@@ -160,7 +160,8 @@
{ 'O', 'O', OPTION_optional_FLAG, { "--optimize" } },
{ 'S', 'S', (OPTION_flags)0, { "--switched-core" } },
{ 'V', 'V', (OPTION_flags)0, { "--version" } },
- { '\0', OPT_DESTROY_FLAG, (OPTION_flags)0, { "--leak-test",
"--destroy-at-end" } },
+ { '\0', OPT_DESTROY_FLAG, (OPTION_flags)0,
+ { "--leak-test", "--destroy-at-end" } },
{ '\0', OPT_GC_DEBUG, (OPTION_flags)0, { "--gc-debug" } },
{ 'a', 'a', (OPTION_flags)0, { "--pasm" } },
{ 'b', 'b', (OPTION_flags)0, { "--bounds-checks", "--slow-core" } },
@@ -349,7 +350,7 @@
SET_FLAG(PARROT_DESTROY_FLAG);
break;
default:
- IMCC_fatal_standalone(interp, 1, "main: Invalid flag '%s'
used."
+ internal_exception(1, "main: Invalid flag '%s' used."
"\n\nhelp: parrot -h\n", (*argv)[0]);
}
}
@@ -481,6 +482,7 @@
break;
}
}
+ yylex_destroy(&yyscanner);
}
static void
@@ -509,41 +511,19 @@
return;
}
-int
-main(int argc, char * argv[])
+static int
+imcc_initialize(Interp *interp)
{
- struct PackFile *pf;
- int obj_file;
- char *sourcefile;
- const char *output_file;
- Interp *interp;
- void *yyscanner;
- STRING *executable_name;
- PMC *executable_name_pmc;
-
- Parrot_set_config_hash();
-
- interp = Parrot_new(NULL);
+ yyscan_t yyscanner = IMCC_INFO(interp)->yyscanner;
do_yylex_init(interp, &yyscanner);
Parrot_block_DOD(interp);
Parrot_block_GC(interp);
+ IMCC_INFO(interp)->yyscanner = yyscanner;
IMCC_INFO(interp)->allocator = IMCC_VANILLA_ALLOCATOR;
- /* We parse the arguments, but first store away the name of the Parrot
- executable, since parsing destroys that and we want to make it
- available. */
- executable_name = string_from_cstring(interp, argv[0], 0);
- executable_name_pmc = pmc_new(interp, enum_class_String);
- VTABLE_set_string_native(interp, executable_name_pmc, executable_name);
- VTABLE_set_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_EXECUTABLE,
- executable_name_pmc);
-
- sourcefile = parseflags(interp, &argc, &argv);
- output_file = interp->output_file;
-
/* Default optimization level is zero; see optimizer.c, imc.h */
if (!IMCC_INFO(interp)->optimizer_level) {
#if 1
@@ -555,6 +535,74 @@
#endif
}
+ return 1;
+}
+
+static void
+imcc_run_pbc(Interp *interp, int obj_file, const char *output_file,
+ int argc, char * argv[])
+{
+ if (IMCC_INFO(interp)->imcc_warn)
+ PARROT_WARNINGS_on(interp, PARROT_WARNINGS_ALL_FLAG);
+ else
+ PARROT_WARNINGS_off(interp, PARROT_WARNINGS_ALL_FLAG);
+
+ if (!IMCC_INFO(interp)->gc_off) {
+ Parrot_unblock_DOD(interp);
+ Parrot_unblock_GC(interp);
+ }
+
+ if (obj_file)
+ IMCC_info(interp, 1, "Writing %s\n", output_file);
+ else
+ IMCC_info(interp, 1, "Running...\n");
+
+ /* runs :init functions */
+ PackFile_fixup_subs(interp, PBC_MAIN, NULL);
+
+ /* XXX no return value :-( */
+ Parrot_runcode(interp, argc, argv);
+}
+
+static void
+imcc_write_pbc(Interp *interp, const char *output_file)
+{
+ size_t size;
+ opcode_t *packed;
+ FILE *fp;
+
+ IMCC_info(interp, 1, "Writing %s\n", output_file);
+
+ size = PackFile_pack_size(interp, interp->code->base.pf) *
+ sizeof (opcode_t);
+ IMCC_info(interp, 1, "packed code %d bytes\n", size);
+ packed = (opcode_t*) mem_sys_allocate(size);
+ PackFile_pack(interp, interp->code->base.pf, packed);
+ if (strcmp(output_file, "-") == 0)
+ fp = stdout;
+ else if ((fp = fopen(output_file, "wb")) == 0)
+ IMCC_fatal_standalone(interp, E_IOError,
+ "Couldn't open %s\n", output_file);
+
+ if ((1 != fwrite(packed, size, 1, fp)))
+ IMCC_fatal_standalone(interp, E_IOError,
+ "Couldn't write %s\n", output_file);
+ fclose(fp);
+ IMCC_info(interp, 1, "%s written.\n", output_file);
+ free(packed);
+}
+
+static int
+imcc_run(Interp *interp, const char *sourcefile, int argc, char * argv[])
+{
+ struct PackFile *pf;
+ int obj_file;
+ const char *output_file;
+ yyscan_t yyscanner;
+
+ yyscanner = IMCC_INFO(interp)->yyscanner;
+ output_file = interp->output_file;
+
/* Read in the source and determine whether it's Parrot bytecode,
PASM or a Parrot abstract syntax tree (PAST) file. If it isn't
any of these, then we assume that it is PIR. */
@@ -568,7 +616,7 @@
char *ext;
ext = strrchr(sourcefile, '.');
if (ext && strcmp(ext, ".pbc") == 0) {
- load_pbc = 1;
+ load_pbc = 1;
write_pbc = 0;
}
else if (!load_pbc) {
@@ -586,6 +634,7 @@
do_pre_process(interp);
Parrot_destroy(interp);
yylex_destroy(yyscanner);
+ IMCC_INFO(interp)->yyscanner = NULL;
Parrot_exit(interp, 0);
}
@@ -599,10 +648,10 @@
}
else if (ext && strcmp(ext, PARROT_OBJ_EXT) == 0) {
#if EXEC_CAPABLE
- load_pbc = 1;
+ load_pbc = 1;
write_pbc = 0;
- run_pbc = 1;
- obj_file = 1;
+ run_pbc = 1;
+ obj_file = 1;
Parrot_set_run_core(interp, PARROT_EXEC_CORE);
#else
IMCC_fatal_standalone(interp, 1, "main: can't produce object
file");
@@ -626,14 +675,13 @@
if (load_pbc) {
pf = Parrot_readbc(interp, sourcefile);
if (!pf)
- IMCC_fatal_standalone(interp, 1,
- "main: Packfile loading failed\n");
+ IMCC_fatal_standalone(interp, 1, "main: Packfile loading
failed\n");
Parrot_loadbc(interp, pf);
}
else {
/* Otherwise, we need to compile our input to bytecode. */
- int per_pbc = (write_pbc | run_pbc) != 0;
- int opt_level = IMCC_INFO(interp)->optimizer_level;
+ int per_pbc = (write_pbc | run_pbc) != 0;
+ int opt_level = IMCC_INFO(interp)->optimizer_level;
/* Shouldn't be more than five, but five extra is cheap */
char opt_desc[10];
@@ -643,7 +691,7 @@
IMCC_info(interp, 1, "using optimization '-O%s' (%x) \n",
opt_desc, opt_level);
- pf = PackFile_new(interp, 0);
+ pf = PackFile_new(interp, 0);
Parrot_loadbc(interp, pf);
IMCC_push_parser_state(interp);
@@ -656,12 +704,9 @@
IMCC_INFO(interp)->state->pasm_file = pasm_file;
IMCC_TRY(IMCC_INFO(interp)->jump_buf,
IMCC_INFO(interp)->error_code) {
- int retval;
- retval = yyparse(yyscanner, (void *) interp);
- if (retval) {
- /* fprintf(stderr, "** Parsing failed **\n"); */
+ if (yyparse(yyscanner, (void *) interp))
exit(1);
- }
+
imc_compile_all_units(interp);
}
IMCC_CATCH(IMCC_FATAL_EXCEPTION) {
@@ -692,30 +737,8 @@
}
/* Produce a PBC output file, if one was requested */
- if (write_pbc) {
- size_t size;
- opcode_t *packed;
- FILE *fp;
- IMCC_info(interp, 1, "Writing %s\n", output_file);
-
- size = PackFile_pack_size(interp, interp->code->base.pf) *
- sizeof (opcode_t);
- IMCC_info(interp, 1, "packed code %d bytes\n", size);
- packed = (opcode_t*) mem_sys_allocate(size);
- PackFile_pack(interp, interp->code->base.pf, packed);
- if (strcmp(output_file, "-") == 0)
- fp = stdout;
- else if ((fp = fopen(output_file, "wb")) == 0)
- IMCC_fatal_standalone(interp, E_IOError,
- "Couldn't open %s\n", output_file);
-
- if ((1 != fwrite(packed, size, 1, fp)))
- IMCC_fatal_standalone(interp, E_IOError,
- "Couldn't write %s\n", output_file);
- fclose(fp);
- IMCC_info(interp, 1, "%s written.\n", output_file);
- free(packed);
- }
+ if (write_pbc)
+ imcc_write_pbc(interp, output_file);
/* If necessary, load the file written above */
if (run_pbc == 2 && write_pbc && strcmp(output_file, "-")) {
@@ -729,34 +752,46 @@
}
/* Run the bytecode */
- if (run_pbc) {
+ if (run_pbc)
+ imcc_run_pbc(interp, obj_file, output_file, argc, argv);
- if (IMCC_INFO(interp)->imcc_warn)
- PARROT_WARNINGS_on(interp, PARROT_WARNINGS_ALL_FLAG);
- else
- PARROT_WARNINGS_off(interp, PARROT_WARNINGS_ALL_FLAG);
- if (!IMCC_INFO(interp)->gc_off) {
- Parrot_unblock_DOD(interp);
- Parrot_unblock_GC(interp);
- }
- if (obj_file)
- IMCC_info(interp, 1, "Writing %s\n", output_file);
- else
- IMCC_info(interp, 1, "Running...\n");
+ yylex_destroy(yyscanner);
+ IMCC_INFO(interp)->yyscanner = NULL;
+ return 0;
+}
- /* runs :init functions */
- PackFile_fixup_subs(interp, PBC_MAIN, NULL);
+int
+main(int argc, char * argv[])
+{
+ char *sourcefile;
+ Interp *interp;
+ STRING *executable_name;
+ PMC *executable_name_pmc;
+ int status;
- Parrot_runcode(interp, argc, argv);
- /* XXX no return value :-( */
- }
+ Parrot_set_config_hash();
+
+ interp = Parrot_new(NULL);
+ if (!imcc_initialize(interp))
+ internal_exception(1, "Could not initialize IMCC\n");
+
+ /* We parse the arguments, but first store away the name of the Parrot
+ executable, since parsing destroys that and we want to make it
+ available. */
+ executable_name = string_from_cstring(interp, argv[0], 0);
+ executable_name_pmc = pmc_new(interp, enum_class_String);
+ VTABLE_set_string_native(interp, executable_name_pmc, executable_name);
+ VTABLE_set_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_EXECUTABLE,
+ executable_name_pmc);
+
+ sourcefile = parseflags(interp, &argc, &argv);
+ status = imcc_run(interp, sourcefile, argc, argv);
/* Clean-up after ourselves */
Parrot_destroy(interp);
- yylex_destroy(yyscanner);
Parrot_exit(interp, 0);
- return 0;
+ return status;
}