int main(int argc, char **argv) { const char *in_filename; FILE *fp = stdout; BOOL pretty_print_only; BOOL analyse_optimise_print; BOOL optimise; BOOL to_file; progname = argv[0]; pretty_print_only = FALSE; analyse_optimise_print = FALSE; optimise = FALSE; to_file = FALSE; /* Process command line */ if ((argc < 2) || (argc > 3)) { usage(); exit(EXIT_FAILURE); } if (argc == 2) { in_filename = argv[1]; } if (argc == 3 && streq(argv[1], "-p")) { pretty_print_only = TRUE; in_filename = argv[2]; } if (argc == 3 && streq(argv[1], "-c")) { analyse_optimise_print = TRUE; in_filename = argv[2]; } if (argc == 3 && streq(argv[1], "-f")) { to_file = TRUE; in_filename = argv[2]; } yyin = fopen(in_filename, "r"); if (yyin == NULL) { perror(in_filename); exit(EXIT_FAILURE); } if (yyparse() != 0) { /* The error message will already have been printed. */ exit(EXIT_FAILURE); } if (pretty_print_only) { pretty_prog(fp, parsed_program); return 0; } if (analyse_optimise_print) { print_bold("Original Program:"); pretty_prog(fp, parsed_program); reduce_ast(parsed_program); print_bold("\nOptimised Program:"); pretty_prog(fp, parsed_program); print_bold("\n Errors Detected:"); analyse(parsed_program); return 0; } //Standard compilation reduce_ast(parsed_program); if (to_file) { int in_filename_len = strlen(in_filename); char *outfile = checked_malloc((strlen(in_filename) + 4) * sizeof(char)); //suffix points to the '.' in filename, assuming it ends in ".wiz" const char *suffix = &in_filename[in_filename_len - 4]; //decide whether there is a ".wiz" suffix to remove or not if (in_filename_len > 3 && strcmp(suffix, ".wiz") == 0) { //in this case remove the last three characters (w, i and z) strncpy(outfile, in_filename, in_filename_len - 3); //append null-byte because strncpy does not do this automatically outfile[in_filename_len - 3] = '\0'; } else { //if suffix is not ".wiz", just append ".oz" to end of name strncpy(outfile, in_filename, in_filename_len); outfile[in_filename_len] = '.'; //append nullbute in preparation of appending "oz" outfile[in_filename_len + 1] = '\0'; } //finally add the "oz" to end of name const char *ending = "oz"; strcat(outfile, ending); printf("%s\n", outfile); fp = fopen(outfile, "w"); } compile(fp, parsed_program); return 0; }
struct Value execute (struct Tree * ast, struct Tree_map * defined, struct Map * let_map){ struct Value result; // first check for special kinds of execution if(ast->type == 'k' && string_matches(&ast->content.data.str, &if_const)){ return if_block(ast, defined, let_map); } else if(ast->type == 'k' && string_matches(&let_const, &ast->content.data.str)){ store_let_binding(ast, defined, let_map); result.type = 'u'; } else if(ast->type == 'k' && string_matches(&each_const, &ast->content.data.str)){ for_each(ast, defined, let_map); result.type = 'u'; } else if(ast->type == 'k' && string_matches(&map_const, &ast->content.data.str)){ return map_array(ast, defined, let_map); } else if(ast->type == 'k' && string_matches(&reduce_const, &ast->content.data.str)){ return reduce_array(ast, defined, let_map); } else if(ast->type == 'k' && string_matches(&set_const, &ast->content.data.str)){ struct Value index = execute(ast->children[0], defined, let_map); struct Value item = execute(ast->children[1], defined, let_map); struct Value array = execute(ast->children[2], defined, let_map); result = array_set(index, item, array); return result; } else if(ast->type == 'k' && string_matches(&for_const, &ast->content.data.str)){ for_loop(ast, defined, let_map); result.type = 'u'; //return undefined } else if(ast->type == 'k' && string_matches(&do_const, &ast->content.data.str)){ for(int i = 0; i < ast->size; i++){ if(i == ast->size-1){ result = execute(ast->children[i], defined, let_map); } else { execute(ast->children[i], defined, let_map); } } } else if(ast->type == 'k' && string_matches(&read_const, &ast->content.data.str)){ return read_file(ast->children[0]->content.data.str); } else if(ast->type == 'k' && string_matches(&substring_const, &ast->content.data.str)){ struct Value string = execute(ast->children[2], defined, let_map); struct Value start = execute(ast->children[0], defined, let_map); struct Value end = execute(ast->children[1], defined, let_map); if(string.type != 's'){ ERROR("Non-string value passed into substring: %c.", string.type); result.type = 'u'; return result; } else { return substring(start.data.ln, end.data.ln, string); } } else if(ast->type == 'k' && string_matches(&switch_const, &ast->content.data.str)){ return switch_case(ast, defined, let_map); } else if(ast->type == 'k' && string_matches(¶llel_const, &ast->content.data.str)){ parallel_execution(ast, defined, let_map); result.type = 'u'; } else { // no special execution types found, check for more basic conditions int idx; if(!ast->size){ // ast with no children is either a value or a variable if(ast->type == 'k'){ for(int i = 0; i < let_map->size; i++){ if(string_matches(&let_map->members[i]->key->data.str, &ast->content.data.str)){ return *let_map->members[i]->val; } } ERROR("Undefined variable: %s", ast->content.data.str.body); } else { return ast->content; } } else if(ast->type == 'k' && (idx = is_defined_func(defined, ast->content.data.str)) > -1){ return execute_defined_func(ast, defined, let_map, idx); } else if(ast->size == 1){ struct Value a = execute(ast->children[0], defined, let_map); if(ast->type == 'k'){ if(string_matches(&ast->content.data.str, &print_const)){ print(a); printf("\n"); result.type = 'u'; } else if(string_matches(&ast->content.data.str, &length_const)){ return length(a); } else if(string_matches(&ast->content.data.str, &return_const)){ return execute(ast->children[0], defined, let_map); } } } else if(ast->size == 2) { struct Value a = execute(ast->children[0], defined, let_map); struct Value b = execute(ast->children[1], defined, let_map); result = apply_core_function(ast, a, b); } else { result = reduce_ast(ast, defined, let_map); } } return result; }