Code tuple_const(Pnode p, Pschema s) { Pschema schema; // Scorro tutti gli elementi della tupla Code result = endcode(); Pnode elem; for (elem = p->child; elem != NULL; elem = elem->brother) { Code elemcode; switch (elem->type) { case N_INTCONST: case N_BOOLCONST: elemcode = makecode1(T_IATTR, elem->value); break; case N_STRCONST: elemcode = makecode1(T_SATTR, elem->value); break; default: noderror(elem); } if (result.head == NULL) result = elemcode; else result = appcode(result, elemcode); } // Type checking schema = tuple_to_schema(p); if (!type_equal(schema, s)) semerror(p, "Incompatible tuples in table constant"); free_schema(schema); return result; }
/*Controlla la semantica del nodo while e ne restituisce il codice*/ Code while_stat(Pnode while_stat_node){ //Imposto le due parti del nodo Pnode expr_node = while_stat_node->child; Pnode stat_list_node = while_stat_node->child->brother; //Definisco la variabile che contiene il codice da ritornare Code while_stat_code; //La generazione dell'ambiente viene fatta all'interno della funzione stat_list //Genero il codice di expr Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); //Controllo i vincoli semantici if (schema_expr->type!=BOOLEAN) semerror(expr_node,"Expected boolean type"); //Genero il codice di stat_list Code stat_list_code = stat_list(stat_list_node); //Calcolo gli offset int exit = stat_list_code.size + 2; int up = -(expr_code.size + stat_list_code.size + 1); //Genero il codice di while_stat while_stat_code = concode(expr_code,makecode1(T_SKIPF,exit),stat_list_code,makecode1(T_SKIP,up),endcode()); return while_stat_code; }
/*Genera il codice per il nodo def_stat e controlla i vincoli semantici*/ Code def_stat(Pnode def_stat_node){ //Imposto le due parti del nodo Pnode type_node = def_stat_node->child; Pnode id_list_head_node = def_stat_node->child->brother; //Definisco la variabile che contiene il codice da ritornare Code def_stat_code ; def_stat_code.head = NULL; def_stat_code.tail = NULL; def_stat_code.size = 0; //Sintetizzo il type Pschema schema_type = type(type_node); //Ottengo la id_list int id_list_len; Pname id_list_name = id_list(id_list_head_node,&id_list_len); //Controllo gli errori semantici //id ripetuti Boolean repetition = repeated_names(id_list_name); if (repetition == TRUE){ semerror(def_stat_node,"More than one variable with the same name"); } //variabili già assegnate Pnode id_node; for (id_node = id_list_head_node; id_node!=NULL; id_node=id_node->brother) if (name_in_environment(valname(id_node))) semerror(id_node,"Variable already defined"); //Genero il codice per la definizione delle variabili e inserisco i nomi nel contesto for (id_node = id_list_head_node; id_node!=NULL; id_node=id_node->brother){ //Genero il codice dell'id Code id_code ; int spazio_da_allocare = get_size(schema_type); if (schema_type->type == TABLE) id_code = makecode1(T_NEWTAB,spazio_da_allocare); else id_code = makecode1(T_NEWATOM,spazio_da_allocare); //Inserisco il nome nell'ambiente insert_name_into_environment(valname(id_node)); //Inserisco il nome nella symbol table Pschema schema_symbol = clone_schema(schema_type); schema_symbol->name = valname(id_node); insert(*schema_symbol); //Appendo a def_stat_code l'id_code def_stat_code = appcode(def_stat_code,id_code); } return def_stat_code; }
Code stat_list(Pnode p) { int env_num_vars = 0; push_environment(); /* stat_list / / stat --> stat --> stat */ Code s = stat(p->child); // Scorro gli stats, dal secondo in poi for (p = p->child->brother; p != NULL; p = p->brother) { s = appcode(s, stat(p)); } // Tolgo le variabili dichiarate in questo environment: if ((env_num_vars = numobj_in_current_env()) > 0) { Value v1; v1.ival = env_num_vars; s = appcode(s, makecode1(T_POP, v1)); } pop_environment(); return s; }
Code assign_stat(Pnode p) { Psymbol symbol; Code exprcode; Schema exprschema; /* assign_stat / / ID ---> expr */ // Semantica: Carico gli schemi di ID e expr symbol = lookup(valname(p->child)); if (symbol == NULL) semerror(p->child, "Undefined identifier in assignment"); exprcode = expr(p->child->brother, &exprschema); // Type checking: if (!type_equal(symbol->schema, &exprschema)) semerror(p->child->brother, "Incompatible types in assignment"); if (exprschema.next != NULL) free_schema(exprschema.next); Value v1; v1.ival = symbol->oid; return concode( exprcode, makecode1(T_STO, v1), endcode()); }
/*Controlla i vincoli semantici dell'assegnamento e ne ritorna il codice*/ Code assign_stat(Pnode assign_stat_node){ #ifdef DEBUG_ASSIGN_STAT printf("ASSIGN_STAT - enter\n"); #endif //Imposto le due parti del nodo Pnode id_node = assign_stat_node->child; Pnode expr_node = assign_stat_node->child->brother; //Definisco la variabile che contiene il codice da ritornare Code assign_stat_code ; //Controllo i vincoli semantici //Visibilità del nome if (lookup(valname(id_node))==NULL) semerror(id_node,"Undefined variable"); //Compatibilità degli schemi Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); Psymbol symbol = lookup(valname(id_node)); if (!type_equal((symbol->schema),*(schema_expr))) semerror(assign_stat_node,"Incompatible types"); //Genero il codice assign_stat_code = appcode(expr_code,makecode1(T_STO,symbol->oid)); #ifdef DEBUG_ASSIGN_STAT printf("ASSIGN_STAT - exit\n"); #endif return assign_stat_code; }
Code write_stat(Pnode p) { /* WRITE_STAT / / N_SPECIFIER --> expr / / [expr-filename] */ Value format; int op; Schema exprschema; Code code = expr(p->child->brother, &exprschema); if (p->child->child != NULL) { // Con specifier code = appcode(code, specifier(p->child)); op = T_FPRINT; } else { // Senza specifier op = T_PRINT; } format.sval = get_format(&exprschema); free_schema(exprschema.next); return concode( code, makecode1(op, format), endcode() ); }
/*Genera lo schema della tupla e ritorna il codice*/ Code tuple_const(Pnode tuple_const_node,Pschema schema){ //Non ci sono vincoli semantici #ifdef DEBUG_TUPLE_CONST printf( "TUPLE_CONST - enter\n"); #endif //Preparo il codice della tupla Code tuple_const_code; tuple_const_code.head = NULL; //Punto al primo elemento della tupla Pnode atomic_const_node = tuple_const_node->child; //Preparo la variabile che contiene il codice dell'id Code atomic_const_code; Pschema prev_schema = schema; do{ //Calcolo il codice e lo schema della prima costante switch(atomic_const_node->type){ case (N_INTCONST): atomic_const_code = makecode1(T_IATTR,qualifier(atomic_const_node)); prev_schema->type = INTEGER; break; case (N_BOOLCONST): atomic_const_code = makecode1(T_IATTR,qualifier(atomic_const_node)); prev_schema->type = BOOLEAN; break; case (N_STRCONST): atomic_const_code = make_sattr(valname(atomic_const_node)); prev_schema->type = STRING; break; } //Appendo il codice della costante al codice della tupla tuple_const_code = appcode(tuple_const_code,atomic_const_code); //Passo al fratello atomic_const_node = atomic_const_node->brother; //Creo un nuovo schema if (atomic_const_node!=NULL){ Pschema newSchema = (Pschema) newmem(sizeof(Schema)); prev_schema->next = newSchema; prev_schema = prev_schema->next; } }while(atomic_const_node!=NULL); #ifdef DEBUG_TUPLE_CONST printf( "TUPLE_CONST - exit\n"); #endif return tuple_const_code; }
Code make_get_fget(Operator op, int oid, char *format) { Code code; code = makecode1(op, oid); code.head->args[1].sval = format; return(code); }
Code makecode2(Operator op, Value arg1, Value arg2) { Code code; code = makecode1(op, arg1); code.head->args[1] = arg2; return code; }
Code makecode2(Operator op, int arg1, int arg2) { Code code; code = makecode1(op, arg1); code.head->args[1].ival = arg2; return(code); }
/*Controlla la semantica del nodo if e ne ritorna il codice*/ Code if_stat(Pnode if_stat_node){ #ifdef DEBUG_IF_STAT printf("IF_STAT - enter\n"); #endif //Imposto le tre parti del nodo Pnode expr_node = if_stat_node->child; Pnode then_node = if_stat_node->child->brother; Pnode else_node = if_stat_node->child->brother->brother; //Definisco la variabile che contiene il codice da ritornare Code if_stat_code ; //La generazione dell'ambiente viene fatta all'interno della funzione stat_list //Genero il codice di expr Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); //Controllo i vincoli semantici if (schema_expr->type!=BOOLEAN) semerror(expr_node,"Expected boolean type"); //Genero il codice di then_node Code then_code = stat_list(then_node); if (else_node==NULL){//if then endif //Calcolo l'offset int offset = then_code.size + 1; //Genero il codice di if_stat if_stat_code = concode(expr_code,makecode1(T_SKIPF,offset),then_code,endcode()); } else {//if then else //Genero il codice di else_node Code else_code = stat_list(else_node); //Calcolo gli offset int offset_then = then_code.size + 2; int offset_else = else_code.size + 1; //Genero il codice di if_stat if_stat_code = concode(expr_code,makecode1(T_SKIPF,offset_then),then_code,makecode1(T_SKIP,offset_else),else_code,endcode()); } #ifdef DEBUG_IF_STAT printf("IF_STAT - exit\n"); #endif return if_stat_code; }
Code make_get_fget(Operator op, int oid, char *format) { Code code; Value v1; v1.ival = oid; Value v2; v2.sval = format; code = makecode1(op, v1); code.head->args[1] = v2; return code; }
Code program(Pnode root) { Code body = stat_list(root->child); Value v1; v1.ival = body.size + 2; return concode(makecode1(T_TCODE, v1), body, makecode(T_HALT), endcode()); }
Code if_stat(Pnode p) { /* if / / expr ---> stat_list [---> stat_list] */ Schema exprschema; Code exprcode = expr(p->child, &exprschema); Code bodythen = stat_list(p->child->brother); // Vincoli semantici if (exprschema.type != BOOLEAN) semerror(p->child, "Boolean expression required"); if (p->child->brother->brother == NULL) { // IF-THEN Value v1; v1.ival = bodythen.size + 1; return concode(exprcode, makecode1(T_SKIPF, v1), bodythen, endcode()); } else { // IF-THEN-ELSE Code bodyelse = stat_list(p->child->brother->brother); Value v1; v1.ival = bodythen.size + 2; Value v2; v2.ival = bodyelse.size + 1; return concode(exprcode, makecode1(T_SKIPF, v1), bodythen, makecode1(T_SKIP, v2), bodyelse, endcode() ); } }
Code while_stat(Pnode p) { /* while / / expr ---> stat_list */ Schema exprschema; Code exprcode = expr(p->child, &exprschema); Code body = stat_list(p->child->brother); // Vincoli semantici if (exprschema.type != BOOLEAN) semerror(p->child, "Boolean expression required"); Value v1; v1.ival = body.size + 2; Value v2; v2.ival = -(exprcode.size + body.size + 1); return concode(exprcode, makecode1(T_SKIPF, v1), body, makecode1(T_SKIP, v2), endcode()); }
/*Genera il codice per il nodo stat_list e crea lo scope del programma*/ Code stat_list(Pnode stat_list_node){ //Definisco la variabile che contiene il codice da ritornare Code stat_list_code; stat_list_code.head = NULL; stat_list_code.tail = NULL; stat_list_code.size = 0; //Creo l'ambiente del programma push_environment(); //Punto al primo stat Pnode stat_node = stat_list_node->child; //Ciclo lungo tutti gli stat_node while (stat_node!=NULL){ //Creo il codice dello stat_node Code stat_code; switch (stat_node->type){ case(N_DEF_STAT): stat_code = def_stat(stat_node);break; case(N_ASSIGN_STAT): stat_code = assign_stat(stat_node);break; case(N_IF_STAT): stat_code = if_stat(stat_node);break; case(N_WHILE_STAT): stat_code = while_stat(stat_node);break; case(N_READ_STAT): stat_code = read_stat(stat_node);break; case(N_WRITE_STAT): stat_code = write_stat(stat_node);break; } //Appendo il codice a stat_list_code stat_list_code = appcode(stat_list_code,stat_code); //Punto al fratello successivo stat_node = stat_node->brother; } //Appendo il codice per fare il pop dell'environment a stat_list_code if(numobj_in_current_env()!=0) stat_list_code = appcode(stat_list_code,makecode1(T_POP,numobj_in_current_env())); //elimino l'ambiente creato (elimina già le variabili dall'ambiente) pop_environment(); return stat_list_code; }
/*Genera il codice per il nodo program*/ Code program(Pnode root){ Code body = stat_list(root->child); //Prende body, gli mette TCODE prima e THALT dopo. return concode(makecode1(T_TCODE, body.size + 2), body, makecode(T_HALT), endcode()); }
Code def_stat(Pnode p) { /* def_stat / / type ---> ID ---> ID */ int num_id = 0, op; Code c_temp, code_ret; Pname names; Pnode nodo_type = p->child; Pschema schema; switch (nodo_type->type) { case N_ATOMIC_TYPE: op = T_NEWATOM; break; case N_TABLE_TYPE: op = T_NEWTAB; break; default: noderror(p->child); } /* Operazioni comuni tra dati atomici e table */ // Carico la lista di ID delle variabili names = id_list(p->child->brother, &num_id); // Vincoli semantici if (repeated_names(names)) semerror(p, "Variable redeclaration"); // Controlliamo che nessuna variabile sia nell'environment Pname n; for (n = names; n != NULL; n = n->next) { if (name_in_environment(n->name)) semerror(p, "Variable redeclaration"); // Aggiungo la nuova variabile nell'environment insert_name_into_environment(n->name); } // Genero il codice per allocare ognuna delle variabili code_ret.head = NULL; for (n = names; n != NULL; n = n->next) { // Aggiungo il nome alla Symbol Table schema = type(nodo_type); schema->name = n->name; insert(schema); Value v1; v1.ival = get_size(schema); c_temp = makecode1(op, v1); code_ret = (code_ret.head == NULL ? c_temp : appcode(code_ret, c_temp)); } // Liberiamo la memoria free_name_list(names); return code_ret; }