Beispiel #1
0
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;
}
Beispiel #2
0
/*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;
}
Beispiel #3
0
/*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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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());
}
Beispiel #6
0
/*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;
}
Beispiel #7
0
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()
        );
}
Beispiel #8
0
/*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;
}
Beispiel #9
0
Code make_get_fget(Operator op, int oid, char *format)
{
    Code code;

    code = makecode1(op, oid);
    code.head->args[1].sval = format;
    return(code);
}
Beispiel #10
0
Code makecode2(Operator op, Value arg1, Value arg2)
{
    Code code;

    code = makecode1(op, arg1);
    code.head->args[1] = arg2;
    return code;
}
Beispiel #11
0
Code makecode2(Operator op, int arg1, int arg2)
{
    Code code;

    code = makecode1(op, arg1);
    code.head->args[1].ival = arg2;
    return(code);
}
Beispiel #12
0
/*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;
}
Beispiel #13
0
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;
}
Beispiel #14
0
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());
}
Beispiel #15
0
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()
            );
    }
}
Beispiel #16
0
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());
}
Beispiel #17
0
/*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;
}
Beispiel #18
0
/*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());
}
Beispiel #19
0
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;
}