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; }
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() ); }
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()); }
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() ); } }
/*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 stat(Pnode p) { switch (p->type) { case N_DEF_STAT: return def_stat(p); case N_ASSIGN_STAT: return assign_stat(p); case N_IF_STAT: return if_stat(p); case N_WHILE_STAT: return while_stat(p); case N_READ_STAT: return read_stat(p); case N_WRITE_STAT: return write_stat(p); default: noderror(p); } return 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()); }
/*Controlla la semantica della write e ne ritorna il codice*/ Code write_stat(Pnode write_stat_node){ //Imposto le due parti del nodo Pnode specifier_node = write_stat_node->child; Pnode expr_node = write_stat_node->child->brother; //Definisco la variabile che contiene il codice da ritornare Code write_stat_code; //Calcolo il codice di specifier Pschema schema_specifier = (Pschema) newmem(sizeof(Schema)); Code specifier_code = specifier(specifier_node,schema_specifier); //Controllo che non ci siano errori semantici //Controllo che il tipo di specifier sia corretto if (schema_specifier->type != STRING && schema_specifier->type != NIHIL) semerror(write_stat_node,"Expected string type"); //Genero il codice di write_stat //Genero il codice di expr Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); //La sintassi della write dipende dalla presenza dello specifier if (specifier_node->child == NULL) write_stat_code = appcode(expr_code,make_print_fprint(T_PRINT,get_format(*schema_expr))); else write_stat_code = concode(expr_code,specifier_code,make_print_fprint(T_FPRINT,get_format(*schema_expr)),endcode()); return write_stat_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()); }
/*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; }