git @ Cat's Eye Technologies Bhuna / master src / driver / main.c
master

Tree @master (Download .tar.gz)

main.c @masterraw · history · blame

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "mem.h"
#include "scan.h"
#include "parse.h"
#include "symbol.h"
#include "ast.h"
#include "builtin.h"
#include "value.h"
#include "activation.h"
#include "vm.h"
#include "type.h"
#include "report.h"
#include "gc.h"
#include "trace.h"
#include "process.h"
#include "icode.h"

#ifdef DEBUG
#define OPTS "cdgG:ilmnopsvy"
#define RUN_PROGRAM run_program
#else
#define OPTS "G:i"
#define RUN_PROGRAM 1
#endif

extern char *optarg;
extern int optind, opterr, optopt;

struct activation *global_ar;

extern int gc_trigger;
extern int gc_target;

void
usage(char **argv)
{
	fprintf(stderr, "Usage: %s [-" OPTS "] source\n",
	    argv[0]);
#ifdef DEBUG
	fprintf(stderr, "  -c: trace process context switching\n");
	fprintf(stderr, "  -d: trace pooling\n");
	fprintf(stderr, "  -g: trace garbage collection\n");
#endif
	fprintf(stderr, "  -G int: set garbage collection threshold\n");
#ifdef DEBUG
	fprintf(stderr, "  -i: dump intermediate format\n");
	fprintf(stderr, "  -l: trace bytecode generation (implies -x)\n");
	fprintf(stderr, "  -m: trace virtual machine\n");
	fprintf(stderr, "  -n: don't actually run program\n");
	fprintf(stderr, "  -o: trace allocations\n");
	fprintf(stderr, "  -p: dump program AST before run\n");
	fprintf(stderr, "  -s: dump symbol table before run\n");
	fprintf(stderr, "  -v: trace activation records\n");
	fprintf(stderr, "  -y: trace type inference\n");
#endif
	exit(1);
}

int
main(int argc, char **argv)
{
	char **real_argv = argv;
	struct scan_st *sc;
	struct symbol_table *stab;
	struct ast *a;
	char *source = NULL;
	int opt;
	int err_count = 0;
#ifdef DEBUG
	int run_program = 1;
	int dump_symbols = 0;
	int dump_program = 0;
	int dump_icode = 0;
#endif

#ifdef DEBUG
	setvbuf(stdout, NULL, _IOLBF, 0);
#endif

	/*
	 * Get command-line arguments.
	 */
	while ((opt = getopt(argc, argv, OPTS)) != -1) {
		switch(opt) {
#ifdef DEBUG
		case 'c':
			trace_scheduling++;
			break;
#ifdef POOL_VALUES
		case 'd':
			trace_pool++;
			break;
#endif
		case 'g':
			trace_gc++;
			break;
#endif
		case 'G':
			gc_trigger = atoi(optarg);
			break;
#ifdef DEBUG
		case 'i':
			dump_icode++;
			break;
		case 'l':
			trace_gen++;
			break;
		case 'm':
			trace_vm++;
			break;
		case 'n':
			run_program = 0;
			break;
		case 'o':
			trace_valloc++;
			break;
		case 'p':
			dump_program = 1;
			break;
		case 's':
			dump_symbols = 1;
			break;
		case 'v':
			trace_activations++;
			break;
		case 'y':
			trace_type_inference++;
			break;
#endif
		case '?':
		default:
			usage(argv);
		}
	}
	argc -= optind;
	argv += optind;

	if (*argv != NULL)
		source = *argv;
	else
		usage(real_argv);

#ifdef POOL_VALUES
	value_pool_new();
#endif

	gc_target = gc_trigger;
	if ((sc = scan_open(source)) != NULL) {
		stab = symbol_table_new(NULL, 0);
		global_ar = activation_new_on_heap(100, NULL, NULL);
		register_std_builtins(stab);
		report_start();
		a = parse_program(sc, stab);
		scan_close(sc);
#ifdef DEBUG
		if (dump_symbols)
			symbol_table_dump(stab, 1);
		if (dump_program) {
			ast_dump(a, 0);
		}
#endif
#ifndef DEBUG
		symbol_table_free(stab);
		types_free();
#endif
		err_count = report_finish();
		if (err_count == 0) {
			struct iprogram *ip;
			struct vm *vm;
			struct process *p;
			unsigned char *program;

			program = bhuna_malloc(16384);

			ip = ast_gen_iprogram(a);
			iprogram_eliminate_nops(ip);
			iprogram_eliminate_useless_jumps(ip);
			iprogram_optimize_tail_calls(ip);
			iprogram_optimize_push_small_ints(ip);
			iprogram_eliminate_dead_code(ip);
			iprogram_gen(&program, ip);
#ifdef DEBUG
			if (dump_icode > 0)
				iprogram_dump(ip, program);
#endif

			vm = vm_new(program, 16384);
			vm_set_pc(vm, program);
			vm->current_ar = global_ar;
			p = process_new(vm);
			/* ast_dump(a, 0); */
			if (RUN_PROGRAM) {
				process_scheduler();
			}
			vm_free(vm);
			bhuna_free(program);
			/*value_dump_global_table();*/
		}

		ast_free(a);	/* XXX move on up */
		/* gc(); */		/* actually do a full blow out at the end */
		/* activation_free_from_stack(global_ar); */
#ifdef DEBUG
		symbol_table_free(stab);
		types_free();
		if (trace_valloc > 0) {
			/*
			value_dump_global_table();
			*/
			printf("Created:  %8d\n", num_vars_created);
			printf("Cached:   %8d\n", num_vars_cached);
			printf("Freed:    %8d\n", num_vars_freed);
		}
		if (trace_activations > 0) {
			printf("AR's alloc'ed:  %8d\n", activations_allocated);
			printf("AR's freed:     %8d\n", activations_freed);
		}
#ifdef POOL_VALUES
		if (trace_pool > 0) {
			pool_report();
		}
#endif
#endif
		return(0);
	} else {
		fprintf(stderr, "Can't open `%s'\n", source);
		return(1);
	}
}