ast_result_t pass_verify(ast_t** astp, pass_opt_t* options) { ast_t* ast = *astp; bool r = true; switch(ast_id(ast)) { case TK_FUN: case TK_NEW: case TK_BE: r = verify_fun(options, ast); break; case TK_FUNREF: case TK_FUNCHAIN: case TK_NEWREF: r = verify_function_call(options, ast); break; case TK_BEREF: case TK_BECHAIN: case TK_NEWBEREF: r = verify_behaviour_call(options, ast); break; case TK_FFICALL: r = verify_ffi_call(options, ast); break; case TK_TRY: case TK_TRY_NO_CHECK: r = verify_try(options, ast); break; case TK_LETREF: case TK_VARREF: case TK_FLETREF: case TK_FVARREF: case TK_EMBEDREF: case TK_CALL: case TK_QUALIFY: case TK_TUPLE: case TK_ASSIGN: case TK_MATCH: case TK_CASES: case TK_CASE: case TK_IS: case TK_ISNT: case TK_SEQ: case TK_BREAK: case TK_RETURN: case TK_IF: case TK_IFDEF: case TK_WHILE: case TK_REPEAT: case TK_RECOVER: case TK_POSITIONALARGS: case TK_NAMEDARGS: case TK_NAMEDARG: case TK_UPDATEARG: ast_inheritflags(ast); break; case TK_ERROR: ast_seterror(ast); break; default: {} } if(!r) { assert(errors_get_count(options->check.errors) > 0); return AST_ERROR; } return AST_OK; }
bool expr_fun(pass_opt_t* opt, ast_t* ast) { typecheck_t* t = &opt->check; AST_GET_CHILDREN(ast, cap, id, typeparams, params, type, can_error, body); if(ast_id(body) == TK_NONE) return true; if(!coerce_literals(&body, type, opt)) return false; bool is_trait = (ast_id(t->frame->type) == TK_TRAIT) || (ast_id(t->frame->type) == TK_INTERFACE) || (ast_id((ast_t*)ast_data(ast)) == TK_TRAIT) || (ast_id((ast_t*)ast_data(ast)) == TK_INTERFACE); // Check partial functions. if(ast_id(can_error) == TK_QUESTION) { // If a partial function, check that we might actually error. ast_t* body_type = ast_type(body); if(body_type == NULL) { // An error has already occurred. assert(errors_get_count(t->errors) > 0); return false; } if(!is_trait && !ast_canerror(body) && (ast_id(body_type) != TK_COMPILE_INTRINSIC)) { ast_error(opt->check.errors, can_error, "function body is not partial but the function is"); return false; } } else { // If not a partial function, check that we can't error. if(ast_canerror(body)) { ast_error(opt->check.errors, can_error, "function body is partial but the function is not"); show_partiality(opt, body); return false; } } if(!check_primitive_init(opt, ast) || !check_finaliser(opt, ast)) return false; if(!check_main_create(opt, ast)) return false; switch(ast_id(ast)) { case TK_NEW: { bool ok = true; if(is_machine_word(type)) { if(!check_return_type(opt, ast)) ok = false; } if(!check_fields_defined(opt, ast)) ok = false; return ok; } case TK_FUN: return check_return_type(opt, ast); default: {} } return true; }
int main(int argc, char* argv[]) { stringtab_init(); pass_opt_t opt; pass_opt_init(&opt); opt.release = true; opt.output = "."; ast_setwidth(get_width()); bool print_program_ast = false; bool print_package_ast = false; opt_state_t s; ponyint_opt_init(args, &s, &argc, argv); bool ok = true; bool print_usage = false; int id; while((id = ponyint_opt_next(&s)) != -1) { switch(id) { case OPT_VERSION: printf("%s [%s] (llvm %s)\n", PONY_VERSION, PONY_BUILD_CONFIG, LLVM_VERSION); return 0; case OPT_DEBUG: opt.release = false; break; case OPT_BUILDFLAG: define_build_flag(s.arg_val); break; case OPT_STRIP: opt.strip_debug = true; break; case OPT_PATHS: package_add_paths(s.arg_val, &opt); break; case OPT_OUTPUT: opt.output = s.arg_val; break; case OPT_LIBRARY: opt.library = true; break; case OPT_RUNTIMEBC: opt.runtimebc = true; break; case OPT_PIC: opt.pic = true; break; case OPT_DOCS: opt.docs = true; break; case OPT_SAFE: if(!package_add_safe(s.arg_val, &opt)) ok = false; break; case OPT_IEEEMATH: opt.ieee_math = true; break; case OPT_CPU: opt.cpu = s.arg_val; break; case OPT_FEATURES: opt.features = s.arg_val; break; case OPT_TRIPLE: opt.triple = s.arg_val; break; case OPT_STATS: opt.print_stats = true; break; case OPT_LINK_ARCH: opt.link_arch = s.arg_val; break; case OPT_LINKER: opt.linker = s.arg_val; break; case OPT_AST: print_program_ast = true; break; case OPT_ASTPACKAGE: print_package_ast = true; break; case OPT_TRACE: parse_trace(true); break; case OPT_WIDTH: ast_setwidth(atoi(s.arg_val)); break; case OPT_IMMERR: errors_set_immediate(opt.check.errors, true); break; case OPT_VERIFY: opt.verify = true; break; case OPT_EXTFUN: opt.extfun = true; break; case OPT_FILENAMES: opt.print_filenames = true; break; case OPT_CHECKTREE: opt.check_tree = true; break; case OPT_BNF: print_grammar(false, true); return 0; case OPT_ANTLR: print_grammar(true, true); return 0; case OPT_ANTLRRAW: print_grammar(true, false); return 0; case OPT_VERBOSE: { int v = atoi(s.arg_val); if (v >= 0 && v <= 4) { opt.verbosity = (verbosity_level)v; } else { ok = false; } } break; case OPT_PASSES: if(!limit_passes(&opt, s.arg_val)) { ok = false; print_usage = true; } break; default: usage(); return -1; } } for(int i = 1; i < argc; i++) { if(argv[i][0] == '-') { printf("Unrecognised option: %s\n", argv[i]); ok = false; print_usage = true; } } #if defined(PLATFORM_IS_WINDOWS) opt.strip_debug = true; #endif if(!ok) { errors_print(opt.check.errors); if(print_usage) usage(); return -1; } if(ponyc_init(&opt)) { if(argc == 1) { ok &= compile_package(".", &opt, print_program_ast, print_package_ast); } else { for(int i = 1; i < argc; i++) ok &= compile_package(argv[i], &opt, print_program_ast, print_package_ast); } } if(!ok && errors_get_count(opt.check.errors) == 0) printf("Error: internal failure not reported\n"); ponyc_shutdown(&opt); pass_opt_done(&opt); return ok ? 0 : -1; }