📄 declaration.c
字号:
#include "declaration.h"#include "error.h"#include "io.h"#include "salloc.h"#include "printlist.h"#include "statement.h"#include <string.h>List *global_declarations;int expr_offset = 0;Declaration *global_decl;Type *type;Scope *temp, *expr_temp;Declaration *new_subprogram_declaration(Token *token){ Declaration *decl = safe_malloc(sizeof(Declaration)); decl->subtype = subprog_decl; decl->token = token; SUBPROG_DECL(decl).body = 0; SUBPROG_DECL(decl).formal_args_scope = 0; SUBPROG_DECL(decl).formal_args = 0; SUBPROG_DECL(decl).type = 0; SUBPROG_DECL(decl).return_type = 0; SUBPROG_DECL(decl).redeclaration = 0; SUBPROG_DECL(decl).has_been_defined = false; return decl;}Declaration *new_var_declaration(Token *token){ Declaration *decl = safe_malloc(sizeof(Declaration));#ifdef DEBUG printf("Token name = %s\n",token->name); printf("Token line = %d\n",token->line_number);#endif decl->subtype = var_decl; decl->token = token; VAR_DECL(decl).type = 0; return decl;}Declaration *new_record_declaration(Token *token, List *list) /*create a new record declaration */{ Declaration *decl = safe_malloc(sizeof(Declaration));#ifdef DEBUG printf("Token name = %s\n",token->name); printf("Token line = %d\n",token->line_number);#endif decl->subtype = record_decl; decl->token = token; RECORD_DECL(decl).member_scope = current_scope; RECORD_DECL(decl).var_list = list; RECORD_DECL(decl).type = new_record_type(decl); return decl;}void delete_declaration(Declaration *decl){ if (decl != 0) { switch (decl->subtype) { case subprog_decl: delete_statement(SUBPROG_DECL(decl).body); delete_scope(SUBPROG_DECL(decl).formal_args_scope); delete_declaration_list(SUBPROG_DECL(decl).formal_args); delete_type(SUBPROG_DECL(decl).type); delete_type(SUBPROG_DECL(decl).return_type); break; case var_decl: delete_type(VAR_DECL(decl).type); break; case record_decl: delete_scope(RECORD_DECL(decl).member_scope); delete_declaration_list(RECORD_DECL(decl).var_list); break; } delete_token(decl->token); free(decl); }}void delete_declaration_list(List *declarations){ if (declarations != 0) { unsigned i; for (i = 0; i < list_size(declarations); i ++) delete_declaration(list_index(declarations, i)); delete_list(declarations); }}/* Redeclaring is only allowed for subprograms, and only if the types * are identical. This function checks whether that is the case for * two declarations. */static void match_subprogram_prototypes(Declaration *d1, Declaration *d2){ unsigned i; List *formals1, *formals2; Type *t1, *t2; if (d1->subtype != subprog_decl) { error(d2->token, "%s redeclares non-subprogram", d2->token->name); return; } formals1 = SUBPROG_DECL(d1).formal_args; formals2 = SUBPROG_DECL(d2).formal_args; if (formals1 != 0 && formals2 != 0) { if (list_size(formals1) != list_size(formals2)) error(d2->token, "%s redeclared with different number of arguments", d2->token->name); else for (i = 0; i < list_size(formals1); i ++) { Declaration *var1 = list_index(formals1, i); Declaration *var2 = list_index(formals2, i); t1 = VAR_DECL(var1).type; t2 = VAR_DECL(var2).type; if (!types_compatible(t1, t2) || t1->call_by_ref != t2->call_by_ref) error(var2->token, "argument %u redeclared with different type", i + 1); } } t1 = SUBPROG_DECL(d1).return_type; t2 = SUBPROG_DECL(d2).return_type; if (!types_compatible(t1, t2)) error(d2->token, "different return type for redeclared subprogram %s", d2->token->name);}static void type_check_main_function(Declaration *decl){ List *formals; Declaration *arg; Type *type; if (strcmp(decl->token->name, "main") == 0 && (formals = SUBPROG_DECL(decl).formal_args) != 0 && (list_size(formals) != 1 || ((arg = list_index(formals, 0)) != 0 && (type = VAR_DECL(arg).type) != 0 && (type->subtype != array_type || ((type = ARRAY_TYPE(type).base_type) != 0 && (type->subtype != array_type || ((type = ARRAY_TYPE(type).base_type) != 0 && type->subtype != char_type))))) || SUBPROG_DECL(decl).return_type->subtype != int_type)) error(decl->token, "prototype of global function main should be: " "\"function main(argv : array of string) : int;\"");}static void type_check_subprogram_declaration(Declaration *decl){ Declaration *redecl = SUBPROG_DECL(decl).redeclaration; if (redecl != 0) { match_subprogram_prototypes(redecl, decl); if (redecl->subtype == subprog_decl && SUBPROG_DECL(decl).body != 0) { if (SUBPROG_DECL(redecl).has_been_defined) error(decl->token, "multiple definition of %s", decl->token->name); else SUBPROG_DECL(redecl).has_been_defined = true; } } type_check_statement(SUBPROG_DECL(decl).body, decl); type_check_main_function(decl);}void type_check_declaration(Declaration *decl){ if (decl == 0) return; switch (decl->subtype) { case subprog_decl: type_check_subprogram_declaration(decl); break; case var_decl: break; case record_decl: break; }}void type_check_declaration_list(List *declarations){ if (declarations != 0) { unsigned i; for (i = 0; i < list_size(declarations); i ++) type_check_declaration(list_index(declarations, i)); }}static void generate_record_declaration(FILE *file, Declaration *decl, Bool initialize){ int i; Declaration *declTemp; fprintf(file,"typedef struct\n{\n");#ifdef DEBUG printf("typedef struct\n{\n");#endif for (i=0;i<list_size(RECORD_DECL(decl).var_list);i++) { declTemp = ((Declaration *)list_index(RECORD_DECL(decl).var_list,i)); generate_type(file,(VAR_DECL(declTemp)).type); fprintf(file," field_%s;\n",((Declaration *)list_index(RECORD_DECL(decl).var_list,i))->token->name); #ifdef DEBUG printf(" field_%s;\n",((Declaration *)list_index(RECORD_DECL(decl).var_list,i))->token->name); #endif } fprintf(file,"}\nrecord_%s;\n",decl->token->name);#ifdef DEBUG printf("}\nrecord_%s;\n",decl->token->name);#endif}static void generate_init_record(FILE *file,Declaration *decl){ int i; Declaration *declTemp,*temp; declTemp = decl; for (i=0;i<list_size(RECORD_DECL(declTemp).var_list);i++) { temp = list_index(RECORD_DECL(declTemp).var_list,i); if (i==0) { fprintf(file, "{"); #ifdef DEBUG printf("{"); #endif } else { fprintf(file,","); #ifdef DEBUG printf(","); #endif } if (VAR_DECL(temp).type->subtype == record_type) { generate_init_record(file, RECORD_TYPE(VAR_DECL(temp).type).decl); } else { fprintf(file, "0"); #ifdef DEBUG printf("0"); #endif } } if (i==0) { fprintf(file, "{}"); #ifdef DEBUG printf("{}"); #endif } else { fprintf(file,"}"); #ifdef DEBUG printf("}"); #endif }}static void generate_var_declaration(FILE *file, Declaration *decl, Bool initialize){ /* RAFB: bug fix. We must generate an extern declaration for * each global variable in case it is used before it is * declared. */ if (lookup_in_this_scope(global_scope, decl->token->name) == decl) { fprintf(h_out, "extern "); #ifdef DEBUG printf("extern "); #endif generate_type(h_out, VAR_DECL(decl).type); fprintf(h_out, " cb_%s;\n", decl->token->name); #ifdef DEBUG printf(" cb_%s;\n", decl->token->name); #endif } if(decl->subtype == var_decl) { generate_type(file, VAR_DECL(decl).type); fprintf(file, " cb_%s", decl->token->name); #ifdef DEBUG printf(" cb_%s", decl->token->name); #endif if (initialize) { if ( VAR_DECL(decl).type->subtype==record_type) { fprintf(file,"="); #ifdef DEBUG printf("="); #endif generate_init_record(file,RECORD_TYPE(VAR_DECL(decl).type).decl); fprintf(file,";\n"); #ifdef DEBUG printf(";\n"); #endif } else { fprintf(file, "=0;\n"); #ifdef DEBUG printf("=0;\n"); #endif } } }}static void generate_prototype(FILE *file, Declaration *decl){ unsigned i; generate_type(file, SUBPROG_DECL(decl).return_type); fprintf(file, " cb_%s", decl->token->name); #ifdef DEBUG printf(" cb_%s", decl->token->name); #endif for (i = 0; i < list_size(SUBPROG_DECL(decl).formal_args); i ++) { Declaration *arg = list_index(SUBPROG_DECL(decl).formal_args, i); putc(i == 0 ? '(' : ',', file); #ifdef DEBUG printf("%c",i == 0 ? '(' : ','); #endif generate_var_declaration(file, arg, false); } fprintf(file, i == 0 ? "()" : ")"); #ifdef DEBUG printf(i == 0 ? "()" : ")"); #endif}static void generate_subprog_declaration(Declaration *decl){ generate_prototype(h_out, decl); fprintf(h_out, ";\n"); #ifdef DEBUG printf(";\n"); #endif if (SUBPROG_DECL(decl).body != 0) { generate_prototype(c_out, decl); fprintf(c_out, "{\n"); #ifdef DEBUG printf("{\n"); #endif generate_statement(SUBPROG_DECL(decl).body); if (SUBPROG_DECL(decl).return_type->subtype != void_type) { fprintf(c_out, "runtime_error(\"%s returns no value\");\n", decl->token->name); #ifdef DEBUG printf("runtime_error(\"%s returns no value\");\n", decl->token->name); #endif } fprintf(c_out, "}\n"); #ifdef DEBUG printf("}\n"); #endif }}void generate_declaration(Declaration *decl){ switch (decl->subtype) { case subprog_decl: generate_subprog_declaration(decl); break; case var_decl: generate_var_declaration(c_out, decl, true); break; case record_decl: generate_record_declaration(h_out,decl,true); break; }}void generate_declaration_list(List *declarations){ unsigned i; for (i = 0; i < list_size(declarations); i ++) generate_declaration(list_index(declarations, i));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -