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; }
/*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; }
/*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() ); }
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 read_stat(Pnode p) { Code result, specifiercode; int op; // Vincoli semantici Psymbol symbol = lookup(valname(p->child->brother)); if (symbol == NULL) semerror(p->child, "Unknown identifier"); if (p->child->child != NULL) { // Con specifier op = T_FGET; specifiercode = specifier(p->child); } else { op = T_GET; } Value v1; v1.ival = symbol->oid; Value v2; v2.sval = get_format(symbol->schema); result = makecode2(op, v1, v2); if (op == T_GET) return result; else return appcode(specifiercode, result); }
bool CBDS::startApp(const QString &filename, const QVariant &settings) { QFile f(filename); if (f.open(QIODevice::ReadOnly)) { QString appcode(f.readAll()); f.close(); m_cbo->reset(); m_lastdraw = QVariantMap(); m_engine.collectGarbage(); if (settings.isValid()) m_cbo->setSettings(m_engine.toScriptValue(settings)); engageDebugger(); if (!m_engine.evaluate(appcode, QFileInfo(filename).fileName()).isError()) { if (m_clearchatonstart) m_chat.clear(); m_chat.addLine(new ChatLine(QFileInfo(filename).baseName() + " app has started.")); m_cbo->drawPanel(); return true; } else return false; } emit error("Can't open file: " + filename); return false; }
QVariant CBDS::getSettingsFromScript(const QString &filename) { QFile f(filename); if (f.open(QIODevice::ReadOnly)) { QString appcode(f.readAll()); f.close(); QScriptSyntaxCheckResult res = m_engine.checkSyntax(appcode); if (res.state() != QScriptSyntaxCheckResult::Valid) { emit error(QString("SyntaxCheck Failed: Line: %1 Column: %2: %3").arg(res.errorLineNumber()).arg(res.errorColumnNumber()).arg(res.errorMessage())); return QVariant(); } QScriptContext *ctx = m_engine.pushContext(); CBJSObject js; CBObjectBase cbo(&m_engine, m_roomowner); ctx->activationObject().setProperty("cb", m_engine.newQObject(&cbo)); ctx->activationObject().setProperty("cbjs", m_engine.newQObject(&js)); QScriptValue ret = m_engine.evaluate(appcode, QFileInfo(filename).fileName()); if (ret.isError()) { emit error(ret.toString()); m_engine.popContext(); return QVariant(); } m_engine.popContext(); return cbo.getSettingsChoices().toVariant(); } emit error("Can't open file: " + filename); return QVariant(); }
Code concode(Code code1, Code code2, ...) { Code rescode = code1, *pcode = &code2; while (pcode->head != NULL) { rescode = appcode(rescode, *pcode); pcode++; } return rescode; }
/*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 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; }
/*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; }
/*Controlla la semantica della read e ritorna il codice della read*/ Code read_stat(Pnode read_stat_node){ #ifdef DEBUG_READ_STAT printf("READ_STAT - enter\n"); #endif //Imposto le due parti del nodo Pnode specifier_node = read_stat_node->child; Pnode id_node = read_stat_node->child->brother; //Definisco il codice del nodo Code read_stat_code; read_stat_code.head = NULL; //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(read_stat_node,"Expected string type"); //Controllo che il nome dell'id sia visibile if (lookup(valname(id_node))==NULL) semerror(id_node,"Variable not defined"); //Genero il codice di readstat //La sintassi della read dipende dalla presenza dello specifier Psymbol symbol = lookup(valname(id_node)); if (specifier_node->child == NULL) read_stat_code = make_get_fget(T_GET,symbol->oid,get_format((symbol->schema))); else read_stat_code = appcode(specifier_code,make_get_fget(T_FGET,symbol->oid,get_format((symbol->schema)))); #ifdef DEBUG_READ_STAT printf("READ_STAT - exit\n"); #endif return read_stat_code; }
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; }