bool ffi_get_decl(typecheck_t* t, ast_t* ast, ast_t** out_decl, pass_opt_t* opt) { pony_assert(t != NULL); pony_assert(ast != NULL); pony_assert(out_decl != NULL); const char* ffi_name = ast_name(ast_child(ast)); // Get the symbol table for our containing ifdef (if any) directly. We can't // just search up through scopes as normal since FFI declarations in outer // scopes may not be valid within our ifdef. ast_t* ifdef = t->frame->ifdef_clause; pony_assert(ifdef != NULL); symtab_t* symtab = ast_get_symtab(ifdef); sym_status_t status; ast_t* decl = symtab_find(symtab, ffi_name, &status); if(status == SYM_ERROR) // We've already found an error with that FFI name in this context. return false; if(status == SYM_NONE) { // We've not looked that up yet. pony_assert(decl == NULL); if(!find_ffi_decl(ast, t->frame->package, t->frame->ifdef_cond, &decl, opt)) { // That went wrong. Record that so we don't try again. symtab_add(symtab, ffi_name, NULL, SYM_ERROR); return false; } // Store declaration found for next time, including if we found nothing. symtab_add(symtab, ffi_name, decl, SYM_FFIDECL); } *out_decl = decl; return true; }
// Process all our sub-tree references static bool process_refs(build_parser_t* builder) { assert(builder != NULL); assert(builder->defs != NULL); for(builder_ref_t* p = builder->refs; p != NULL; p = p->next) { assert(p->name != NULL); assert(p->node != NULL); ast_t* subtree = (ast_t*)symtab_find(builder->defs, p->name, NULL); if(subtree == NULL) { build_error(builder, "Attribute {def %s} not found", p->name); return false; } if(p->symtab == NULL) { // Set node data ast_setdata(p->node, subtree); } else { // Add subtree to node's symtab symtab_t* symtab = ast_get_symtab(p->node); assert(symtab != NULL); if(!symtab_add(symtab, p->symtab, subtree, SYM_NONE)) { build_error(builder, "Duplicate name %s in symbol table", p->name); return false; } } } return true; }
ast_result_t pass_expr(ast_t** astp, pass_opt_t* options) { typecheck_t* t = &options->check; ast_t* ast = *astp; bool r = true; switch(ast_id(ast)) { case TK_NOMINAL: r = expr_nominal(options, astp); break; case TK_FVAR: case TK_FLET: case TK_PARAM: r = expr_field(options, ast); break; case TK_NEW: case TK_BE: case TK_FUN: r = expr_fun(options, ast); break; case TK_SEQ: r = expr_seq(ast); break; case TK_VAR: case TK_LET: r = expr_local(t, ast); break; case TK_BREAK: r = expr_break(t, ast); break; case TK_CONTINUE: r = expr_continue(t, ast); break; case TK_RETURN: r = expr_return(options, ast); break; case TK_IS: case TK_ISNT: r = expr_identity(options, ast); break; case TK_ASSIGN: r = expr_assign(options, ast); break; case TK_CONSUME: r = expr_consume(t, ast); break; case TK_RECOVER: r = expr_recover(ast); break; case TK_DOT: r = expr_dot(options, astp); break; case TK_TILDE: r = expr_tilde(options, astp); break; case TK_QUALIFY: r = expr_qualify(options, astp); break; case TK_CALL: r = expr_call(options, astp); break; case TK_IF: r = expr_if(options, ast); break; case TK_WHILE: r = expr_while(options, ast); break; case TK_REPEAT: r = expr_repeat(options, ast); break; case TK_TRY_NO_CHECK: case TK_TRY: r = expr_try(options, ast); break; case TK_MATCH: r = expr_match(options, ast); break; case TK_CASES: r = expr_cases(ast); break; case TK_CASE: r = expr_case(options, ast); break; case TK_TUPLE: r = expr_tuple(ast); break; case TK_ARRAY: r = expr_array(options, astp); break; case TK_REFERENCE: r = expr_reference(options, astp); break; case TK_THIS: r = expr_this(options, ast); break; case TK_TRUE: case TK_FALSE: r = expr_literal(options, ast, "Bool"); break; case TK_ERROR: r = expr_error(ast); break; case TK_COMPILER_INTRINSIC: r = expr_compiler_intrinsic(t, ast); break; case TK_POSITIONALARGS: case TK_NAMEDARGS: case TK_NAMEDARG: case TK_UPDATEARG: ast_inheritflags(ast); break; case TK_AMP: r = expr_addressof(options, ast); break; case TK_DONTCARE: r = expr_dontcare(ast); break; case TK_INT: // Integer literals can be integers or floats make_literal_type(ast); break; case TK_FLOAT: make_literal_type(ast); break; case TK_STRING: if(ast_id(ast_parent(ast)) == TK_PACKAGE) return AST_OK; r = expr_literal(options, ast, "String"); break; case TK_FFICALL: return expr_ffi(options, ast); default: {} } if(!r) { assert(get_error_count() > 0); return AST_ERROR; } // Can't use ast here, it might have changed symtab_t* symtab = ast_get_symtab(*astp); if(symtab != NULL && !symtab_check_all_defined(symtab)) return AST_ERROR; return AST_OK; }