T_INFO* check_fun_call(SYM_TAB* scope,char* name,T_LIST** args) { SYM_INFO* i = symtab_find(scope,name); T_INFO* ft; if (!i) error("undeclared function \"",name,0,"\"",0,0); ft = i->type; if (ft->cons!=fun_t) error(name," is not a function",0,0,0,0); if (types_list_equal(ft->info.fun.source,(args?*args:0))) { /* release type_list from args, replace by equal list * from function type */ if (args) { types_list_release(*args); *args = ft->info.fun.source; } return ft->info.fun.target; } error("bad type of arguments for ",name,0,0,0,0); return 0; }
ast_t* ast_get(ast_t* ast, const char* name, sym_status_t* status) { // Searches all parent scopes, but not the program scope, because the name // space for paths is separate from the name space for all other IDs. // If called directly on the program scope, searches it. if(status != NULL) *status = SYM_NONE; do { if(ast->symtab != NULL) { sym_status_t status2; ast_t* value = (ast_t*)symtab_find(ast->symtab, name, &status2); if((status != NULL) && (*status == SYM_NONE)) *status = status2; if(value != NULL) return value; } ast = ast->parent; } while((ast != NULL) && (token_get_id(ast->t) != TK_PROGRAM)); return NULL; }
ast_t* builder_find_sub_tree(builder_t* builder, const char* name) { if(builder == NULL || name == NULL) return NULL; return (ast_t*)symtab_find(builder->defs, stringtab(name), NULL); }
SYM_INFO* check_symbol(SYM_TAB* scope,char* name) { SYM_INFO* i = symtab_find(scope,name); if (!i) error("undeclared variable \"",name,0,"\"",0,0); return i; }
SYM_ENTRY* check_symbol(SYM_TAB* scope,char* name) { //printf("check_symbol\n"); SYM_ENTRY* i = symtab_find(scope,name); if (!i) error("undeclared variable \"",name,0,"\"",0,0); return i; }
LLVMValueRef gen_return(struct node *ast) { LLVMValueRef func, retval; LLVMBasicBlockRef next_block, ret_block; ret_block = symtab_find(".return"); retval = symtab_find(".retval"); if (ast->one) LLVMBuildStore(builder, codegen(ast->one), retval); LLVMBuildBr(builder, ret_block); func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); next_block = LLVMAppendBasicBlock(func, ""); LLVMPositionBuilderAtEnd(builder, next_block);; return NULL; }
static LLVMValueRef lvalue_name(struct node *ast) { LLVMValueRef lvalue; lvalue = symtab_find(ast->val); if (lvalue == NULL) generror("un %s", ast->val); return lvalue; }
LLVMValueRef gen_label(struct node *ast) { LLVMBasicBlockRef label_block, prev_block; prev_block = LLVMGetInsertBlock(builder); label_block = symtab_find(ast->one->val); LLVMMoveBasicBlockAfter(label_block, prev_block); LLVMPositionBuilderAtEnd(builder, prev_block); LLVMBuildBr(builder, label_block); LLVMPositionBuilderAtEnd(builder, label_block); codegen(ast->two); return NULL; }
// Add the given method to the relevant name list in the given symbol table static bool add_method_to_list(ast_t* method, methods_t* method_info, const char *entity_name) { assert(method != NULL); assert(method_info != NULL); assert(entity_name != NULL); const char* name = ast_name(ast_childidx(method, 1)); assert(name != NULL); symtab_t* symtab = method_info->symtab; assert(symtab != NULL); // Entity doesn't yet have method, add it to our list for later ast_t* list = (ast_t*)symtab_find(symtab, name, NULL); if(list == NULL) { ast_t* case_clash = (ast_t*)symtab_find_case(symtab, name, NULL); if(case_clash != NULL) { ast_error(case_clash, "in %s method name differs only in case", entity_name); ast_error(method, "previous definition is here"); return false; } // First instance of this name list = ast_blank(TK_ID); ast_set_name(list, name); symtab_add(symtab, name, (void*)list, SYM_NONE); if(method_info->last_list == NULL) ast_add(method_info->name_lists, list); else ast_add_sibling(method_info->last_list, list); method_info->last_list = list; } ast_add(list, method); return true; }
void check_declr(SymTab *st, Declr* d) { switch(d->tag) { case DECLR_VAR: { if(st->prev) check_array_sizes(d->type); else check_array_empty(d->type); if(!symtab_add(st, d)) print_error("double declaration of variable", d->line); break; } case DECLR_FUNC: { check_array_empty(d->type); if(d->u.func.block) { Declr *proto; SymTab *param; proto = symtab_find(st, d->u.func.name); if(!proto) { symtab_add(st, d); proto = d; } else if(proto->u.func.block) { print_error("double declaration of function", d->line); } else { proto->u.func.block = d->u.func.block; } return_type = d->type; param = symtab_new(st); check_paramlist(param, proto->u.func.params, d->line); check_block(param, proto->u.func.block); symtab_free(param); } else { if(!symtab_add(st, d)) print_error("double declaration of function prototype", d->line); } break; } default: print_error("bug in compiler!", 0); } }
static ssize_t format_address(symtab_t *st, char **buf, size_t *bufsiz, size_t offs, const char *fmt, const void *addr) { Dl_info dli; memset(&dli, 0, sizeof(dli)); (void)dladdr(addr, &dli); if (st) symtab_find(st, addr, &dli); if (dli.dli_sname == NULL) dli.dli_sname = "???"; if (dli.dli_fname == NULL) dli.dli_fname = "???"; if (dli.dli_saddr == NULL) dli.dli_saddr = (void *)(intptr_t)addr; return format_string(buf, bufsiz, offs, fmt, &dli, addr); }
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; }
bool ast_within_scope(ast_t* outer, ast_t* inner, const char* name) { do { if(inner->symtab != NULL) { sym_status_t status2; ast_t* value = (ast_t*)symtab_find(inner->symtab, name, &status2); if(value != NULL) return true; } if(inner == outer) break; inner = inner->parent; } while((inner != NULL) && (token_get_id(inner->t) != TK_PROGRAM)); return false; }
void check_var(SymTab *st, Var* v) { Declr *d; int dim; ExpListNode *eln; d = symtab_find(st, v->name); if(!d) print_error("variable is not declared" , v->line); if(d->tag == DECLR_FUNC) print_error("illegal use of a function", v->line); v->var = d; dim = d->type->dimensions; eln = v->idxs; while(eln) { if(!dim) print_error("tried to index a value that is not an array", v->line); check_exp(st, eln->exp); check_type_int(eln->exp); dim--; eln = eln->next; } ALLOC(v->type, Type); v->type->type = d->type->type; v->type->dimensions = dim; v->type->sizes = NULL; }
// 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; }
void check_exp(SymTab *st, Exp* e) { switch(e->tag) { case EXP_INT: e->type = ∭ break; case EXP_FLOAT: e->type = &tfloat; break; case EXP_STRING: e->type = &tstring; break; case EXP_VAR: check_var(st, e->u.var); e->type = (e->u.var)->type; break; case EXP_BINOP: { check_exp(st, e->u.binop.e1); if((e->u.binop.e1)->type->type == TK_TCHAR) insert_conv(&(e->u.binop.e1), TK_TINT); check_exp(st, e->u.binop.e2); if((e->u.binop.e2)->type->type == TK_TCHAR) insert_conv(&(e->u.binop.e2), TK_TINT); switch(e->u.binop.op) { case TK_EQ: case TK_LEQ: case TK_GEQ: case TK_NEQ: case '<': case '>': { check_type_relational(e); break; } case TK_AND: case TK_OR: { check_type_int(e->u.binop.e1); check_type_int(e->u.binop.e2); e->type = ∭ break; } case '+': case '-': case '*': case '/': { check_type_arith(e); break; } default: print_error("Bug in the compiler!", e->line); } break; } case EXP_NEG: { check_exp(st, e->u.exp); if((e->u.exp)->type->type == TK_TCHAR) insert_conv(&(e->u.exp), TK_TINT); if((e->u.exp)->type->dimensions != 0) print_error("cannot negate an array", e->line); e->type = (e->u.exp)->type; break; } case EXP_LNEG: { check_exp(st, e->u.exp); check_type_int(e->u.exp); e->type = ∭ break; } case EXP_FUNCALL: { Declr *func; ExpListNode *eln; DeclrListNode *pln; func = symtab_find(st, e->u.funcall.name); if(!func) print_error("calling undeclared function", e->line); eln = e->u.funcall.expl; pln = func->u.func.params; while(eln) { if(!pln) print_error("excess arguments in function call", e->line); check_exp(st, eln->exp); if(pln->declr != NULL) { check_type_compatible(pln->declr->type, &(eln->exp), e->line); pln = pln->next; } eln = eln->next; } if(pln && pln->declr) print_error("missing arguments in function call", e->line); e->u.funcall.func = func; e->type = func->type; break; } } }