diff --git a/Makefile b/Makefile index 08c392d..6827d7f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ all: - bison -d src/tdsrpl.y -b src/tdsrpl - flex -o src/lex.yy.c src/tdsrpl.l - gcc src/main.c src/tdsrpl.tab.c src/lex.yy.c src/Interpreter.c src/datastructures/Node.c src/textManager.c src/langmodules/Object.c src/datastructures/STable.c src/datastructures/HeaderSmv.c src/PreProcess.c src/PostProcess.c -o tds - ./tds sample/basic-main/basic.tds sample/merger-fifo/nuxmv.smv + bison -d src/flex-bison/tdsrpl.y -b src/flex-bison/tdsrpl + flex -o src/flex-bison/lex.yy.c src/flex-bison/tdsrpl.l + gcc src/datastructures/Node.c src/flex-bison/tdsrpl.tab.c src/flex-bison/lex.yy.c src/util/Hash.c src/util/textManager.c src/langmodules/TypeMinMax.c src/langmodules/TypeSet.c src/langmodules/Object.c src/langmodules/TDS.c src/datastructures/STable.c src/datastructures/HeaderSmv.c src/EnvController.c src/PreProcess.c src/PostProcess.c src/Visitor.c src/langmodules/LangCore.c src/Interpreter.c src/main.c -o tds \ No newline at end of file diff --git a/execution-scripts/execution-profiles/profiles b/execution-scripts/execution-profiles/profiles new file mode 100644 index 0000000..6636e09 --- /dev/null +++ b/execution-scripts/execution-profiles/profiles @@ -0,0 +1,12 @@ +merger-fifo: + +./tds -int sample/merger-fifo/merger-fifo.tds sample/merger-fifo/nuxmv2.smv + + +filter-inte: + +./tds -int sample/filter/filter.tds sample/filter/nuxmv.smv + +sequenciador: + +./tds -int sample/sequenciador/seq.tds sample/sequenciador/seq.smv diff --git a/generatelexer.sh b/execution-scripts/flex-bison/generatelexer.sh similarity index 100% rename from generatelexer.sh rename to execution-scripts/flex-bison/generatelexer.sh diff --git a/execution-scripts/flex-bison/generateparsing.sh b/execution-scripts/flex-bison/generateparsing.sh new file mode 100755 index 0000000..d909bd6 --- /dev/null +++ b/execution-scripts/flex-bison/generateparsing.sh @@ -0,0 +1,2 @@ +bison -d src/flex-bison/tdsrpl.y -b src/flex-bison/tdsrpl +flex -o src/flex-bison/lex.yy.c src/flex-bison/tdsrpl.l diff --git a/generateparsing.sh b/generateparsing.sh deleted file mode 100755 index 48d7ee3..0000000 --- a/generateparsing.sh +++ /dev/null @@ -1,4 +0,0 @@ -bison -d tdsrpl.y -flex tdsrpl.l -gcc tdsrpl.tab.c lex.yy.c datastructures/Node.c datastructures/constants.c -o tdsPARSING -./tdsPARSING ../sample/merger.tdsrpl > PARSINGOUTPUT \ No newline at end of file diff --git a/headers/Enum.h b/headers/Enum.h index 7363340..d3b7ebe 100644 --- a/headers/Enum.h +++ b/headers/Enum.h @@ -6,14 +6,14 @@ typedef enum SCOPE_TYPE { GLOBAL, FUNC, LOOP, IF_BLOCK, ELSE_BLOCK, SMV_PORTS, SMV_V_MAIN, SIMPLE_HASH} SCOPE_TYPE; -typedef enum ENTRY_TYPE {NUMBER_ENTRY, LOGICAL_ENTRY, LABEL_ENTRY ,T_DIRECTIVE_ENTRY, TDS_ENTRY, NULL_ENTRY, FUNCTION_ENTRY, WRITE_SMV_INFO ,TYPE_SET } ENTRY_TYPE; +typedef enum ENTRY_TYPE {NUMBER_ENTRY, LOGICAL_ENTRY, LABEL_ENTRY ,T_DIRECTIVE_ENTRY, TDS_ENTRY, NULL_ENTRY, TIME_COMPONENT, FUNCTION_ENTRY, WRITE_SMV_INFO ,TYPE_SET } object_type; // permitir lista de tipos diferentes? permitir lista de TDS's? // comentado por enquanto, devemos decidir oque fazer sobre os enums do node typedef enum smvtype {MAIN = 1, AUTOMATA = 2, PORTS = 3, FUNCTION_SMV = 4} smvtype; - +typedef enum TDS_TYPE {DATA_LIST, MATH_EXPRESSION, FUNCTION_APPLY, TDS_DEPEN} TDS_TYPE; //separar enums por: OPERAÇÃO UNÁRIA, OPERAÇÃO BINÁRIA, OPERAÇÃO ATRIBUIÇÃO, DADOS, @@ -32,29 +32,34 @@ typedef enum EVAL_TYPE { NUMBER, L_BOOL, STRING, D_NULL, IDVAR, TIME_DIRECTIVE, - DATA_V, PARAMS_CALL, DEFINE_INTERVAL, + DATA_V, PARAMS_CALL, PARAMS, DEFINE_INTERVAL, + + AC_V, ASSIGN_TDIRECTIVE ,OTHER_ASSIGN, V_PROP, ADD_V, ADD_V_PROP, V_PROP_TDS, - AC_V, OTHER_ASSIGN, V_PROP, ADD_V, ADD_V_PROP, V_PROP_TDS, + EXPR, MINUS_EXPR, PLUS_EXPR, MULTI_EXPR, DIV_EXPR, LE_EXPR, GE_EXPR, LT_EXPR, GT_EXPR, EQUAL_EXPR, NEQUAL_EXPR, + NOT_EXPR, AND_EXPR, OR_EXPR, IMP_EXPR, BIMP_EXPR, PRI_EXPR, - EXPR, CMD_IF, TDS_DEF_COMPLETE, TD_DEF_DEPEN, + CMD_IF, TDS_DEF_COMPLETE, TDS_DEF_DEPEN, CMD_TDS_ANON, - TIME_LIST, TIME_COMP, DOMAIN_FUNCTION, + LIST_ITERATOR, TIME_COMP, V_PROP_TDS_VALUE, DOMAIN_FUNCTION, MATCH_IF, - ASSIGN_IDVAR, ASSIGN_AC_V, ASSIGN_TDIRECTIVE, + ASSIGN_IDVAR, ASSIGN_AC_V, - DEF_EXTRAS_LINKED, DEF_EXTRAS_DELAYED, + DEF_EXTRAS_LINKED, DEF_EXTRAS_DELAYED, DEF_EXTRAS_FILTER, HEADERS_E_PROG, PROG, FUNC_DEFS, CMD, - FUNC_DEF, PROC_DEF, OPT_RETURN, PARAMS, PARAM, + FUNC_DEF, PROC_DEF, OPT_RETURN, PARAM, CMD_OTHER, - CMD_TDS_ANON, TDS_ANON_OP_PASS, TDS_ANON_OP_DPASS, + TDS_ANON_OP_PASS, TDS_ANON_OP_DPASS, TDS_ANON_OP_FPASS, + + OTHER_LOOP, FUNC_CALL, PROC_CALL, - OTHER_LOOP, FUNC_CALL, PROC_CALL + SHOW_PRINT } EVAL_TYPE; diff --git a/headers/EnvController.h b/headers/EnvController.h new file mode 100644 index 0000000..379abbe --- /dev/null +++ b/headers/EnvController.h @@ -0,0 +1,190 @@ +// Created by mateus on 22/03/2021. +// + +#ifndef TDSREPLANGUAGE_ENVCONTROLLER_H +#define TDSREPLANGUAGE_ENVCONTROLLER_H + +#include "Enum.h" +#include "STable.h" +#include "textManager.h" +#include "HeaderSmv.h" +#include "TDS.h" +#include "TypeSet.h" +#include "TypeMinMax.h" + +#define TYPE_SET_DIR_SIZE 9999 +#define DEFAULT_HEADERS_AUX_SIZE 100 + + + +typedef struct envcontroller +{ + // info + HeaderSmv* MAIN; + HeaderSmv** AUTOMATA_RELATED; + HeaderSmv** PORTS_RELATED; // ports module e as tds (vão ter referência para esse header na sua declaração, assim como tabela auxiliar) + HeaderSmv** FUNCTIONS; // as funções usadas por main e tds (vão ter referência para seu header na sua declaração, assim como tabela auxiliar) + + int H_FUNCTION_CURRENT_SIZE; + int H_AUTOMATA_CURRENT_SIZE; + int H_PORTS_CURRENT_SIZE; + int PORTS_INFO_CURRENT_SIZE; + + STable* mainInfo; // tabela de simbolos auxiliar para main + STable** portsInfo; // para cada tds (talvez não va precisar, a lógica vai estar TODA nas funções ou nele mesmo (de maneira constante) + STable** functionsInfo; // para cada função + + char** typeSetWords; // dict para "otmização" + + //contexto tds + TDS** declaredPorts; + TDS* currentTDScontext; + + + + // validação + STable* originalPorts; + int expectedPorts; + int validPorts; + // ai ele verifica se foram usadas (não tem declarações de funções) + int declaredPortsNumber; + // avisa caso não tenha nenhuma TDS linkada uma com a outra + int IO_RELATION; + // avisa caso uma porta tenha tido declaração repetida + int multiPortDeclartion; + + // validações para o filter e recuperar o header correto + int modelHasFilter; + int* automatasToChange; + int filterContext; + int F_AUTOMATAS_CHANGE_POINTER; + int modelHasFinalAutomata; + int filterUsed; + int relationRef; + + // interactive + int interactiveMode; + +}EnvController; + + +EnvController *createController(int enableInteractive); + +/** + * Libera o controlador e todas as estruturas armazenadas por ele + * @SideEffects: Chama o liberar dos headers e tabelas de simbolos + * */ +void letGoHeaderControl(EnvController* Hcontrol); + +/** + * Printa todas os headers armazenados pelo controlador + * */ +void printAllHeaders(EnvController* Hcontrol); + +/** +* Considerando a refatoração do controller e header, encapsulamos o header apropriado pela estrutura, e esse deve +* ser recuperado usando o enum de smvtype e o indice. +* +* Caso o indice não seja informado o último header salvo (tanto do agrupamento main, automato, ou ports) é retornado +* Esse comportamento é usado pelo pré processamento, considerando que cada agrupamento é consultado para verificar o + * progresso de algumas alterações (ex: trocar FROZENVAR de portsModule), e otimizações da leitura +* +* @param controller o controlador de headers +* @param cat o tipo smv de parte de intesse (main, automato/modulo generico, ports) +* @param indexOfHeader a ordem de headers de cada parte de interesse (ex: 0 = portsModule, 1: função1 associada a tds) +* +* @returns o header apropriado com a parte de interesse do arquivo SMV +* */ +HeaderSmv* accessHeader(EnvController* controller, smvtype cat, int indexOfHeader); + +/** + * Considerando a refatoração do controller e header, encapsulamos as tabelas de simbolo auxiliares (SMV_INFO) + * ser recuperado usando o enum de smvtype. + * + * @param controller o controlador de headers + * @param cat o tipo smv de parte de intesse (main, automato/modulo generico, funções) + * @param SMV_INFO_ID o identificador daquela tabela auxiliar (usado atualmente só para as funções) + * @returns a tabela de simbolos SMV_INFO apropriada + * */ +STable* accessSmvInfo(EnvController* controller, smvtype cat, int SMV_INFO_ID); + +/** + * Adiciona um novo header ao controller encapsulando suas operações e categorizando apropriadamente + * @param o controller + * @param o novo header retornado por createHeader + */ +void addNewHeader(EnvController* controller, HeaderSmv* newHeader); + +/** + * Adiciona uma nova tabela de simbolos auxiliar ao controller encapsulando suas operações e categorizando apropriadamente + * @param o controller + * @param a nova tabela de simbolos auxiliar retornada por retornado por createTable + */ +void addNewAuxInfo(EnvController* controller, STable* newTableInfo); + +/** + * Valida a declaração de uma TDS, vendo se os nomes bateram com os que vieram do modelo de input. + * @param declarationName o nome da declaração da TDS + * @param controller o controlador + */ +void validateTdsDeclaration(char* declarationName, EnvController* controller); + +/** + * Propaga um parâmetro para o mpodulo de uma TDS recuperando os headers apropriados dessa. + * @param controller o controlador de ambiente + * @param param o identificador do parametro + * @param currentTDS a tds recuperada da interpretação + */ +void addParamToTdsDeclaration(EnvController* controller, char* param, TDS* currentTDS); + +/** + * Tendo um controller com o contexto e associação Header e AuxTable, + * adiciona um parâmetro (se necessário) para o header do módulo da TDS. + * Também propaga as dependências relacionadas a esse parâmetro para o portsModule + * @param controller o controlador de ambiente + * @param param o bind daquele parâmetro + * @param currentTDS a TDS corrente + * @SideEffects: Aloca uma string nova, caso esse parâmetro já não tenha sido memoizado + */ +void addParamToTds(EnvController* controller, char* param, TDS* currentTDS); + +/** + * Adiciona um novo parâmetro a portModule, e resolve as depêndencias nos demais módulos main e automato. + * @param o controller + * @param o novo parâmetro + * @SideEffects: Para cada módulo (main, automato ...) é atualizada a linha com depdência a ports e essa operação chama + * o módulo textManager e seus método addParams, criando uma string nova e liberando a antiga + */ +void addParamToPortsModule(EnvController *controller, char *param); + +/** + * Recupera uma palavra do dicionário de type-set do ambiente. + * @param word uma palavra já utilizada anteriomente em um type-set + * @param controller o controlador de ambiente + * @return um ponteiro para a palavra, ou NULL caso essa não exista + */ +char* getTypeSetWordFromDict(char* wordRef, EnvController* controller); + +/** + * Adiciona uma palavra ao dicionário de type-set do ambiente + * @param word a palavra nova + * @param controller o controlador + * @SideEffects: Aloca uma string nova de tamanho da word +1 (deve ser liberada no final do programa) + */ +void addTypeSetWordToDict(char* word, EnvController* controller); + +/** + * Atualizaa os parâmetros de todos os automatos que possam ter condição de filtro. E propaga os parâmetros + * @param controller o controlador + * @param paramName o parâmetro + */ +void addParamToAutomatasFilter(EnvController* controller, char* paramName); + +/** + * Realiza diversas validações de contexto. + * @param controller o controller que contem todas as informações de necessárias + */ +void validateAfterInterPost(EnvController* controller); + + +#endif //TDSREPLANGUAGE_ENVCONTROLLER_H \ No newline at end of file diff --git a/headers/Hash.h b/headers/Hash.h new file mode 100644 index 0000000..31397b1 --- /dev/null +++ b/headers/Hash.h @@ -0,0 +1,12 @@ +// +// Created by mateus on 13/03/2021. +// + +#ifndef TDSREPLANGUAGE_HASH_H +#define TDSREPLANGUAGE_HASH_H + +#define MAX_SIMPLE 903 + +int hash(char* str, int SIZE_ED); + +#endif //TDSREPLANGUAGE_HASH_H diff --git a/headers/HeaderSmv.h b/headers/HeaderSmv.h index 848923a..cb04a1b 100644 --- a/headers/HeaderSmv.h +++ b/headers/HeaderSmv.h @@ -3,8 +3,11 @@ #define HEADER_H #include "Enum.h" -#include "STable.h" #include "textManager.h" +#include "Hash.h" +#include + +#define MAX_PARAM 301 typedef enum headerpart {CREATE_MODULE = -1, VAR = 0, ASSIGN = 1, TRANS = 2} headerpart; @@ -12,52 +15,39 @@ typedef struct headersmv { smvtype type; char* moduleName; - char** varBuffer; // poderia transormar em uma tabela hash(facilidade em achar a variavel, mas acredito que uma vez escrito aqui não vai ter alteração!) + char** varBuffer; // poderia transormar em uma tabela calculateHashPos(facilidade em achar a variavel, mas acredito que uma vez escrito aqui não vai ter alteração!) char** transBuffer; // vai ser inalterado durante a execução (só no pré processamento, ou seja já é criado preeenchido) - char** assignBuffer; // aqui a ordem é importante não pode ser uma tabela hash + char** assignBuffer; // aqui a ordem é importante não pode ser uma tabela calculateHashPos int VAR_POINTER; int TRANS_POINTER; int ASSIGN_POINTER; int VAR_RENAME_POINTER; // aponta para a referência a portsModule que vai ser passada para os demais módulos (e será centralizada no main agora) + int* PARAM_MAP; + int expectFilter; + int* filterPosNeg; + int* filterPosCond; }HeaderSmv; -HeaderSmv* createHeader(int type, char* moduleName, int varP, int assignP, int transP); - -void letgoHeader(HeaderSmv* h); - - -typedef struct headerController -{ - HeaderSmv* MAIN; - HeaderSmv** AUTOMATA_RELATED; - HeaderSmv** PORTS_RELATED; // ports module e as tds (vão ter referência para esse header na sua declaração, assim como tabela auxiliar) - HeaderSmv** FUNCTIONS; // as funções usadas por main e tds (vão ter referência para seu header na sua declaração, assim como tabela auxiliar) - - int H_FUNCTION_CURRENT_SIZE; - int H_AUTOMATA_CURRENT_SIZE; - int H_PORTS_CURRENT_SIZE; - - STable* mainInfo; // tabela de simbolos auxiliar para main - //STable** portsInfo; // para cada tds (talvez não va precisar, a lógica vai estar TODA nas funções ou nele mesmo (de maneira constante) - STable** functionsInfo; // para cada função - - STable* originalPorts; // tabela de simbolos auxiliar para ports (necessária?) (só vai ter o módulo de cada porta) (pode ser na verdade para as portas declaradas) - int expectedPorts; - // ai ele verifica se foram usadas (não tem declarações de funções) - int declaredPorts; - - -}HeaderController; +/** + * Cria um Header de módulo que será escrito depois no arquivo SMV. Dependendo do tipo do header a ser escrito, + * ele terá o nome do módulo passado com alguma alteração de parâmetro. + * {MAIN = 1, AUTOMATA = 2, PORTS = 3, FUNCTION_SMV = 4}, onde para qualquer um exceto o main ele adiciona um parametro time ao modulo + * @param type o tipo do header + * @param moduleName o nome padrão do módulo da forma: MODULE %s\n + * @param varP o ponteiro de controle para a parte var + * @param assignP o ponteiro de controle para a parte assign + * @param transP o ponteiro de controle para a parte trans + * @param finalAutomataFilterModel usado para otimizar a verificação na hora que um automato filter é criado + * @return O novo Header do novo módulo + * @SideEffects: Aloaca um header que deve ser liberado como responsabilidade do chamador + */ +HeaderSmv * createHeader(enum smvtype type, char *moduleName, int varP, int assignP, int transP, int finalAutomataFilterModel); -HeaderController *createController(); +void letgoHeader(HeaderSmv* h); -/** - * Libera o controlador e todas as estruturas armazenadas por ele - * @SideEffects: Chama o liberar dos headers e tabelas de simbolos - * */ -void letGoHeaderControl(HeaderController* Hcontrol); +void letGoRelatedHeaders(HeaderSmv** RHeader, int size); /** * Printa cada componente: VAR, ASSIGN, TRANS de um módulo SMV @@ -69,60 +59,47 @@ void printHeaderBuffer(HeaderSmv* h, int type, char* typeString); * */ void printHeader(HeaderSmv* h); -/** - * Printa todas os headers armazenados pelo controlador - * */ -void printAllHeaders(HeaderController* Hcontrol); - void writeHeaderBuffer(HeaderSmv* h, int part, FILE* smvoutput); void writeHeader(HeaderSmv* header, FILE* smvoutput); -void writeHeaderBuffer(HeaderSmv* h, int part, FILE* smvoutput); - -void writeHeader(HeaderSmv* header, FILE* smvoutput); +/* + escolhe um buffer do header atual para salvar a linha (alocando sempre uma string para essa linha, que depois deve ser liberada). + efeitos colaterais: * ao ter readVarPortsModule como true, ele salva as variáveis do portsModule em uma tabela de portas + * ao ter controlRename como true, ele remove todas as ocorrências de determinados caracteres (no caso []) -/** -* Considerando a refatoração do controller e header, encapsulamos o header apropriado pela estrutura, e esse deve -* ser recuperado usando o enum de smvtype e o indice. -* -* Caso o indice não seja informado o último header salvo (tanto do agrupamento main, automato, ou ports) é retornado -* Esse comportamento é usado pelo pré processamento, considerando que cada agrupamento é consultado para verificar o - * progresso de algumas alterações (ex: trocar FROZENVAR de portsModule), e otimizações da leitura -* -* @param controller o controlador de headers -* @param cat o tipo smv de parte de intesse (main, automato/modulo generico, ports) -* @param indexOfHeader a ordem de headers de cada parte de interesse (ex: 0 = portsModule, 1: função1 associada a tds) -* -* @returns o header apropriado com a parte de interesse do arquivo SMV -* */ -HeaderSmv* accessHeader(HeaderController* controller, smvtype cat, int indexOfHeader); +*/ +void selectBuffer(headerpart part, char* line, HeaderSmv* header, int controlRename); /** - * Considerando a refatoração do controller e header, encapsulamos as tabelas de simbolo auxiliares (SMV_INFO) - * ser recuperado usando o enum de smvtype. - * - * @param controller o controlador de headers - * @param cat o tipo smv de parte de intesse (main, automato/modulo generico, funções) - * @param SMV_INFO_ID o identificador daquela tabela auxiliar (usado atualmente só para as funções) - * @returns a tabela de simbolos SMV_INFO apropriada - * */ -STable* accessSmvInfo(HeaderController* controller, smvtype cat, int SMV_INFO_ID); + * Atualiza uma transição do automáto com a condição de filtro apropriada + * @param cond a condição + * @param automata o header do automato + * @param type o tipo de transição (negativa ou não negativa) + * @SideEffects: Altera a string dessa transição, e caso o tamanho seja suficientemente grande, ocorre realloc + * já que usa o updateString intervals + */ +void updateAutomataFilterCond(const char *cond, const HeaderSmv *automata, int type); /** - * Adiciona um novo header ao controller encapsulando suas operações e categorizando apropriadamente - * @param o controller - * @param o novo header retornado por createHeader + * Adiciona parâmetro para módulo qualquer do nuXmv. + * @param controller o controlador de ambiente e contexto + * @param param a string do parâmetro + * @param cat a categoria do header/tabela auxuliar a ser recuperada + * @param indexOfHeader o indice do header + * @return 1 se a operação foi realizada com sucesso (isto é foi necessária) + * ou 0 caso a operação não tenha sido realizada (o módulo já possui o parâmetro) + * @SideEffects: Aloca uma string nova e libera a antiga */ -void addNewHeader(HeaderController* controller, HeaderSmv* newHeader); +int addParamToModule(HeaderSmv* updated , char* param); /** - * Adiciona um novo parâmetro a portModule, e resolve as depêndencias nos demais módulos main e automato. - * @param o controller - * @param o novo parâmetro - * @SideEffects: Para cada módulo (main, automato ...) é atualizada a linha com depdência a ports e essa operação chama - * o módulo textManager e seus método addParams, criando uma string nova e liberando a antiga + * Dado um header que tenha um ponto de interesse de mudança em VAR, altera esse valor + * @param header o header corrente + * @param paramName a string do parâmetro + * @param offSetPointer o offset do buffer caso seja necessário + * @SideEffects: Altera o buffer nessa posição, e consequentemente aloca uma nova string liberando a antiga. */ -void addParamToPortsModule(HeaderController *controller, char *param, int first); +void addParamInterestPointHeader(HeaderSmv* header, char *paramName, int offSetPointer); #endif diff --git a/headers/Interpreter.h b/headers/Interpreter.h index 56cb31d..670c5fc 100644 --- a/headers/Interpreter.h +++ b/headers/Interpreter.h @@ -6,26 +6,18 @@ #define INTERP_H -#include "textManager.h" -#include "HeaderSmv.h" -#include "STable.h" -#include "Node.h" -#include "Object.h" - -Object *eval(Node *n, STable *scope, HeaderController *controllerSmv); - -// usar depois para criar executores genericos -// caso a gente queira simplificar os parâmetros (note que muitos são desnecessários em alguns evals (MELHORIA)) -//typedef Object* (*generic_fp)(void); -/* - * generic_fp executores[80] = { - (generic_fp ) evalNUM, (generic_fp ) evalBOOL, (generic_fp ) evalSTRING, (generic_fp ) evalNULL, (generic_fp ) evalIDVAR, (generic_fp ) evalTIME_DIRECTIVE, - (generic_fp ) evalDataV, (generic_fp ) evalPARAMS_CALL, (generic_fp ) evalDEFINE_INTERVAL , (generic_fp ) evalAC_V, - (generic_fp ) evalOTHER_ASSIGN, (generic_fp ) evalV_PROP, (generic_fp ) evalADD_V, (generic_fp ) evalADD_V_PROP, (generic_fp ) evalV_PROP_TDS, (generic_fp ) evalEXPR, (generic_fp ) - (generic_fp ) evalCMD_IF, (generic_fp ) evalMATCH_IF -}; - * */ - +#include "LangCore.h" + +typedef enum MAP_OP { PLUS = 43, MINUS = 45, TIMES = 42, DIVIDE = 47, MOD = 37, LT = 60, GT = 62, NOTEQUAL = 94, NOT_PREFIX = 110, + LE = 121, EQUAL = 122, GE = 123} MAP_OP; + +/** + * Inicia o processo de interpretação. E ao final commita todos os instantes restantes para uma TDS. + * @param n o nó raiz da AST + * @param scope o escopo GLOBAL + * @param controller o controlador de ambiente + */ +void startInterpreter(Node* n, STable* scope, EnvController* controller); #endif diff --git a/headers/LangCore.h b/headers/LangCore.h new file mode 100644 index 0000000..9156f29 --- /dev/null +++ b/headers/LangCore.h @@ -0,0 +1,139 @@ +// +// Created by mateus on 20/04/2021. +// + +#ifndef TDSREPLANGUAGE_LANGCORE_H +#define TDSREPLANGUAGE_LANGCORE_H + +#include "Visitor.h" + + +//#define DEFAULT_MEMOI 300 + + +//Object** MEMOI; + + +/* + * FUNÇÕES AUXILIARES + */ + +STable* selectSMV_SCOPE(STable* scope, EnvController* controllerSmv); + +HeaderSmv * selectSMV_INFO(STable* scope, Object* functionPointer, EnvController* controllerSmv); +// avaliar a importancia dos métodos acima, e se possível movimentar eles para o HeaderSmv.c ou para um Novo Controller.h + +/** + * Resolve a dependencia de todas as TDS's linkadas a TDS corrente durante a avaliação lazy + * @param currentTDS a TDS corrente + * @param controllerSmv o controller usado para atualizar o type-set das TDS's dependentes. + * @param scope a tabela de simbolos do escopo corrente + * @param I_TIME para validar o instante ao criar init e next + * @param C_TIME para indexar o data-time correto + */ +void resolveDependencies(TDS* currentTDS, STable* scope, EnvController* controllerSmv, int I_TIME, int C_TIME); + +/** + * Resolve a avaliação lazy das TDS's pendentes após uma mudança de contexto temporal. E salva seus dados para Memoization. + * @param currentScope o escopo atual + * @param controllerSmv o controlador de ambiente + * @param C_TIME o contexto temporal atual + */ +void resolveTdsLazyEvaluation(STable *currentScope, EnvController *controllerSmv, int C_TIME); + +// CASO FORA DE FLUXO 1: e se ele "pular", ex: commitar c_time = 2 (quando era 0 antes), ele pulou o 1! A gente deve ver a "diferença" +// CHAMAR ESSA FUNÇÃO DIFERENÇA VEZES. +// CASO FORA DE FLUXO 2: deve chamar isso também ao FIM DO PROGRAMA (para cada CHAMADA RESTANTE, ex: C_TIME terminou em 4, deve chamar até F_TIME (5, ... , F_TIME). +// DIFERENÇA VEZES DE NOVO! +void commitCurrentTime(STable* currentScope, EnvController* controllerSmv, int changedTo); + +/** + * Real as operaçoes basicas envolvidas em quaisquer declaraçoes de TDS's. Dentre elas, alocaçao da estrutura, + * consulta das diretivas temporais, sintetização de binds e, se necessário, resolução de dependências. + * @param pathForDepen o path para se resolver uma dependência, isto é o dos nós mais abaixo da AST + * @param portName o nome da porta + * @param type o tipo da TDS para enumeraçao + * @param tdsSpec o objeto que representa a especificaçao da TDS + * @param delayed o parametro delayed de uma TDS + * @param scope o scopo corrente + * @param pathForCond o caminho para recuperar a condição a ser avaliada para essa TDS + * @param controller o controlador de ambiente + * @return um objeto sintetizado com a TDS criada. + * @SideEffects: Aloca uma TDS, e posições no vetor de dependências de uma TDS se for necessário + */ +Object *computeTDSBasicOperations(Node *pathForDepen, char *portName, TDS_TYPE type, Object *tdsSpec, int delayed, STable *scope, Node *pathForCond, EnvController *controller); + + +/** + * + * @param n o nó passado para resolução de dependências + * @param portName o nome da porta da tds + * @param scope o escopo corrente + * @param newTDS a nova TDS + * @param controller o controlador de ambiente + * @param I_TIME a diretiva de tempo inicial + * @param C_TIME a diretiva de tempo corrente + * @return a TDS com as dependencias computadas + * @SideEffects: Aloca e posições no vetor de dependências de uma TDS se for necessário + */ +void computeTDSDependentOperations(Node*n, char* portName, STable* scope, TDS* newTDS, EnvController* controller, int I_TIME, int C_TIME); + + +/** + * Realiza a negação de uma expressão (object) + * @param o a expressão object + * @return um objeto que encapsula true ou false + * @Validation: Caso o object não seja booleano dispara erro. + */ +Object * notObjectOperation(Object* o); + +/** + * Realiza a comparação entre dois objetos + * @param o1 o primeiro operando + * @param o2 o segundo operando + * @param op diferencia se é diferente de e igual a + * @return um objeto que encapsula true ou false + * @Validation: Caso os objetos sejam de tipos diferentes dispara erro. + */ +int comparator(Object* o1, Object* o2, char* op); + +/** + * Implementa implicação lógica + * @param a primeiro predicado + * @param b segundo predicado + * @return um resultado 0 ou 1 + */ +_Bool IMP(_Bool a, _Bool b); + +/** + * Implementa biimplicação lógica + * @param a primeiro predicado + * @param b segundo predicado + * @return um resultado 0 ou 1 + */ +_Bool BIMP(_Bool a, _Bool b); + + +/** + * Método auxiliar para tratar atualização de valores de variáveis, incluindo de NULL e listas + * @param varName o nome da variável + * @param var o objeto referência da variável + * @param expr o objeto referência da expressão (que será atirbuida a var) + * @param scope o escopo atual + * @param index o indice o qual a atribuição é feita caso seja uma lista + * @param C_TIME a diretiva C_TIME + * @SideEffects: Atualiza o valor de uma entrada na tabela de simbolos + */ +void updateVariable(char* varName, Object *var, Object *expr, STable* scope, int index, int C_TIME); + +/** + * Considerando as limitações de enums simbolicos do nuXmv, + * enquanto o modelo gerado utilizar esse tipo de dado essa validação deve ser utilizada para + * qualquer operação diferente de != e ==. Abortando a interpretação. + * @param o1 objeto sintetizado em uma operação + * @param o2 outro objeto sintetizado em uma operação + * + */ +void validateOpsTdsValue(Object* o1, Object* o2); + +#endif //TDSREPLANGUAGE_LANGCORE_H diff --git a/headers/Object.h b/headers/Object.h index fe28af5..bc26d7b 100644 --- a/headers/Object.h +++ b/headers/Object.h @@ -3,23 +3,51 @@ #define OBJECT_H #include "Enum.h" +#include "TypeMinMax.h" +#include "TypeSet.h" // melhor do que retornar void! criar "proxy" (guarda o tipo ! e o valor (evita ter problemas de derefernciação)) // pode permitir lazy evalution no futuro typedef struct SYNTH_OBJECT { - ENTRY_TYPE type; + object_type type; int OBJECT_SIZE; - int* STR; // tamanho strings mapeado + int STR; // tamanho strings mapeado void ** values; // a pergunta é ... lista de valores ou valor único ?(em geral vai ser unico, pode ser também um ponteiro para uma lista) int redef; // serve para auxiliar na escrita no nuXmv (e talvez em um futuro se permitir lista de valores diferentes) char* SINTH_BIND; // auxilia a variavel anterior, // serve para auxiliar a limpeza de memória e escrever no nuXmv int timeContext; + int aList; + void* type_smv_info; + int fromTdsValue; // flag apenas para restringir o comportamento já que o cast do nuXmv de int -> symbolic vale + // mas o contrário symbolic -> int NAO } Object; -// mudar depois o tipo -Object *createObject(int type, int OBJECT_SIZE, void **values, int timeContext, char *BIND); + +/** + * Aloca um objeto atômicos da linguagem (que não sejam uma estrutura TDS ou TimeComponent) + * @param type o tipo do objeto + * @param OBJECT_SIZE o tamanho do objeto + * @param values os valores passados + * @param timeContext o contexto temporal + * @param BIND o bind sintetizado para aquele objeto + * @param TYPE_SMV_INFO a informação de domínio do tipo no nuXmv. (Uma copia é passada para cada objeto) + * @return um objeto qualquer da linguagem que não envolva estruturas de dados + * @SideEffects: Aloca uma lista de ponteiros para void de tamanho OBJECT_SIZE e para parte da lista aloca um + * ponteiro para o tipo apropriado. Ver métodos: allocatePtObjects e allocateTypeSetObjects + */ +Object * createObject(object_type type, int OBJECT_SIZE, void **values, int timeContext, char *BIND, void *TYPE_SMV_INFO); + +/** + * Aloca um Object em forma de estrutura dados composta de objetos + * @param type o tipo da lista (e de todos os seus objetos) + * @param OBJECT_SIZE o tamanho da lista + * @param value os valores a serem passados + * @param aList flag para tratamento de alocação de lista + * @return Aloca um object composto de outros objects já alocados anteriormente. + */ +Object* createObjectDS(object_type type, int OBJECT_SIZE, void ** values, int timeContext, char *BIND, int aList); void printObject(Object* o); @@ -30,9 +58,38 @@ void letgoObject(Object *o); */ Object* copyObject(Object* o); +/** + * Copia uma propreidade de um objeto + * @param o o objeto raiz + * @param path o caminho da propriedade + * @return retorna o objeto esncapsulado que possui o bind completo + */ +Object* copyObjectProperty(Object* o, char* path); + /* Atualiza as definições de um objeto "o" */ void updateObject(Object *o, void **any, int any_type, int object_size, int index, int prop, int contextChange); +/*** + * Junta duas componentes sintetizadas de uma lista em uma + * nova lista (Objeto do tipo GEN_LIST ou do mesmo tipo que os demais membros da lista (para os objetos não internos da linguagem) ). + * É usado para parâmetros, listas, e outras estruturas recursivas da AST. + * + * @param LEFT_COMPONENT o objeto mais a esquerda LISTA ou valor único + * @param RIGHT_COMPONENT o objeto mais a direita, um valor únco + * @param separator um separador utilizado para sintetizar expressões no SMV (, &, |) ... (talvez nem seja usado) + * @return uma lista genérica ou uma lista de objetos comuns da linguagem + */ +Object * mergeGenericList(Object* LEFT_COMPONENT, Object* RIGHT_COMPONENT); + +/** + * Atualiza um objeto que era NULL + * @param var o objeto original + * @param expr o novo objeto + * @SideEffects: Aloca um BIND para var, aloca um values para var caso expr não seja uma lista, já que irá ocorrer copia + * de valores. + */ +void updateNullRef(Object *var, Object *expr); + #endif \ No newline at end of file diff --git a/headers/PostProcess.h b/headers/PostProcess.h index 7c2912b..0e5faf2 100644 --- a/headers/PostProcess.h +++ b/headers/PostProcess.h @@ -2,10 +2,7 @@ #define POSP_H -#include "textManager.h" -#include "HeaderSmv.h" -#include "STable.h" -#include "Node.h" +#include "EnvController.h" #include "Object.h" @@ -21,15 +18,14 @@ * @SideEffects Aletra o conteúdo em memória vindo de SINTH_BIND * * */ -void copyValueBind(Object* o, char* bind,int index,int defaultValue); +void copyValueBind(Object *o, char *bind, int index, int defaultValue, int valueNotRef); /* * Atualiza o intervalo de tempo -> "time: 0..3;" e * o init(time) ou next(time) dependendo se for I_TIME ou F_TIME * */ - -void updateTime(HeaderSmv* main , STable * writeSmvTypeTable, char* newValue, int type, int typeExrp,int minmax); +void updateTime(HeaderSmv* main, STable * writeSmvTypeTable, char* newValueBind, int type, int typeExpr, int newValue); /** * Cria um cubo de condições da forma: @@ -114,7 +110,7 @@ char *formatBinds(int ctime, int changeContext, char *directiveValueBind, char * * */ void createAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, const char *newValue, char *condition, - int typeExpr, char *defaultEvalCond); + int typeExpr, char *defaultEvalCond, int freeCondition, int initialNext); /** @@ -133,23 +129,30 @@ void createAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, c * além disso, atualiza na entrada da tabela da simbolos o tipo (typeSet) associada a varName, * se o tipo mudar (caso de next após mudança de contexto). * */ -void updateAssign(char* varName ,HeaderSmv* header, STable* writeSmvTypeTable, char* newValue, char* condition, int type ,int typeExpr, int minmax); +void updateAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, char *newValue, char *condition, int type, int typeExpr); /** * Devolve uma referência a um objeto, considerando seu bind com redefinições e escopo original onde foi criado * @param a entrada original na tabela de simbolos da linguagem * @sideEffects: Todos os criar uma copia do Object referênciado por var, e passa uma string do nome referênciado para o seu SYNTH_OBJECT * */ -Object* refCopyOfVariable(TableEntry* var); +Object *refCopyOfVariable(TableEntry *var, EnvController *controller); /** * Escolhe entre update/create Assign de casos init/next tratando casos de redefinição e condições * @param - * @sideEffects: Todos os colaterais de updateAssign ou createAssign + * @SideEffects: Todos os colaterais de updateAssign ou createAssign * */ void specAssign(int varInit, char *varName, int contextChange, HeaderSmv *header, STable *scope, STable *writeSmvTypeTable, - Object *newValue, int redef, int typeExpr, int C_TIME); + Object *newValue, int redef, int typeExpr, int C_TIME, EnvController *controller); +/** + * Cria um nome ativo para uma TDS da forma tds_{declaredName} + * @param declaredName + * @return um bind do nome criado. + * @SideEffects: aloca uma string para retornar, tornando responsabilidade do chamador a liberar da memória depois. + */ +char* createReferenceTDS(char* declaredName); /** * Para casos de redefinição, libera a entrada anterior dessa variável já que a mesma não será mais referênciada @@ -159,8 +162,129 @@ void specAssign(int varInit, char *varName, int contextChange, HeaderSmv *header * */ void letGoOldEntry(TableEntry* var, STable* auxTable); +/** + * Processa uma TDS para criar o seu equivalente nuXmv em módulo. + * Criando assim, sua tabela auxiliar e Header (modulo), sua declaração em ports module, e realizando sua validação + * + * @param encapsulatedTDS o objeto tds encapsulado + * @param controller o controlador de contexto + * @param C_TIME o contexto temporal atual, usado para validar o uso dessa TDS em casos de listas de dados (onde os dados são vinculados diretamente) + * @param I_TIME o tempo inicial de um intervalo, usado para validações lógicas de TDS de listas de dados + * @param F_TIME o tempo final de um intervalo, usado para validações lógicas de TDS de listas de dados + * @param SYNTH_DEP as tds's necessárias para criar o assign inicial em casos de tds com dependencia de outras + * @SideEffects: Aloca um Header e o salva no controller nas ports. Aloca uma tabela de simbolos para esse módulo. + * Essas devem ser liberadas assim como as outras. Realiza declaração da tds em ports module (linha que deve ser liebrada depois) + */ + +void preProcessTDS(Object* encapsulatedTDS, EnvController* controller, int C_TIME, int I_TIME, int F_TIME); + +/** + * Define um módulo smv para a TDS associada ao parâmetro. Recupera as informações da encapsulatedTDS avaliada, seus dados, seu header, + * seu conjunto de tipos esperados (NULL é o default os demais são retirados dos dados). + * @param encapsulatedTDS o objeto TDS encapsulado. + * @param C_TIME o contexto temporal atual, usado para criar condições de inicialização para essa TDS. + * @param controller o controller para conseguir realizar a escrita. + * @param currentScope o escopo corrente usado para outras passagens necessárias de informação. + */ +void specTDS(TDS* currentTDS, Object* lazyValue, int C_TIME, int I_TIME, EnvController *controller, STable *currentScope); + +/** + * Dada uma TDS sintetizada e sua dependencia, atualiza o type-set em seu header baseado no + * type-set do header da dependencia. "Unindo" os type-sets caso seja necessário + * + * Faz as operações para recuperar a tabela de simbolos auxiliar e header apropriados + * para atualizar um type-set. Delega as demais operações para o updateTypeSet depois + * + * @param currentTDS a TDS que recebe valores + * @param dependency a TDS que fornece valores + * @param controller o controlador de ambiente + * @SideEffects: O mesmos do updateTypeSet + */ +void propagateValueToTypeSet(TDS* currentTDS, TDS* dependency, EnvController* controller); +// doc antiga +// método especializado para adicionar valores que sejam SMV_POINTERS (indice no Header, tamanho da palavra, conjunto de tipos(hashmap ou outro objeto)) +/* + + Objeto: vetor dinamico[inteirosDoConjunto], nullable, vetor dinamico[labelsDoConjunto] + + Prós: Menos structs para alocar,não tem que alocar uma TABELA INTEIRA só para alguns valores, + a linguagem possui poucos tipos (atualmente: int, label, boolean(FALSE E TRUE são só enums no nuXmv), + e tds (que na verdade retorna qualquer um dos tipos anteriores)) + + Cons: Outro objeto (mais coisas para dar free), + "quebaria" o conceito de hashmap que é justamente não ter duplicata, ia ser um objeto só para checar algumas coisas + Toda vez que adicionar um tipo novo necessita alterar essa estrutura + + Hashmap: estrutura que já temos atualmente, teria pelo menos umas 5 entras (talvez mais ou menos) + + Pŕos: Não necessita criar mais nada, não precisa alocar vetores (indexa pela string em qualquer caso), + aberto para novos tipos (indexa pela string) + + Cons: Vai ficar uma estrutura "recursiva" tabela --x entradas--> entradaSmv(porta ou main) --> Objeto(iHeader,size, + tabela ---y entradas--->entradas --> Objeto(bool)) + Mais coisas para centralizar e dar free +*/ + +/** + * Dado um valor sintetizado (em string) um type-set e criado com esse valor (e o default NULL) + * e a palavra e adicionada ao dicionario do controller (caso seja necessario) + * @param controllerSmv o controller que contem o dicionario + * @param sint_value o valor sintetizado em string + * @return um novo type-set que pode ser usado para realizar referencias + */ +TypeSet *computeTypeSet(EnvController *controllerSmv, char *sint_value); + +/** + * Formata o nome de uma variável da forma init/next(varName) + * @param varName o nome original da variável + * @param stateId o id do estado init ou next (recuperado do enum) + * @param refToUpdate a string que vai ser atualizada (optamos pelo sideEffect por flexibilidade) + * @SideEffects: Atualiza a string refToUpdate + */ +void formatStateVar(char* varName, int stateId, char* refToUpdate); + +/** + * Cria a string de referencia ao valor de uma TDS, da forma, nomeTds.value + * @param currentTds a tds corrente + * @param refToUpdate a string que vai ser atualizada (optamos pelo sideEffect por flexibilidade) + * @SideEffects: Atualiza a string refToUpdate + */ +void formatTdsValueRef(TDS* currentTds, char* refToUpdate); + +/** + * Atualiza a referencia de todas as transições de automato que receberiam a condição de filtor + * @param condFilter condição de filtro sintetizada + * @param controller o controlador de ambiente que + */ +void updateAllAutomataFilter(Object* condFilter, EnvController* controller); + +/** + * Cria uma expressão do tipo parcialPath.propName + * @param parcialPath o path da propreidade + * @param propName o nome da propriedade + * @return uma string que segue o padrão especificado + * @SideEffects: Aloca uma string que deve ser liberada pelo chamador + */ +char* createPropPathBind(char* parcialPath, char* propName); + +/** + * Encapsula uma expressão com o comando next() + * @param expression a epxressão original + * @return Uma expressão em string com o padrão especificado + * @SideEffects: Aloca uma string que deve ser liberada pelo chamador + */ +char* encapsulateWithNext(char* expression); + +/** + * É utilizado para o automato (filter) já que as expressões resultantes devem ser negadas. + * Como elas não vieram da arvore do interpretador o processo deve ser feito manualmente... + * @param expression a expressão resultante + * @return uma expressão da forma !(expr) + * @SideEffects: aloca uma string que deve ser liberada pelo chamador + */ +char* encapsulateExpressionWithNegation(char* expression); -void writeResultantHeaders(HeaderController* controller, const char* path); +void writeResultantHeaders(EnvController* controller, const char* path); #endif diff --git a/headers/PreProcess.h b/headers/PreProcess.h index 2563371..c9f3193 100644 --- a/headers/PreProcess.h +++ b/headers/PreProcess.h @@ -2,30 +2,18 @@ #define PREP_H -#include "HeaderSmv.h" - - - +#include "EnvController.h" /* salva o headerSMV do módulo lido anteriormente. se for um automato o ponteiro de transição não é vázio. - efeito colateral: * ao criar ao salvar o header incrementa o tamanho de headers do HeaderController + efeito colateral: * ao criar ao salvar o header incrementa o tamanho de headers do EnvController * cria um header (necessita de free depois) */ -void initPreProcessHeader(smvtype type, char* moduleName, HeaderController* Hcontrol); - - +void initPreProcessHeader(smvtype type, char* moduleName, EnvController* Hcontrol); -/* - escolhe um buffer do header atual para salvar a linha (alocando sempre uma string para essa linha, que depois deve ser liberada). - efeitos colaterais: * ao ter readVarPortsModule como true, ele salva as variáveis do portsModule em uma tabela de portas - * ao ter controlRename como true, ele remove todas as ocorrências de determinados caracteres (no caso []) - -*/ -void selectBuffer(headerpart part, char* line, HeaderSmv* header, int controlRename); /* @@ -33,14 +21,14 @@ void selectBuffer(headerpart part, char* line, HeaderSmv* header, int controlRen ratando a posição (pos) que representa o tamanho do vetor de HEADERS do controller (LEN-1) */ -void saveLineOnBuffer(smvtype currentHeader, headerpart part, char *line, HeaderController *Hcontrol, int controlRename); +void saveLineOnBuffer(smvtype currentHeader, headerpart part, char *line, EnvController *Hcontrol, int controlRename); /* fases: criação, var, assign(pode não existir), trans(pode não existir) (as partes de interesse) as partes de interesse servem como delimitadores, quebras de linha servem como delimitadores dos módulos stages são os módulos 0(main), automato(2), ports(3) */ -void processPhase(smvtype stage, headerpart part, HeaderController *Hcontrol, char *line, int controlRename); +void processPhase(smvtype stage, headerpart part, EnvController *Hcontrol, char *line, int controlRename); /** * Salva o arquivo SMV original em headers, separados por categorias e partes de um arquivo SMV. @@ -50,7 +38,13 @@ void processPhase(smvtype stage, headerpart part, HeaderController *Hcontrol, ch * para renomações futuras. Além disso são criadas entradas na tabelas de simbolos auxiliares (SMV_INFO) usadas pelo main e ports, respectivamente, * a variável time e as portas que vierem do módulo original. * */ -void preProcessSmv(FILE *smvP, HeaderController *Hcontrol); +void preProcessSmv(FILE *smvP, EnvController *Hcontrol); + +/** + * Operação oposta ao pré processamento padrão o qual um arquivo default é "pré processado" + * @param controller o controlaod de ambiente para manter as informações dos headers default que iremos criar + */ +void setDefaultSmv(EnvController* controller); /** * Configura a tabela de controle SMV info da main para a variável time a incializando @@ -63,7 +57,7 @@ void preProcessSmv(FILE *smvP, HeaderController *Hcontrol); * @SideEffects: Chama o addValue da tabela de simbolos para os casos citados, alocando memória para as Entry de * cada tupla. * */ -void setUpMainSmvTable(HeaderController *Hcontrol, STable *global); +void setUpMainSmvTable(EnvController *Hcontrol, STable *global); #endif diff --git a/headers/STable.h b/headers/STable.h index 3dd5aa6..f9ac535 100644 --- a/headers/STable.h +++ b/headers/STable.h @@ -4,10 +4,9 @@ #include "Enum.h" #include "Object.h" +#include "Hash.h" -#define MAX_TABLE 950 - -#define MAX_SIMPLE 100 +#define MAX_TABLE 1025 #define MAX_CHILD 150 @@ -43,7 +42,7 @@ typedef struct S_TABLE int backup; int collision; int notEvaluated; - int usedSize; + int notWrite; int childOfFunction; int indexRef; } STable; @@ -64,7 +63,7 @@ STable* addSubScope(STable* parent, SCOPE_TYPE type); Após isso tenta novamente inserir param :e - efeitos colaterais: muda comportamento da função hash e chama insert novamente para param :e + efeitos colaterais: muda comportamento da função calculateHashPos e chama insert novamente para param :e */ void redistributeHashs(STable* t, TableEntry* e); @@ -75,16 +74,18 @@ void redistributeHashs(STable* t, TableEntry* e); */ int checkTypeSet(STable* current, char* name, char* typeid); -/* - Adiciona um tipo para o "conjunto de tipos das variáveis" para otimizar a escrita no arquivo SMV. - Efeitos colaterais: chama addValue para a tabela* da tupla (indice, tamanho, tabela*) -*/ -void addEntryToTypeSet(STable* current, char* name, char* typeid); - -void addTypeSetSmv(char *name, void **any, int object_size, STable *current); - void addValue(char *name, void **any, int any_type, int object_size, int methodParam, STable *current, int timeContext); +/*** + * Adiciona a referência a um objeto(ED) a uma variável de um dado escopo + * @param name o nome da variável + * @param DATA_STRUCT a estrutura de dados (VETORES E TDS'S) + * @param methodParam se essa referência é passada como parâmetro ou não (provavelmente útil ao dar free já que dar free e ele existe fora da uma + * função implicaria em perda de dados) + * @param current o escopo corrente. + */ +void addReferenceCurrentScope(char* name, Object* DATA_STRUCT, int methodParam, STable* current); + void addValueCurrentScope(char* name, Object* val, int methodParam,STable* current); /* @@ -98,7 +99,7 @@ void printTable(STable* t); void letgoTable(STable *t); -int hash(char * str, STable* t); +int calculateHashPos(char * str, STable* t); void insert(STable* t, TableEntry* e); @@ -124,8 +125,22 @@ void letgoEntry(TableEntry *e); * Porque desse método? Caso seja necessário "economizar entradas" antes do fim da execução, ele limpa os valores da tabela (NULL) * @param a tabela a liberar os dados * @param name o nome da variável - * @SideEffects chama o letGoEntry original e seta o table->data[hash] = NULL + * @SideEffects chama o letGoEntry original e seta o table->data[calculateHashPos] = NULL * */ void letGoEntryByName(STable* table, char* name); + +/** + * Chama o addValue, porém, como o objeto salvo na tabela de simbolos auxiliar é um type-min-max/type-info, + * passamos o type_smv_info_dc como parâmetro para setar ao objeto recebem escrito. + * @param name o nome da variável na tabela de simbols auxiliar (e no nuXmv) + * @param any os valores da declaração (ex: pos, size, ptini, ptend) + * @param any_type o tipo (WRITE_SMV_INFO, TYPE_SET) + * @param object_size o tamanho do objeto + * @param current a tabela de simbolos auxiliar usada no momento + * @param type_smv_info_dc a informação adicional para escrever o domínio de valores de uma variável + * @SideEffects: Aloca um objeto e entrada na tabela de simbolos auxiliar assim como addValue, + */ +void addSmvInfoDeclaration(char *name, void **any, int any_type, int object_size, STable *current, void* type_smv_info_dc); + #endif diff --git a/headers/TDS.h b/headers/TDS.h new file mode 100644 index 0000000..a487187 --- /dev/null +++ b/headers/TDS.h @@ -0,0 +1,118 @@ +#ifndef TDSV_H + +#define TDSV_H + +#include "Enum.h" +#include "Object.h" +#include "Hash.h" + +#define MAX_DEPEND 150 + + +//struct de TDS: + +typedef struct TDS +{ + char* name; + TDS_TYPE type; + void* DATA_SPEC; // especificação da TDS, ou seja o PATH DO PROGRAMA (referencia a função também vai ficar aqui) + Object** DATA_TIME; // todos os objetos de valor por tempo sintetizados para a TDS, usado para memoization + struct TDS** linkedDependency; // tds's que estão sendo observadas por essa (são dependencias) + int TOTAL_DEPENDENCIES_PT; // total de dependencias dessa TDS (quando aplicavel) + int delayed; // se ela é delayed ou não + int I_INTERVAL; + int F_INTERVAL; + int* COMPONENT_TIMES; + int AUX_REF; // devemos ter duas referências porque a tabela de simbolos auxiliar NÃO É USADA POR PORTS MODULE. (NA VERDADE É USADO SIM AGORA) + int SMV_REF; // por outro lado, os HEADERS SÃO USADOS POR AMBOS! + // watch-list não será reintroduzida + int noValue; + int LAST_DELAYED_ACCEPT_TIME; + + // usados pelo filter + void* limitCondition; // provavelmente vai ter que ser um path + int currentCondEval; + char* currenCondBindRef; + + +} TDS; + +// passar valores e função para construtor? (função já vai estar definida, valores só vai estar definido se a TDS for linked!) +TDS * createTDS(char *name, TDS_TYPE type, void *valueList, int delayed, int I_INTERVAL, int F_INTERVAL, void *limitCondition); + +/** + * Linka duas TDS's. + * @param tds a TDS que fornece a dependência + * @param dependent a TDS que recebe a dependência + */ +void addTdsDependency(TDS* dependency, TDS* tds); + +/** + * Adiciona um dado sintetizado para uma TDS indexado por instantes de tempo. + * Caso o instante não possua dado, realiza a operação e retorna 1, + * caso contrário retorna zero. + * @param currentTDS a tds a ser modificada + * @param C_TIME o tempo corrente + * @param value o valor + * @return 1 caso a operação tenha sido realizada, 0 caso contrário + */ +int addDataToTds(TDS* currentTDS, int C_TIME, Object* value); + +/** + * Dada uma TDS, resolve todas as dependências de valor que ela possui em um determinado instante de tempo. + * Caso mais de uma resolução seja encontrada, não faz nada. (MERGER) + * @param tds a tds atual + * @param C_TIME o tempo corrente + */ +void resolveMergerTdsDependencies(TDS *tds, int C_TIME); + +/** + * Resolve a dependência de uma TDS que segue o padrão delayed. + * Usa o tempo corrente para determinar se estamos em um instante futuro ao I_INTERVAL + * delayed só aceita 1 input, e esse deve seguir a seguinte regra: + * + * init(d.value):= NULL; + * next(d.value):= case + * d.value = NULL : c.value; + * c.value = NULL & d.value != NULL : NULL; + * TRUE : d.value; + * esac; + * Dessa forma referenciando um valor anterior da TDS delayed e tendo um ponteiro próprio para esse + * de forma que quando um valor não é aceito pela porta ele se mantem no anterior. + * + * @param tds a tds delayed + * @param C_TIME o tempo de referência + */ +void resolveDelayedTdsDependencies(TDS* tds, int C_TIME); + +/** + * Devolve o valor de uma TDS em um determinado instante de tempo. A não ser que essa seja delayed, + * ai ele referencia o último valor "aceito". + * @param tds a tds a qual necessitamos do valor + * @param C_TIME o tempo corrente + * @param valuePath o caminho de referencia + * @return uma copia do valor da TDS no instante corrente + * @SideEffects: Aloca um novo object que deve ser liberado pelo chamador depois + */ +Object* getTdsValue(TDS* tds, int C_TIME, char* valuePath); + +/** + * Atualiza a condição de uma TDS realizando as validações corretas + * @param tds a tds a qual o filtro é aplicado + * @param condExpr a condição que foi avaliada no instante de tempo atual + */ +void updateLimitCondition(TDS* tds, Object* condExpr); + +/** + * Reseta uma condição de filtro para a próxima iteração da TDS. + * @param tds a tds atual + */ +void resetLimitConditionEval(TDS* tds); + +void letGoTDS(struct TDS* tds); + +void prepareToPrintTDS(TDS* tds, int C_TIME); + +void printTDS(TDS* tds, TDS* dependent, int C_TIME); + +#endif \ No newline at end of file diff --git a/headers/TDSvar.h b/headers/TDSvar.h deleted file mode 100644 index 8f83f04..0000000 --- a/headers/TDSvar.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef TDSV_H - -#define TDSV_H - -#include "Enum.h" - - -//struct de TDS: - -typedef struct TDS_VAR -{ - char* name; - int type; - int I_TIME; // reflete os valores globais - int F_TIME; - int C_TIME; // apesar que o C_TIME é do contexto dessa tds... - - int linked; // lista unica que referencia outra TDS e toma os valores dela! (economiza um campo, evita ref ciclica) - int delayed; - - // ainda não sei como isso vai ficar - void * fpointer; - - - // dados da tds (lista de tamanho = F_TIME - I_TIME), (ACEITAR DADOS DIFERENTES? OU SÓ UM PARA A TDS?) - // se for um tipo só : usar union? (pode ser um de cada vez mais não ao mesmo tempo) - // senão usar VOID - void ** values; // delayed? passar lista "alternada?", ou usar object? - - - -} TDSvar; - -// passar valores e função para construtor? (função já vai estar definida, valores só vai estar definido se a TDS for linked!) -TDSvar* createTDS(char* name, int type, int I_TIME, int F_TIME, int C_TIME, int linked, int delayed); - -#endif \ No newline at end of file diff --git a/headers/TypeMinMax.h b/headers/TypeMinMax.h new file mode 100644 index 0000000..96ee02a --- /dev/null +++ b/headers/TypeMinMax.h @@ -0,0 +1,209 @@ +// +// Created by mateus on 02/04/2021. +// + +#ifndef TDSREPLANGUAGE_TYPEMINMAX_H +#define TDSREPLANGUAGE_TYPEMINMAX_H + +typedef struct type_min_max +{ + //int pos; // talvez seja desnecessário + //int size; // só precisamos da referencia (mesmo para type-set) em que iremos usar os demais valores para auxiliar o que devemos jogar no nuXmv + int min; + int max; +} TypeMinMax; + +/** + * para todos os casos devemos tratar caso min = max (e colocar 1) senão o nuXmv acha que é UMA CONSTANTE + */ + +/** + * Trata inicializações de type-min-max de valores unicos considerando que não devemos montar "constantes". + * Esse método pode ser melhorado no futuro + * @param valSin o valor unico sintetizado junto de um objeto + * @return um type-min-max montado com um valor único + */ +TypeMinMax* createMinMaxByOneValue(int valSin); + +/** + * Cria o type-min max associado a um valor/variável/expressão. Realizando o tratamento necessário + * @param min o valor máximo + * @param max o valor mínimo + */ +TypeMinMax* createMinMax(int min, int max); + + +/** + * Cria um novo min-max que representa a soma de outros dois tipos inteiros. + * + * A representação segue as seguintes regras: + * + * tmm1: min: + , max : + + * - resulta em -> tmmR: min: min1 + min2 , max: max1+max2 + * tmm2: min: + , max : + (0,10) , (2,5) -> (2,15) + * + * tmm1: min: + , max : + + * - resulta em -> tmmR: min: min1 + min2 , max: max1+max2 + * tmm2: min: - , max : + (-3,10) , (2,5) -> (-1,15) + * + * tmm1: min : -, max : - + * - resulta em -> min: min1 - min 2 , max> max1 - max2 + * (-3,-6) , (-4,-1) -> -7 , -7 + * tmm2: min: -, max : - + * + * generalizando.... o nuXmv faz assim (como escrevi na subtração que é um pouco diferente): + * + * (0,10) , (2,5) -> (2,15) + * 0 + (2~5) -> 2~5 + * 1 + (2~5) -> 3~6 + * 2 + (2~5) -> 4~7 + * 3 + (2~5) -> 5~8 + * 4 + (2~5) -> 6~9 + * 5 + (2~5) -> 7~10 + * 6 + (2~5) -> 8~11 + * 7 + (2~5) -> 9~12 + * 8 + (2~5) -> 10~13 + * 9 + (2~5) -> 11~14 + * 10 + (2~5) -> 12~15 + * + * No caso da soma é "trivial" + * + * @param typeRefMinMax1 o type-min-max do primeiro operando + * @param typeRefMinMax2 o type-min-max do segundo operando + * @return um type-min-max novo que segue as regras especificadas. + */ +TypeMinMax* computeMinMaxSum(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2); + +/** + * Cria um novo min-max que representa a subtração de outros dois tipos inteiros. + * + * A representação segue as seguintes regras: + * + * tmm1: min: + , max : + + * - resulta em -> tmmR: min: min1 - min2 , max: max1-max2 + * tmm2: min: + , max : + (0,10) , (2,5) -> (-2,5) + * + * tmm1: min: + , max : + + * - resulta em -> tmmR: min: min1 - min2 , max: max1-max2 + * tmm2: min: - , max : + + * + * tmm1: min : +, max : + + * - resulta em -> min: min1 - min 2 , max: max1 - max2 + * (-4,1), (0,6) -> -4, -5 ? (ERRADO) -> na verdade o que ele faz é + * tmm2: min: -, max : - + * -4 - (0~6) -> (-4,-10) + * -3 - (0~6) + * -2 - (0~6) + * -1 - (0~6) + * 0 - (0~6) + * 1 - (0~6) -> (1,-5) + * + * O certo é: + * min: min1 - max2 , max: max1 - min2 + * -4-6 e 1-0 (-10,1) + * A lógica é... o minimo deve ter O MAIOR VALOR POSSÍVEL RETIRADO (ou seja o max do operando 2) + * E o max deve ter o menos retirado o possível + * + * @param typeRefMinMax1 o type-min-max do primeiro operando + * @param typeRefMinMax2 o type-min-max do segundo operando + * @return um type-min-max novo que segue as regras especificadas. + */ +TypeMinMax* computeMinMaxSub(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2); + +/** + * Realiza a operação de negativo de um valor único de type-min-max. Seguindo a regra: + * + * Se o número é positivo: + * min: -max1 + * max: -min1 + * + * Se o número é negativo: + * + * min: -max1 + * max: -min1 + * + * A ideia é tratar a distancia em módulo de valores + * @param typeRefMinMax1 + * @return o novo type-set com o min max que segue a regra + */ +TypeMinMax* computeMinMaxNeg(TypeMinMax* typeRefMinMax1); + +/** + * Cria um novo min-max que representa a multiplicação de outros dois tipos inteiros seguindo a seguinte regra: + * + * min: + * + * Se min1 e min2 forem positivos >= 0. min1*min2 + * Se min1 ou min2 forem negativos: negativo1*max2 ou negativo2*max1 (vai resultar em uma multiplicação bem negativa) + * + * max: + * + * max1*max2 se ambos positivos + * se algum deles forem negativos (ou seja o max =< 0 deve ser max1*maiorNegativo ou o contrário) + * Da a mesma coisa no final das contas... + * + * @param typeRefMinMax1 o type-min-max do primeiro operando + * @param typeRefMinMax2 o type-min-max do segundo operando + * @return um type-min-max novo que segue as regras especificadas + */ +TypeMinMax* computeMinMaxMul(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2); + +/** + * Cria um novo min-max que representa a divisão de outros dois tipos inteiros seguindo a seguinte regra: + * + * min: min1/max2 ou min1/min2 (caso min1 seja negativo, deve ser o min2 > 0 de forma a gerar o negativo com maior distancia a zero), + * + * max: max1/min2 tal que min seja > 0, senão ele pega o menor valor positivo possível (caso exista) + * Se não existir esse menor (max) positivo (número negativo completo), + * (vamos estar gerando uma operação com resultado com o maior número possível, sendo na verdade o menor..) + * Enão fazer max: max1/max2 (de forma que ainda vai gerar um negativo porém "maior" isso é mais perto de zero). + * + * @param typeRefMinMax1 o type-min-max do primeiro operando + * @param typeRefMinMax2 o type-min-max do segundo operando + * @return retorna um novo type-min-max que resolva o intervalo + */ +TypeMinMax* computeMinMaxDiv(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2); + +/** + * + * Cria um novo min-max que representa a operação de modlulo entre dois tipos inteiros seguindo a seguinte regra: + * + * operando2 não pode ser igual a zero (mas a linguagem já trata) + um módulo de x mod y pode ter os seguintes valores: + 0 divisão exata (a operação mod não tem negativos) + ~ + x y é muito maior que x + Como o operando1 pode ter um intervalo variado. Devemos estender entre o seu min e max caso seja um número + que varia entre positivos e negativos. Caso contrário, será do 0 até o seu max. + E o nuXmv trata diferente da regra: + a/b = q with remainder r + Such that: b*q + r = a and 0 <= r < b + Assim como em C e C++ + * + * @param typeRefMinMax1 o type-min-max do primeiro operando + * @param typeRefMinMax2 o type-min-max do segundo operando + * @return retorna um novo type-min-max que resolva o intervalo + */ +TypeMinMax* computeMinMaxMod(TypeMinMax* typeRefMinMax1, int by2); + +/** +** + * Cria um novo objeto type-min-max + * @return uma copia do type-min-max original + */ +TypeMinMax* copyTypeMinMax(TypeMinMax* original); + +/** + * Decide o min-max de um type-min-max baseado em uma nova informação sintetizada. + * Após realizar a decisão retorna um código que irá sinalizar qual parte da declaração deve ser alterada na string. + * @param original o type-min-max que já está contido na declaração + * @param newInfo a nova informação de type-min-max sintetizada + * @return -1 caso nenhum tenha sido alterado, 0 se o minimo necessita de alteração, 1, se o maximo necessita, 2 se ambos necessitam + */ +int mergeTypeMinMax(TypeMinMax* original, TypeMinMax* newInfo); + +int changeMinMax(TypeMinMax* tmm, int value); + +void letGoTypeMinMax(TypeMinMax* tmm); + +#endif //TDSREPLANGUAGE_TYPEMINMAX_H \ No newline at end of file diff --git a/headers/TypeSet.h b/headers/TypeSet.h new file mode 100644 index 0000000..27ebc87 --- /dev/null +++ b/headers/TypeSet.h @@ -0,0 +1,49 @@ +// Created by mateus on 31/03/2021. +// + +#ifndef TDSREPLANGUAGE_TYPESET_H +#define TDSREPLANGUAGE_TYPESET_H + +#include "Hash.h" + + +typedef struct TypeSet +{ + //int pos; + //int size; + char** hash_set; + int usedSize; + int lastIndex; + +} TypeSet; + +TypeSet* createTypeSet(char* defaultWord); + +int addElementToTypeSet(TypeSet* ts, char* newElement); + +// não existem operaçõs intermediaras com variáveis que vão retornar o type-set. O que vai acontecer é que +// não "atualizaremos" ele durante o eval expr, mas no final do add type-set ou ainda do update type-set +// é que compararemos o type-set sintetizado com o que está na tabela auxiliar, +// +// na criação poderemos utilizar o type-set que foi sintetizado ao invés de criar +// -> caso a string não exista no controller, alocar nele e depois passar ref para o type-set novo +// +// na atualização (método merge) se eles tiverem divergencia, atualizaremos +// o da tabela e daremos free no outro. +// -> o merge atualiza uma ref (vinda do env) para o type-set que ficou na tabela e da free no outro que foi sintetizado + +/** + * Cria um novo objeto type-set que contem referência as trings todos os objetos do type-set anterior e os demais campos alocados + * @param original o type-set original + * @return uma "copia" do type-set original + */ +TypeSet* copyTypeSet(TypeSet* original); + +/** + * Libera o type-set, de forma a dar free em toda a memoria utilizada por ele (menos as strings que vem do dict, são responsabilidades + * do controller. + * @param ts o type-set a ser liberado + */ +void letGoTypeSet(TypeSet* ts); + +#endif //TDSREPLANGUAGE_TYPESET_H \ No newline at end of file diff --git a/headers/Visitor.h b/headers/Visitor.h new file mode 100644 index 0000000..9f86166 --- /dev/null +++ b/headers/Visitor.h @@ -0,0 +1,79 @@ +// +// Created by mateus on 22/03/2021. +// + +#ifndef TDSREPLANGUAGE_VISITOR_H +#define TDSREPLANGUAGE_VISITOR_H + +#include "PostProcess.h" +#include "Node.h" +#include "Object.h" + +Object* evalNUM(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalBOOL(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalSTRING(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalNULL(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalIDVAR(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalTIME_DIRECTIVE(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalDataV(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalPARAMS(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalPARAMS_CALL(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalAC_V(Node* n, STable* scope, EnvController* controllerSmv); +Object* eval_ASSIGN_TDIRECTIVE(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalOTHER_ASSIGN(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalV_PROP(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalADD_V(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalADD_V_PROP(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalV_PROP_TDS(Node* n, STable* scope, EnvController* controllerSmv); +Object * evalEXPR(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalMINUS(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalPLUS(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalMULTI(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalDIV(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalLE(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalGE(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalLT(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalGT(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalEQUAL(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalNEQUAL(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalNOT(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalAND(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalOR(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalIMP(Node* n, STable* scope, EnvController* controller); +Object* evalBIMP(Node* n, STable* scope, EnvController* controller); +Object* evalPRI_EXPR(Node* n, STable* scope, EnvController* controllerSmv); +Object * evalDEFINE_INTERVAL(Node* n, STable* scope, EnvController* controllerSmv); +Object * evalCMD_IF(Node* n, STable* scope, EnvController* controllerSmv); +Object * evalTDS_DEF_COMPLETE(Node* n, STable* scope, EnvController* controllerSmv); +Object * evalTDS_DEF_DEPENDECE(Node* n, STable* scope, EnvController* controllerSmv); +Object * evalTDS_DATA_TIME_COMPONENT(Node* n, STable* scope, EnvController* controllerSmv); +Object * evalANON_TDS(Node* n, STable* scope, EnvController* controllerSmv); +Object* eval_ITERATOR(Node* n, STable* scope, EnvController* controllerSmv); +Object* evalV_PROP_TDS_VALUE(Node* n, STable* scope, EnvController* controllerSmv); + +Object* (* *executores) (Node* n, STable* scope, EnvController* controllerSmv); + +/** + * Função mapeadora de avaliações do interpretador. De forma que essa função busca + * a avaliação apropriada e repassa para o interpretador. + * @param n o nó corrente da AST + * @param scope o escopo corrente + * @param controllerSmv o controlador de ambiente + * @return retorna um objeto genérico resultado da interpretação (OBJETO SINTETIZADO) + */ +Object *eval(Node *n, STable *scope, EnvController *controllerSmv); + +// usar depois para criar executores genericos +// caso a gente queira simplificar os parâmetros (note que muitos são desnecessários em alguns evals (MELHORIA)) +//typedef Object* (*generic_fp)(void); +/* + * generic_fp executores[80] = { + (generic_fp ) evalNUM, (generic_fp ) evalBOOL, (generic_fp ) evalSTRING, (generic_fp ) evalNULL, (generic_fp ) evalIDVAR, (generic_fp ) evalTIME_DIRECTIVE, + (generic_fp ) evalDataV, (generic_fp ) evalPARAMS_CALL, (generic_fp ) evalDEFINE_INTERVAL , (generic_fp ) evalAC_V, + (generic_fp ) evalOTHER_ASSIGN, (generic_fp ) evalV_PROP, (generic_fp ) evalADD_V, (generic_fp ) evalADD_V_PROP, (generic_fp ) evalV_PROP_TDS, (generic_fp ) evalEXPR, (generic_fp ) + (generic_fp ) evalCMD_IF, (generic_fp ) evalMATCH_IF +}; + * */ + + +#endif //TDSREPLANGUAGE_VISITOR_H diff --git a/headers/textManager.h b/headers/textManager.h index bccf302..0bd77ea 100644 --- a/headers/textManager.h +++ b/headers/textManager.h @@ -2,6 +2,9 @@ #define TM_H + +#define ALOC_SIZE_LINE 1000 + /** * Concatena strings, porém sempre retornando o final da string como ponteiro, servindo para evitar percorrer a mesma * diversas vezes ao se concatenar várias componentes (usada ao adicionar parâmetros por exemplo). Por outro lado, @@ -37,7 +40,7 @@ char * customCat(char* dest, char* src, char toIgnore, int ignoreMode); * * @return A nova string alocada em outro ponteiro (a responsabilidade de free ou realloc fica fora dessa função) * */ -char *addParams(char *original, char *param, char *delim1, char *delim2); +char *addParams(char *original, char *param, char *delim1, char *delim2, int useRealloc); @@ -59,8 +62,10 @@ void clearOldPortsRefs(char* oldConstraint, char* toCopyResult); * (usado para updateAssign) * @sideEffects : Atualiza o updated, seja lá de onde que essa string veio em primeiro lugar * (a responsabilidade de free ou realloc fica fora dessa função) + * Caso o tamanho da string venha a VIOLAR o tamanho padrão de texto, a string passada é realocada! + * @returns um ponteiro da string atualizada (justamente para o caso de realocação) * */ -void updateSubStringInterval(const char *newValue, char *updated, int sizeNew, int pointIni, int pointEnd, int size, +char* updateSubStringInterval(const char *newValue, char *updated, int sizeNew, int pointIni, int pointEnd, int size, int *newPointInit, int *newPointEnd, int variantPointIni); /** @@ -76,4 +81,31 @@ void updateSubStringInterval(const char *newValue, char *updated, int sizeNew, i * */ char* overwriteParam(char* moduleName, char* param); +/** + * Recebendo uma String dest como parâmetro, para evitar a responsabiliddade de retornar uma alocada (podemos inclusive mudar isso nos demais métodos) + * copia dados de src para ela até um determinado caracter de parada + * @param dest a string destino alocada ou não fora desse método (tenha em mente que a string NÃO PODE SER READ ONLY) + * @param src a string a qual iremos copiar + * @param stop o caracter onde pararemos a copia. + * @SideEffects: Copia caracteres para dest, se é alocado ou não é responsabilidade de quem chamar a função + */ +void removeAfter(char* dest, char* src, char stop); + +/** + * Converte um número ou diretiva para uma string da mesma + * @param num o número ou diretiva passada + * @return uma string alocada com o valor + * @SideEffects: Aloca uma string com o valor do número que deve ser liberado pelo chamador + */ +char* formatNumeric(int ctime); + +/** + * Remove todas as ocorrencias de uma substring + * @param string a string original + * @param toRemove a substring que deve ser removida + * @return uma nova string igual a antiga porém sem ocorrencias de toRemove + * @SideEffects: Aloca uma string no formato descrito e deve ser liberada pelo chamador + */ +char* removeAllSubStrings(char* string, char* toRemove); + #endif diff --git a/PARSINGOUTPUT b/results/PARSINGOUTPUT-old similarity index 100% rename from PARSINGOUTPUT rename to results/PARSINGOUTPUT-old diff --git a/results/newSmvfile.smv b/results/newSmvfile.smv index 9fcd1f1..3949ac0 100644 --- a/results/newSmvfile.smv +++ b/results/newSmvfile.smv @@ -1,73 +1,76 @@ MODULE main VAR time: 0..20; - finalAutomata: finalAutomata(ports) - ports: portsModule(time); - x : -1..4; + finalAutomata: finalAutomata(ports); + ports: portsModule(time, x, y); + x : -4..0; z : boolean; - zelda : boolean; + zeta : boolean; w_scope1_0 : 0..1; r_scope1_1 : boolean; u_scope1_1_2_0 : boolean; y : 0..6; - w_scope1_2 : 0..1; + w_scope1_2 : boolean; u_scope1_2_2_0 : boolean; - tdsA : 0..1; + stu : -4..0; ASSIGN init(time) := 0; next(time) := case time < 20: time + 1; TRUE: time; esac; - init(x):= 2; + init(x):= -2; + next(x):= case + next(time) = 2 : -4; + next(time) = 3 : -1; + TRUE : x; + esac; init(z):= TRUE; - init(zelda):= FALSE; + next(z):= case + next(time) = 4 : TRUE; + TRUE : z; + esac; + init(zeta):= FALSE; + next(zeta):= case + next(time) = 4 : FALSE; + TRUE : zeta; + esac; init(w_scope1_0):= case !z : 1; TRUE : 0; esac; + next(w_scope1_0):= w_scope1_0; init(r_scope1_1):= case - zelda : FALSE; + zeta : FALSE; TRUE : FALSE; esac; + next(r_scope1_1):= r_scope1_1; init(u_scope1_1_2_0):= case - zelda & z : FALSE; + zeta & z : FALSE; TRUE : FALSE; esac; - next(x):= case - next(time) = 2 : 4; - next(time) = 3 : -1; - TRUE : x; - esac; + next(u_scope1_1_2_0):= u_scope1_1_2_0; init(y):= 0; next(y):= case - next(time) = 2 : 5; - next(time) = 4 & !next(zelda) : 2; - next(time) = 4 & !!next(zelda) : 6; + next(time) = 2 : 5; + next(time) = 4 & !next(zeta) : 2; + next(time) = 4 & !!next(zeta) : 6; TRUE : y; esac; - next(zelda):= case - next(time) = 4 : FALSE; - TRUE : zelda; - esac; - next(z):= case - next(time) = 4 : TRUE; - TRUE : z; - esac; - init(w_scope1_2):= 0; + init(w_scope1_2):= FALSE; next(w_scope1_2):= case - next(time) = 4 & !next(zelda) : 1; + next(time) = 4 & !next(zeta) : TRUE; TRUE : w_scope1_2; esac; init(u_scope1_2_2_0):= FALSE; next(u_scope1_2_2_0):= case - next(time) = 4 & !next(zelda) & next(z) : FALSE; + next(time) = 4 & !next(zeta) & next(w_scope1_2) : FALSE; TRUE : u_scope1_2_2_0; esac; - init(tdsA):= 0; - next(tdsA):= case - next(time) = 4 : 0; - TRUE : tdsA; + init(stu):= 0; + next(stu):= case + next(time) = 4 : next(x) / next(y); + TRUE : stu; esac; MODULE merger1(ports) @@ -92,8 +95,8 @@ TRANS MODULE finalAutomata(ports) VAR - prod1: merger1(ports) - prod2: fifo2(ports) + prod1: merger1(ports); + prod2: fifo2(ports); cs: {q0q0,q0p0,q0p1}; ASSIGN init(cs) := {q0q0}; @@ -109,7 +112,57 @@ INVAR (((prod1.cs = q0) & (prod2.cs = p0)) <-> (cs = q0p0)) & (((prod1.cs = q0) & (prod2.cs = p1)) <-> (cs = q0p1)); -MODULE portsModule(time) +MODULE portsModule(time, x, y) VAR + a : tds_a(time, x); + b : tds_b(time, y, x); + c : tds_c(time); + d : tds_d(time); +ASSIGN + init(c.value):= NULL; + next(c.value):= case + next(time) >= 2 & next(b.value) = NULL : next(a.value); + next(time) >= 2 & next(a.value) = NULL : next(b.value); + TRUE : NULL; + esac; + init(d.value):= NULL; + next(d.value):= case + next(time) >= 2 & d.value = NULL : c.value; + next(time) >= 2 & c.value = NULL & d.value != NULL : NULL; + TRUE : d.value; + esac; + +MODULE tds_a(time, x) +VAR + value : {NULL, 0, 1, -2, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -4, -3}; +ASSIGN + init(value):= x; + next(value):= case + next(time) = 1 : 1; + next(time) = 2 : 10; + TRUE : NULL; + esac; + +MODULE tds_b(time, y, x) +VAR + value : {NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; +ASSIGN + init(value):= NULL; + next(value):= case + next(time) = 3 : 3; + next(time) = 4 : 4; + next(time) = 5 : 5; + next(time) = 6 : next(y) - next(x); + TRUE : NULL; + esac; + +MODULE tds_c(time) +VAR + value : {NULL, 0, 1, -1, -2, 10, 2, 3, 4, 5, 6, 7, 8, 9, -3, -4}; +ASSIGN + +MODULE tds_d(time) +VAR + value : {NULL, 0, 1, -1, -2, 10, 2, 3, 4, 5, 6, 7, 8, 9, -3, -4}; ASSIGN diff --git a/sample/basic-main/basic-w-tds.tds b/sample/basic-main/basic-w-tds.tds new file mode 100644 index 0000000..9c43747 --- /dev/null +++ b/sample/basic-main/basic-w-tds.tds @@ -0,0 +1,137 @@ +INTERVAL: 0 ~ 20 + +x = -2 //redef =0 , context =0 +// usei aqui o x + + +//r = true // só deve alterar para o false logo depois se a condição for verdadeira (not evaluate) (mas deve escrever correto) + +z = true + +zeta = false + +if(not z){ + w = 1 +} + +if(zeta){ + r = false + if(z){ + u = false + } +} + +tdsA = { + portname : 'a', + data-time: {0: x, 1: 1, 2: 10, 21:4} +} + +//tdsB= { +// portname: 'b', +// data-time: {function-domain: x+x } +//} + +(tdsA) -{x == -2}> c // funciona +// FILTER COM DEF COMPLETA + +//tdsC = { +// portname: 'c', +// linked: {tdsA}, +// filter: x == -2 +//} + +//(tdsA) -{x == -2}> c // funciona + +//(tdsA,tdsB) ==> c // funciona +//(c) -||> d // funciona + +//tdsC = { +// portname : 'c', +// linked : {tdsA,tdsB} +//} // funciona + + +//(tdsA,tdsB) -||> d // temos erro como o esperado + +//tdsD = { +// portname : 'd', +// linked : {tdsA,tdsB}, +// delayed +//} // da erro (como esperado) + +C_TIME TO 2 + +//(tdsA) -||> d realiza a operação com warning + +//(tdsA) ==> c // funciona + +//tdsC = { +// portname : 'c', +// linked : {tdsA} +//} // funciona + +//(tdsA,tdsB) -> c // funciona + +//tdsC = { +// portname : 'c', +// linked : {tdsA,tdsB} +//} // funciona + +//(tdsA,tdsB) ==> c // funciona + + +//(c) ==> d // funciona + +//(c) -||> d // funciona + +x = -4 //redef =1 , context =2 + + +C_TIME TO 2 + +y = 5 + +//tdsB = { +// portname : 'b', +// data-time: {3: 3, 4:4, 5:5, 6:y-x} +//} + +// NOVA TDS b (in line) + +//tdsB= { +// portname: 'b', +// data-time: {function-domain: x-x } +//} + +//(tdsA,tdsB) ==> c // funciona + +//(tdsA,tdsB) -{x == 3}> c // funciona +//(tdsA) -{x == -2}> c // funciona +//(c) -||> d // funciona + + +C_TIME TO 3 + +x = -1 // corrigido + + +C_TIME TO 4 + +zeta = false + +z = true + +if(not zeta){ + w = true + y = 2 + if(w){ + u = false + } +} +else{ + y = 6 +} + +stu = x/y + + diff --git a/sample/basic-main/basic.tds b/sample/basic-main/basic.tds index 6db0358..796cc6f 100644 --- a/sample/basic-main/basic.tds +++ b/sample/basic-main/basic.tds @@ -1,25 +1,66 @@ INTERVAL: 0 ~ 20 +x = 2 + 2 -x = 1 +t = 4 * 5 -y = 30 +ABA = 4 * 7 + 3 -x = 20 +B = 3 + 4 * 7 +C = -3 + 4 * 7 -C_TIME = 2 +D = 4 - -3 // unários só conseguem ser mais a esquerda (corrigido) -x = 3 +ED = 3+4 - 2+2 -x= 4 +DIV = ED/2 -C_TIME = 3 +DIVC = 4*7+3/10 -y = 0 +P = (4*7+3)/10 -x = 80 +y = 4 + x -//condicaoTeste = true +// testamos todas as expressões não lógicas + +C_TIME = x + y + +//bn = 4*y+x + +z = NULL // temos que permitir isso na verdade... + +w = 'batata' + +a = true + +b = false + +logand = a and b + +lognot = not b + +logandT = a and not b + +logor = a or b + +//logIMP = a -> b +logIMP = not a -> not b + +logBIMP = not a <-> b + +lesst = x < y + +lesseq = x <= y + +great = x > y + +//greateq = x > a + +greateq = x >= y + +dif = x != y + +eq = x == y \ No newline at end of file diff --git a/sample/filter/expected-output/expected-filter.smv b/sample/filter/expected-output/expected-filter.smv new file mode 100644 index 0000000..3cef8df --- /dev/null +++ b/sample/filter/expected-output/expected-filter.smv @@ -0,0 +1,61 @@ +MODULE main +VAR + time: 0..20; + finalAutomata: filter(ports); + ports: portsModule(time, y, x); + x : 0..4; + y : 0..3; +ASSIGN + init(time) := 1; + next(time) := case + time < 20: time + 1; + TRUE: time; +esac; + init(x):= 0; + next(x):= case + next(time) = 2 : 4; + TRUE : x; + esac; + init(y):= 1; + next(y):= case + next(time) = 2 : 3; + TRUE : y; + esac; + +CTLSPEC AG (ports.b.value != NULL & time < 10); + + +MODULE filter(ports) +VAR + cs: {q0}; +TRANS + ((cs = q0 & ports.b.value = NULL & ports.a.value != NULL & !((next(ports.a.value) = 0) | (next(ports.a.value) = 1))) -> next(cs) = q0) & + ((cs = q0 & ports.a.value != NULL & ports.a.value = ports.b.value & (next(ports.a.value) = 0) | (next(ports.a.value) = 1)) -> next(cs) = q0); + +MODULE portsModule(time, y, x) +VAR + a : tds_a(time, y, x); + b : tds_b(time); +ASSIGN + init(b.value):= case + (a.value = 0) | (a.value = 1) : a.value; + TRUE : NULL; + esac; + next(b.value):= case + (next(a.value) = 0) | (next(a.value) = 1) : next(a.value); + TRUE : NULL; + esac; + +MODULE tds_a(time, y, x) +VAR + value : {NULL, 0, 1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -4, -3, -2, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}; +ASSIGN + init(value):= y - x + (time + 20) mod 2; + next(value):= next(y) - next(x) + (time + 20) mod 2; + +MODULE tds_b(time) +VAR + value : {NULL, 0, 1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 2, 3, 4, 5, 6, 7, 8, 9, -2, -3, -4, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}; +ASSIGN + + diff --git a/sample/filter/filter.tds b/sample/filter/filter.tds new file mode 100644 index 0000000..e9ecd9c --- /dev/null +++ b/sample/filter/filter.tds @@ -0,0 +1,23 @@ +INTERVAL: 1 ~ 20 + +x = 0 +y = I_TIME + +tdsA = { + portname : 'a', + data-time: {function-domain: y-x + (C_TIME + F_TIME) % 2} +} + +//tdsB = { +// portname: 'b', +// linked: {tdsA}, +// filter: (tdsA.value == 0) or (tdsA.value == 1) +//} + +// ou +(tdsA) -{(tdsA.value == 0) or (tdsA.value == 1)}> b + +C_TIME TO 2 + +x = 4 +y = 3 diff --git a/sample/filter/nuxmv.smv b/sample/filter/nuxmv.smv new file mode 100644 index 0000000..680c36a --- /dev/null +++ b/sample/filter/nuxmv.smv @@ -0,0 +1,34 @@ +MODULE main +VAR + time: 0..3; + finalAutomata: filter(time); +ASSIGN + init(time) := 0; + next(time) := case + time < 3: time + 1; + TRUE: time; +esac; + +MODULE filter(time) +VAR + ports: portsModule; + cs: {q0}; +TRANS + ((cs = q0 & ports.b[time] = NULL & ports.a[time] != NULL & TRUE) -> next(cs) = q0) & + ((cs = q0 & ports.a[time] != NULL & ports.a[time] = ports.b[time] & TRUE) -> next(cs) = q0); + +MODULE portsModule +FROZENVAR + a : array 0..5 of {NULL, 0, 1}; + b : array 0..5 of {NULL, 0, 1}; +ASSIGN + init(a[0]) := 1; + init(a[1]) := 0; + init(a[2]) := 1; + init(a[3]) := 0; + init(a[4]) := NULL; + init(b[0]) := NULL; + init(b[1]) := 0; + init(b[2]) := NULL; + init(b[3]) := 0; + init(b[4]) := 1; diff --git a/sample/merger-fifo/expected-output/expected-merger-fifo.smv b/sample/merger-fifo/expected-output/expected-merger-fifo.smv new file mode 100644 index 0000000..b8bdbcf --- /dev/null +++ b/sample/merger-fifo/expected-output/expected-merger-fifo.smv @@ -0,0 +1,149 @@ +MODULE main +VAR + time: 0..8; + automato: finalAutomata(ports); + ports: portsModule(time, x, y); + x : -4..0; + y : 0..7; + z : boolean; + zeta : boolean; + w_scope1_0 : 0..1; + r_scope1_1 : boolean; + u_scope1_1_2_0 : boolean; + w_scope1_2 : boolean; + u_scope1_2_2_0 : boolean; +ASSIGN + init(time) := 0; + next(time) := case + time < 8: time + 1; + TRUE: time; +esac; + init(x):= -2; + next(x):= case + next(time) = 2 : -4; + next(time) = 3 : -1; + TRUE : x; + esac; + init(y):= 0; + next(y):= case + next(time) = 2 : 5; + next(time) = 4 & !next(zeta) : 3; + next(time) = 4 & !!next(zeta) : 7; + TRUE : y; + esac; + init(z):= TRUE; + next(z):= case + next(time) = 4 : TRUE; + TRUE : z; + esac; + init(zeta):= FALSE; + next(zeta):= case + next(time) = 4 : FALSE; + TRUE : zeta; + esac; + init(w_scope1_0):= case + !z : 1; + TRUE : 0; + esac; + next(w_scope1_0):= w_scope1_0; + init(r_scope1_1):= case + zeta : FALSE; + TRUE : FALSE; + esac; + next(r_scope1_1):= r_scope1_1; + init(u_scope1_1_2_0):= case + zeta & z : FALSE; + TRUE : FALSE; + esac; + next(u_scope1_1_2_0):= u_scope1_1_2_0; + init(w_scope1_2):= FALSE; + next(w_scope1_2):= case + next(time) = 4 & !next(zeta) : TRUE; + TRUE : w_scope1_2; + esac; + init(u_scope1_2_2_0):= FALSE; + next(u_scope1_2_2_0):= case + next(time) = 4 & !next(zeta) & next(w_scope1_2) : FALSE; + TRUE : u_scope1_2_2_0; + esac; + +-- valida se em algum momento as portas param de concorrer (e continuam sem concorrer) (LTL) + +LTLSPEC F(G ( (ports.a.value != NULL & ports.b.value = NULL) + |(ports.a.value = NULL & ports.b.value != NULL) + | (ports.a.value = NULL & ports.b.value = NULL) )) ; + +-- valida se em algum momento as portas param de concorrer (e continuam sem concorrer) (CTL) +CTLSPEC EF(AG ( (ports.a.value != NULL & ports.b.value = NULL) + |(ports.a.value = NULL & ports.b.value != NULL) + | (ports.a.value = NULL & ports.b.value = NULL) ) ) ; + + + +MODULE finalAutomata(ports) +VAR + cs: {q0q0,q0p0,q0p1}; +ASSIGN + init(cs) := {q0q0}; +TRANS + ((cs = q0q0 & ports.b.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.a.value = ports.c.value & ports.c.value = 0) -> next(cs) = q0p0) & + ((cs = q0q0 & ports.b.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.a.value = ports.c.value & ports.c.value = 1) -> next(cs) = q0p1) & + ((cs = q0q0 & ports.a.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.b.value = ports.c.value & ports.c.value = 0) -> next(cs) = q0p0) & + ((cs = q0q0 & ports.a.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.b.value = ports.c.value & ports.c.value = 1) -> next(cs) = q0p1) & + ((cs = q0p0 & ports.a.value = NULL & ports.c.value = NULL & ports.b.value = NULL & ports.d.value = 0) -> next(cs) = q0q0) & + ((cs = q0p0) -> ((next(cs) != q0p1))) & + ((cs = q0p1 & ports.a.value = NULL & ports.c.value = NULL & ports.b.value = NULL & ports.d.value = 1) -> next(cs) = q0q0) & + ((cs = q0p1) -> ((next(cs) != q0p0))); + +MODULE portsModule(time, x, y) +VAR + a : tds_a(time); + b : tds_b(time, x, y); + c : tds_c(time); + d : tds_d(time); +ASSIGN + init(c.value):= case + b.value = NULL : a.value; + a.value = NULL : b.value; + TRUE : NULL; + esac; + next(c.value):= case + next(b.value) = NULL : next(a.value); + next(a.value) = NULL : next(b.value); + TRUE : NULL; + esac; + init(d.value):= NULL; + next(d.value):= case + next(time) > 2 & d.value = NULL : c.value; + next(time) > 2 & c.value = NULL & d.value != NULL : NULL; + TRUE : d.value; + esac; + +MODULE tds_a(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + init(value):= 0; + next(value):= case + next(time) = 1 : 1; + next(time) = 2 : 0; + TRUE : NULL; + esac; + +MODULE tds_b(time, x, y) +VAR + value : {NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; +ASSIGN + init(value):= (8 - (x - y)) mod 2; + next(value):= (8 - (next(x) - next(y))) mod 2; + +MODULE tds_c(time) +VAR + value : {NULL, 0, 1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19}; +ASSIGN + +MODULE tds_d(time) +VAR + value : {NULL, 0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 8, 9, 18, 19}; +ASSIGN + diff --git a/sample/merger-fifo/merger-fifo.tds b/sample/merger-fifo/merger-fifo.tds index 4b47ea4..8f029a3 100644 --- a/sample/merger-fifo/merger-fifo.tds +++ b/sample/merger-fifo/merger-fifo.tds @@ -1,36 +1,76 @@ -INTERVAL: 0 ~ 20 +INTERVAL: 0 ~ 8 -x = 2 //redef =0 , context =0 -// usei aqui o x -x = 30 //redef =1 , context =0 -// usei redef1 +x = -2 +y = 0 -//z = true +z = true -z = false // ERRO -> corrigido +zeta = false if(not z){ w = 1 } +if(zeta){ + r = false + if(z){ + u = false + } +} + +tdsA = { + portname : 'a', + data-time: {0: 0, 1: 1, 2: 0, 21:4} +} -C_TIME = 2 -x = 4 //redef =1 , context =2 -// estamos em time =2 e referenciamos redef1 -// fizemos várias operações que nem a de C_TIME = 3 ... (que geraria colisão = atualiza a condição anterior) +tdsB= { + portname: 'b', + data-time: {function-domain: (F_TIME-(x-y))% 2 } +} -C_TIME = 2 -x = 90 //redef =1 , context =2 // erro (caso de , variavel foi redefinida em time > 0)(unico que não funciona ainda) -y = 1 // e se esse y depender de x? ele vai estar olhando agora o x =5! NÃO O IGUAL A 4... +//tdsC = { +// portname: 'c', +// linked: {tdsA, tdsB} +// +//} +// ou +(tdsA,tdsB) ==> c -C_TIME = 3 -x = 80 // // usa redef(next) anterior , context =3 -// e como vamos lidar com INVAR? (a pensar ainda...? Criar um buffer invar! E escrever em ordem no final!, "utilidade") +C_TIME TO 2 -z = false // ERRO -> corrigido -if(not z){ - w = 1 +x = -4 + + +C_TIME TO 2 // statement sem efeito + +y = 5 + +(c) -||> d // funciona + + +C_TIME TO 3 + +x = -1 + + +C_TIME TO 4 + +zeta = false + +z = true + +if(not zeta){ + w = true + y = 3 + if(w){ + u = false + } +} +else{ + y = 7 } + + diff --git a/sample/merger-fifo/model-result.smv b/sample/merger-fifo/model-result.smv new file mode 100644 index 0000000..22acc4f --- /dev/null +++ b/sample/merger-fifo/model-result.smv @@ -0,0 +1,185 @@ +MODULE main +VAR + time: 0..8; + finalAutomata: finalAutomata(ports); + ports: portsModule(time, x, y); + x : -4..0; + y : 0..7; + z : boolean; + zeta : boolean; + w_scope1_0 : 0..1; + r_scope1_1 : boolean; + u_scope1_1_2_0 : boolean; + w_scope1_2 : boolean; + u_scope1_2_2_0 : boolean; +ASSIGN + init(time) := 0; + next(time) := case + time < 8: time + 1; + TRUE: time; +esac; + init(x):= -2; + next(x):= case + next(time) = 2 : -4; + next(time) = 3 : -1; + TRUE : x; + esac; + init(y):= 0; + next(y):= case + next(time) = 2 : 5; + next(time) = 4 & !next(zeta) : 3; + next(time) = 4 & !!next(zeta) : 7; + TRUE : y; + esac; + init(z):= TRUE; + next(z):= case + next(time) = 4 : TRUE; + TRUE : z; + esac; + init(zeta):= FALSE; + next(zeta):= case + next(time) = 4 : FALSE; + TRUE : zeta; + esac; + init(w_scope1_0):= case + !z : 1; + TRUE : 0; + esac; + next(w_scope1_0):= w_scope1_0; + init(r_scope1_1):= case + zeta : FALSE; + TRUE : FALSE; + esac; + next(r_scope1_1):= r_scope1_1; + init(u_scope1_1_2_0):= case + zeta & z : FALSE; + TRUE : FALSE; + esac; + next(u_scope1_1_2_0):= u_scope1_1_2_0; + init(w_scope1_2):= FALSE; + next(w_scope1_2):= case + next(time) = 4 & !next(zeta) : TRUE; + TRUE : w_scope1_2; + esac; + init(u_scope1_2_2_0):= FALSE; + next(u_scope1_2_2_0):= case + next(time) = 4 & !next(zeta) & next(w_scope1_2) : FALSE; + TRUE : u_scope1_2_2_0; + esac; + + + +-- valida concorrencia entre portas A e B + +--CTLSPEC AG( ( ports.a.value != NULL & ports.b.value = NULL) +-- |(ports.a.value = NULL & ports.b.value != NULL) +-- | (ports.a.value = NULL & ports.b.value = NULL)) ; + +-- valida se em algum momento elas param de concorrer (e continuam sem concorrer) (LTL) +--LTLSPEC F(G ( (ports.a.value != NULL & ports.b.value = NULL) +-- |(ports.a.value = NULL & ports.b.value != NULL) +-- | (ports.a.value = NULL & ports.b.value = NULL) )) ; + +-- valida se em algum momento elas param de concorrer (e continuam sem concorrer) (CTL) +--CTLSPEC EF(AG ( (ports.a.value != NULL & ports.b.value = NULL) +-- |(ports.a.value = NULL & ports.b.value != NULL) +-- | (ports.a.value = NULL & ports.b.value = NULL) ) ) ; + + +-- verifica se a porta C eventualmente esperou o fim do processamento de D (ex daniel ou o meu) + +--LTLSPEC F((ports.d.value != NULL) & ports.c.value = NULL); + + +MODULE merger1(ports) +VAR + cs: {q0}; +TRANS + ((cs = q0 & ports.b.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.a.value = ports.c.value & FALSE) -> next(cs) = q0) & + ((cs = q0 & ports.a.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.b.value = ports.c.value & FALSE) -> next(cs) = q0); + +MODULE fifo2(ports) +VAR + cs: {q0,p0,p1}; +ASSIGN + init(cs) := {q0}; +TRANS + ((cs = q0 & ports.a.value = NULL & ports.b.value = NULL & ports.d.value = NULL & ports.c.value = 0 & FALSE) -> next(cs) = p0) & + ((cs = q0 & ports.a.value = NULL & ports.b.value = NULL & ports.d.value = NULL & ports.c.value = 1 & FALSE) -> next(cs) = p1) & + ((cs = p0 & ports.a.value = NULL & ports.c.value = NULL & ports.b.value = NULL & ports.d.value = 0) -> next(cs) = q0) & + ((cs = p0) -> ((next(cs) != p1))) & + ((cs = p1 & ports.a.value = NULL & ports.c.value = NULL & ports.b.value = NULL & ports.d.value = 1) -> next(cs) = q0) & + ((cs = p1) -> ((next(cs) != p0))); + +MODULE finalAutomata(ports) +VAR + prod1: merger1(ports); + prod2: fifo2(ports); + cs: {q0q0,q0p0,q0p1}; +ASSIGN + init(cs) := {q0q0}; +TRANS + ((cs = q0q0 & ports.b.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.a.value = ports.c.value & ports.c.value = 0) -> next(cs) = q0p0) & + ((cs = q0q0 & ports.b.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.a.value = ports.c.value & ports.c.value = 1) -> next(cs) = q0p1) & + ((cs = q0q0 & ports.a.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.b.value = ports.c.value & ports.c.value = 0) -> next(cs) = q0p0) & + ((cs = q0q0 & ports.a.value = NULL & ports.d.value = NULL & ports.c.value != NULL & ports.b.value = ports.c.value & ports.c.value = 1) -> next(cs) = q0p1) & + ((cs = q0p0) -> ((next(cs) != q0p1))) & + ((cs = q0p1) -> ((next(cs) != q0p0))); +INVAR + (((prod1.cs = q0) & (prod2.cs = q0)) <-> (cs = q0q0)) & + (((prod1.cs = q0) & (prod2.cs = p0)) <-> (cs = q0p0)) & + (((prod1.cs = q0) & (prod2.cs = p1)) <-> (cs = q0p1)); + +MODULE portsModule(time, x, y) +VAR + a : tds_a(time); + b : tds_b(time, x, y); + c : tds_c(time); + d : tds_d(time); +ASSIGN + init(c.value):= case + b.value = NULL : a.value; + a.value = NULL : b.value; + TRUE : NULL; + esac; + next(c.value):= case + next(b.value) = NULL : next(a.value); + next(a.value) = NULL : next(b.value); + TRUE : NULL; + esac; + init(d.value):= NULL; + next(d.value):= case + next(time) > 2 & d.value = NULL : c.value; + next(time) > 2 & c.value = NULL & d.value != NULL : NULL; + TRUE : d.value; + esac; + +MODULE tds_a(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + init(value):= 0; + next(value):= case + next(time) = 1 : 1; + next(time) = 2 : 0; + TRUE : NULL; + esac; + +MODULE tds_b(time, x, y) +VAR + value : {NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; +ASSIGN + init(value):= (8 - (x - y)) mod 2; + next(value):= (8 - (next(x) - next(y))) mod 2; + +MODULE tds_c(time) +VAR + value : {NULL, 0, 1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19}; +ASSIGN + +MODULE tds_d(time) +VAR + value : {NULL, 0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 8, 9, 18, 19}; +ASSIGN + + diff --git a/sample/merger-fifo/merger-fifo.smv b/sample/merger-fifo/old-general-prop/merger-fifo.smv similarity index 100% rename from sample/merger-fifo/merger-fifo.smv rename to sample/merger-fifo/old-general-prop/merger-fifo.smv diff --git a/sample/merger-fifo/old-general-prop/merger-fifo.tds b/sample/merger-fifo/old-general-prop/merger-fifo.tds new file mode 100644 index 0000000..4b47ea4 --- /dev/null +++ b/sample/merger-fifo/old-general-prop/merger-fifo.tds @@ -0,0 +1,36 @@ +INTERVAL: 0 ~ 20 + +x = 2 //redef =0 , context =0 +// usei aqui o x +x = 30 //redef =1 , context =0 +// usei redef1 + +//z = true + +z = false // ERRO -> corrigido + +if(not z){ + w = 1 +} + + +C_TIME = 2 +x = 4 //redef =1 , context =2 +// estamos em time =2 e referenciamos redef1 +// fizemos várias operações que nem a de C_TIME = 3 ... (que geraria colisão = atualiza a condição anterior) + +C_TIME = 2 +x = 90 //redef =1 , context =2 // erro (caso de , variavel foi redefinida em time > 0)(unico que não funciona ainda) +y = 1 // e se esse y depender de x? ele vai estar olhando agora o x =5! NÃO O IGUAL A 4... + + +C_TIME = 3 +x = 80 // // usa redef(next) anterior , context =3 + +// e como vamos lidar com INVAR? (a pensar ainda...? Criar um buffer invar! E escrever em ordem no final!, "utilidade") + +z = false // ERRO -> corrigido + +if(not z){ + w = 1 +} diff --git a/sample/sequenciador/expected-output/expected-seq.smv b/sample/sequenciador/expected-output/expected-seq.smv new file mode 100644 index 0000000..a381cd8 --- /dev/null +++ b/sample/sequenciador/expected-output/expected-seq.smv @@ -0,0 +1,205 @@ +MODULE main +VAR + time: 0..8; + automato: finalAutomata(ports); + ports: portsModule(time); +ASSIGN + init(time) := 1; + next(time) := case + time < 8: time + 1; + TRUE: time; +esac; + +CTLSPEC A [ (ports.e.value = NULL) U ( AG ((ports.e.value != NULL & ports.a.value != NULL) & (time - 2 <= 3 )) )]; + +MODULE finalAutomata(ports) +VAR + cs: {q0q0q0q0q0,q0q0q0q0p0,q0q0q0q0p1,q0q0p0q0q0,q0q0p0q0p0,q0q0p0q0p1,q0q0p1q0q0,q0q0p1q0p0,q0q0p1q0p1,p0q0q0q0q0,p0q0q0q0p0,p0q0q0q0p1,p0q0p0q0q0,p0q0p0q0p0,p0q0p0q0p1,p0q0p1q0q0,p0q0p1q0p0,p0q0p1q0p1,p1q0q0q0q0,p1q0q0q0p0,p1q0q0q0p1,p1q0p0q0q0,p1q0p0q0p0,p1q0p0q0p1,p1q0p1q0q0,p1q0p1q0p0,p1q0p1q0p1}; +ASSIGN + init(cs) := {q0q0q0q0q0}; +TRANS + ((cs = q0q0q0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0q0) -> ((next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 0) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 0) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 1) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 1) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p0q0p0) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 0) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p0q0p0) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 0) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p0q0p1) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 1) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p0q0p1) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 1) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p1q0p0) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 0) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p1q0p0) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 0) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p1q0p1) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 1) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p1q0p1) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0))) & + ((cs = p0q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p0) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p0) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 0) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p1) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 1) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p1) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0q0) + & + ((cs = p1q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0q0) + & + ((cs = p1q0q0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p0) + & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 0) -> next(cs) = q0q0p0q0q0) + & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p0) + & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 0) -> next(cs) = q0q0p1q0q0) + & + ((cs = p1q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p1) + & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 1) -> next(cs) = q0q0p0q0q0) + & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p1) + & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 1) -> next(cs) = q0q0p1q0q0) + & + ((cs = p1q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0p0q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) + & + ((cs = p1q0p0q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) + & + ((cs = p1q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = p1q0p1q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = p1q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0p0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = 0) -> next(cs) = p1q0p1q0q0) & + ((cs = p1q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0p1 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = p1q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0))); + +MODULE portsModule(time) +VAR + a : tds_a(time); + e : tds_e(time); + b : tds_b(time); + f : tds_f(time); + c : tds_c(time); + g : tds_g(time); +ASSIGN + init(e.value):= NULL; + next(e.value):= case + e.value = NULL : a.value; + a.value = NULL & e.value != NULL : NULL; + TRUE : e.value; + esac; + init(b.value):= e.value; + next(b.value):= next(e.value); + init(f.value):= NULL; + next(f.value):= case + f.value = NULL : e.value; + e.value = NULL & f.value != NULL : NULL; + TRUE : f.value; + esac; + init(c.value):= f.value; + next(c.value):= next(f.value); + init(g.value):= NULL; + next(g.value):= case + g.value = NULL : f.value; + f.value = NULL & g.value != NULL : NULL; + TRUE : g.value; + esac; + +MODULE tds_a(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + init(value):= 0; + next(value):= case + next(time) = 2 : 1; + next(time) = 3 : 0; + next(time) = 4 : 1; + TRUE : NULL; + esac; + +MODULE tds_e(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_b(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_f(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_c(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_g(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + diff --git a/sample/sequenciador/input-passado-para-o-reo2nuXmv b/sample/sequenciador/input-passado-para-o-reo2nuXmv new file mode 100644 index 0000000..3e4b6ea --- /dev/null +++ b/sample/sequenciador/input-passado-para-o-reo2nuXmv @@ -0,0 +1,5 @@ +fifo(a,e) +sync(e,b) +fifo(e,f) +sync(f,c) +fifo(f,g) diff --git a/sample/sequenciador/resultado-sequenciador.smv b/sample/sequenciador/resultado-sequenciador.smv new file mode 100644 index 0000000..b132d2a --- /dev/null +++ b/sample/sequenciador/resultado-sequenciador.smv @@ -0,0 +1,187 @@ +MODULE main +VAR + time: 0..8; + automato: finalAutomata(ports); + ports: portsModule(time); +ASSIGN + init(time) := 1; + next(time) := case + time < 8: time + 1; + TRUE: time; +esac; + +MODULE finalAutomata(ports) +VAR + cs: {q0q0q0q0q0,q0q0q0q0p0,q0q0q0q0p1,q0q0p0q0q0,q0q0p0q0p0,q0q0p0q0p1,q0q0p1q0q0,q0q0p1q0p0,q0q0p1q0p1,p0q0q0q0q0,p0q0q0q0p0,p0q0q0q0p1,p0q0p0q0q0,p0q0p0q0p0,p0q0p0q0p1,p0q0p1q0q0,p0q0p1q0p0,p0q0p1q0p1,p1q0q0q0q0,p1q0q0q0p0,p1q0q0q0p1,p1q0p0q0q0,p1q0p0q0p0,p1q0p0q0p1,p1q0p1q0q0,p1q0p1q0p0,p1q0p1q0p1}; +ASSIGN + init(cs) := {q0q0q0q0q0}; +TRANS + ((cs = q0q0q0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0q0) -> ((next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 0) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0q0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 0) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 1) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0q0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 1) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0p0q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p0q0p0) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 0) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p0q0p0) & + ((cs = q0q0p0q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 0) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p0q0p1) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 1) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p0q0p1) & + ((cs = q0q0p0q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 1) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 0 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0p1q0q0 & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.a.value = 1 & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p1q0p0) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 0) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p1q0p0) & + ((cs = q0q0p1q0p0 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 0) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 0) -> next(cs) = p0q0p1q0p1) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 0 & ports.g.value = 1) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.a.value = 1) -> next(cs) = p1q0p1q0p1) & + ((cs = q0q0p1q0p1 & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.a.value = 1 & ports.g.value = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0))) & + ((cs = p0q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p0) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p0) & + ((cs = p0q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 0) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p1) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 1) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p1) & + ((cs = p0q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 0 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p0q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p0q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p0q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p0q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p0q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p0q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p1q0q0q0q0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p1q0q0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p0) & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p0) & + ((cs = p1q0q0q0p0 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 0) -> next(cs) = q0q0p1q0q0) & + ((cs = p1q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0) -> next(cs) = q0q0p0q0p1) & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 0 & ports.g.value = 1) -> next(cs) = q0q0p0q0q0) & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1) -> next(cs) = q0q0p1q0p1) & + ((cs = p1q0q0q0p1 & ports.a.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.e.value = 1 & ports.e.value != NULL & ports.e.value = ports.b.value & ports.e.value = 1 & ports.g.value = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p1q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p0q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = p1q0p0q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 0 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = p1q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p1q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + & + ((cs = p1q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = p1q0p1q0q0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.g.value = NULL & ports.f.value = 1 & ports.f.value != NULL & ports.f.value = ports.c.value & ports.f.value = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = p1q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0p0 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = 0) -> next(cs) = p1q0p1q0q0) & + ((cs = p1q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0p1 & ports.a.value = NULL & ports.e.value = NULL & ports.b.value = NULL & ports.f.value = NULL & ports.c.value = NULL & ports.g.value = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = p1q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0))); + +MODULE portsModule(time) +VAR + a : tds_a(time); + e : tds_e(time); + b : tds_b(time); + f : tds_f(time); + c : tds_c(time); + g : tds_g(time); +ASSIGN + init(e.value):= NULL; + next(e.value):= case + e.value = NULL : a.value; + a.value = NULL & e.value != NULL : NULL; + TRUE : e.value; + esac; + init(b.value):= e.value; + next(b.value):= next(e.value); + init(f.value):= NULL; + next(f.value):= case + f.value = NULL : e.value; + e.value = NULL & f.value != NULL : NULL; + TRUE : f.value; + esac; + init(c.value):= f.value; + next(c.value):= next(f.value); + init(g.value):= NULL; + next(g.value):= case + g.value = NULL : f.value; + f.value = NULL & g.value != NULL : NULL; + TRUE : g.value; + esac; + +MODULE tds_a(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + init(value):= 0; + next(value):= case + next(time) = 2 : 1; + next(time) = 3 : 0; + next(time) = 4 : 1; + TRUE : NULL; + esac; + +MODULE tds_e(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_b(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_f(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_c(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + +MODULE tds_g(time) +VAR + value : {NULL, 0, 1}; +ASSIGN + diff --git a/sample/sequenciador/seq.smv b/sample/sequenciador/seq.smv new file mode 100644 index 0000000..9811048 --- /dev/null +++ b/sample/sequenciador/seq.smv @@ -0,0 +1,173 @@ +MODULE main +VAR + time: 0..3; + automato: finalAutomata(time); +ASSIGN + init(time) := 0; + next(time) := case + time < 3: time + 1; + TRUE: time; +esac; + +MODULE finalAutomata(time) +VAR + ports: portsModule; + cs: {q0q0q0q0q0,q0q0q0q0p0,q0q0q0q0p1,q0q0p0q0q0,q0q0p0q0p0,q0q0p0q0p1,q0q0p1q0q0,q0q0p1q0p0,q0q0p1q0p1,p0q0q0q0q0,p0q0q0q0p0,p0q0q0q0p1,p0q0p0q0q0,p0q0p0q0p0,p0q0p0q0p1,p0q0p1q0q0,p0q0p1q0p0,p0q0p1q0p1,p1q0q0q0q0,p1q0q0q0p0,p1q0q0q0p1,p1q0p0q0q0,p1q0p0q0p0,p1q0p0q0p1,p1q0p1q0q0,p1q0p1q0p0,p1q0p1q0p1}; +ASSIGN + init(cs) := {q0q0q0q0q0}; +TRANS + ((cs = q0q0q0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0q0) -> ((next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0q0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0q0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 0 & ports.g[time] = 0) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0q0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 1 & ports.g[time] = 0) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0q0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0q0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 0 & ports.g[time] = 1) -> next(cs) = p0q0q0q0q0) & + ((cs = q0q0q0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0q0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 1 & ports.g[time] = 1) -> next(cs) = p1q0q0q0q0) & + ((cs = q0q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0 & ports.f[time] = 0 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0p0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0 & ports.f[time] = 0 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 1) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0p0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1 & ports.f[time] = 0 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0p0q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1 & ports.f[time] = 0 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0p0q0p0) & + ((cs = q0q0p0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 0 & ports.g[time] = 0) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0p0q0p0) & + ((cs = q0q0p0q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 1 & ports.g[time] = 0) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0p0q0p1) & + ((cs = q0q0p0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 0 & ports.g[time] = 1) -> next(cs) = p0q0p0q0q0) & + ((cs = q0q0p0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0p0q0p1) & + ((cs = q0q0p0q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 1 & ports.g[time] = 1) -> next(cs) = p1q0p0q0q0) & + ((cs = q0q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0 & ports.f[time] = 1 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 0) -> next(cs) = p0q0q0q0p0) & + ((cs = q0q0p1q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0 & ports.f[time] = 1 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 1) -> next(cs) = p0q0q0q0p1) & + ((cs = q0q0p1q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1 & ports.f[time] = 1 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = q0q0p1q0q0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1 & ports.f[time] = 1 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = q0q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0p1q0p0) & + ((cs = q0q0p1q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 0 & ports.g[time] = 0) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0p1q0p0) & + ((cs = q0q0p1q0p0 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 1 & ports.g[time] = 0) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p1))) & + ((cs = q0q0p1q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 0) -> next(cs) = p0q0p1q0p1) & + ((cs = q0q0p1q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 0 & ports.g[time] = 1) -> next(cs) = p0q0p1q0q0) & + ((cs = q0q0p1q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.a[time] = 1) -> next(cs) = p1q0p1q0p1) & + ((cs = q0q0p1q0p1 & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.a[time] = 1 & ports.g[time] = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = q0q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0))) & + ((cs = p0q0q0q0q0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0q0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p0q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0) -> next(cs) = q0q0p0q0p0) & + ((cs = p0q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0 & ports.g[time] = 0) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1) -> next(cs) = q0q0p1q0p0) & + ((cs = p0q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1 & ports.g[time] = 0) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p0q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0) -> next(cs) = q0q0p0q0p1) & + ((cs = p0q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0 & ports.g[time] = 1) -> next(cs) = q0q0p0q0q0) & + ((cs = p0q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1) -> next(cs) = q0q0p1q0p1) & + ((cs = p0q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 0 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1 & ports.g[time] = 1) -> next(cs) = q0q0p1q0q0) & + ((cs = p0q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p0q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0q0q0q0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0) -> next(cs) = q0q0p0q0q0) + & + ((cs = p1q0q0q0q0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1) -> next(cs) = q0q0p1q0q0) + & + ((cs = p1q0q0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0) -> next(cs) = q0q0p0q0p0) + & + ((cs = p1q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0 & ports.g[time] = 0) -> next(cs) = q0q0p0q0q0) + & + ((cs = p1q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1) -> next(cs) = q0q0p1q0p0) + & + ((cs = p1q0q0q0p0 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1 & ports.g[time] = 0) -> next(cs) = q0q0p1q0q0) + & + ((cs = p1q0q0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0) -> next(cs) = q0q0p0q0p1) + & + ((cs = p1q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 0 & ports.g[time] = 1) -> next(cs) = q0q0p0q0q0) + & + ((cs = p1q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1) -> next(cs) = q0q0p1q0p1) + & + ((cs = p1q0q0q0p1 & ports.a[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.e[time] = 1 & ports.e[time] != NULL & ports.e[time] = ports.b[time] & ports.e[time] = 1 & ports.g[time] = 1) -> next(cs) = q0q0p1q0q0) + & + ((cs = p1q0q0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p1q0p0) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0p0q0q0 & ports.a[time] = NULL & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.f[time] = 0 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 0) -> next(cs) = p1q0q0q0p0) + & + ((cs = p1q0p0q0q0 & ports.a[time] = NULL & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.f[time] = 0 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 1) -> next(cs) = p1q0q0q0p1) + & + ((cs = p1q0p0q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0p0q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) + & + ((cs = p1q0p0q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p1q0q0) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0q0 & ports.a[time] = NULL & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.f[time] = 1 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 0) -> next(cs) = p1q0q0q0p0) & + ((cs = p1q0p1q0q0 & ports.a[time] = NULL & ports.e[time] = NULL & ports.b[time] = NULL & ports.g[time] = NULL & ports.f[time] = 1 & ports.f[time] != NULL & ports.f[time] = ports.c[time] & ports.f[time] = 1) -> next(cs) = p1q0q0q0p1) & + ((cs = p1q0p1q0q0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0p0 & ports.a[time] = NULL & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = 0) -> next(cs) = p1q0p1q0q0) & + ((cs = p1q0p1q0p0) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p1))) & + ((cs = p1q0p1q0p1 & ports.a[time] = NULL & ports.e[time] = NULL & ports.b[time] = NULL & ports.f[time] = NULL & ports.c[time] = NULL & ports.g[time] = 1) -> next(cs) = p1q0p1q0q0) & + ((cs = p1q0p1q0p1) -> ((next(cs) != q0q0q0q0q0) & (next(cs) != q0q0q0q0p0) & (next(cs) != q0q0q0q0p1) & (next(cs) != q0q0p0q0q0) & (next(cs) != q0q0p0q0p0) & (next(cs) != q0q0p0q0p1) & (next(cs) != q0q0p1q0q0) & (next(cs) != q0q0p1q0p0) & (next(cs) != q0q0p1q0p1) & (next(cs) != p0q0q0q0q0) & (next(cs) != p0q0q0q0p0) & (next(cs) != p0q0q0q0p1) & (next(cs) != p0q0p0q0q0) & (next(cs) != p0q0p0q0p0) & (next(cs) != p0q0p0q0p1) & (next(cs) != p0q0p1q0q0) & (next(cs) != p0q0p1q0p0) & (next(cs) != p0q0p1q0p1) & (next(cs) != p1q0q0q0q0) & (next(cs) != p1q0q0q0p0) & (next(cs) != p1q0q0q0p1) & (next(cs) != p1q0p0q0q0) & (next(cs) != p1q0p0q0p0) & (next(cs) != p1q0p0q0p1) & (next(cs) != p1q0p1q0p0))); + +MODULE portsModule +FROZENVAR + a : array 0..5 of {NULL, 0, 1}; + e : array 0..5 of {NULL, 0, 1}; + b : array 0..5 of {NULL, 0, 1}; + f : array 0..5 of {NULL, 0, 1}; + c : array 0..5 of {NULL, 0, 1}; + g : array 0..5 of {NULL, 0, 1}; +ASSIGN + init(a[0]) := 1; + init(a[1]) := 0; + init(a[2]) := 1; + init(a[3]) := 0; + init(a[4]) := NULL; + init(b[0]) := NULL; + init(b[1]) := 0; + init(b[2]) := NULL; + init(b[3]) := 0; + init(b[4]) := 1; + init(e[0]) := 0; + init(e[1]) := 1; + init(e[2]) := NULL; + init(e[3]) := 0; + init(e[4]) := 1; + init(f[0]) := 1; + init(f[1]) := 1; + init(f[2]) := 0; + init(f[3]) := 1; + init(f[4]) := NULL; + init(c[0]) := 1; + init(c[1]) := 1; + init(c[2]) := 0; + init(c[3]) := 0; + init(c[4]) := 1; + init(g[0]) := NULL; + init(g[1]) := 1; + init(g[2]) := NULL; + init(g[3]) := 1; + init(g[4]) := NULL; diff --git a/sample/sequenciador/seq.tds b/sample/sequenciador/seq.tds new file mode 100644 index 0000000..af82c50 --- /dev/null +++ b/sample/sequenciador/seq.tds @@ -0,0 +1,12 @@ +INTERVAL: 1 ~ 8 + +tdsA = { + portname : 'a', + data-time: {1: 0, 2: 1, 3:0, 4:1} +} + +(tdsA) -||> e +(e) ==> b +(e) -||> f +(f) ==> c +(f) -||> g \ No newline at end of file diff --git a/src/EnvController.c b/src/EnvController.c new file mode 100644 index 0000000..993e704 --- /dev/null +++ b/src/EnvController.c @@ -0,0 +1,376 @@ +// +// Created by mateus on 22/03/2021. +// + +#include "../headers/EnvController.h" +#include +#include +#include + +void setUpTypeSetDict(EnvController* controller){ + char** dict = malloc(sizeof(char*)*TYPE_SET_DIR_SIZE); + int i; + for (i = 0; i < TYPE_SET_DIR_SIZE ; i++) { + dict[i] = NULL; + } + controller->typeSetWords = dict; + addTypeSetWordToDict("0",controller); + addTypeSetWordToDict("1",controller); + addTypeSetWordToDict("NULL",controller); +} + + +EnvController *createController(int enableInteractive) { + + + + EnvController* Hcontrol = malloc(sizeof(EnvController)); + Hcontrol->interactiveMode = enableInteractive; + Hcontrol->H_AUTOMATA_CURRENT_SIZE = 0; + Hcontrol->H_PORTS_CURRENT_SIZE = 0; + Hcontrol->PORTS_INFO_CURRENT_SIZE = 0; + Hcontrol->H_FUNCTION_CURRENT_SIZE = 0; + + Hcontrol->originalPorts = createTable(SMV_PORTS, NULL, 0, 0, -1); + Hcontrol->mainInfo = createTable(SMV_V_MAIN, NULL, 0, 0, -1); + Hcontrol->functionsInfo = malloc(sizeof(STable*)*DEFAULT_HEADERS_AUX_SIZE); + Hcontrol->portsInfo = malloc(sizeof(STable*)*DEFAULT_HEADERS_AUX_SIZE); + + Hcontrol->MAIN = NULL; + Hcontrol->AUTOMATA_RELATED = malloc(sizeof(HeaderSmv*)*DEFAULT_HEADERS_AUX_SIZE); + Hcontrol->PORTS_RELATED = malloc(sizeof(HeaderSmv*)*DEFAULT_HEADERS_AUX_SIZE); + Hcontrol->FUNCTIONS = malloc(sizeof(HeaderSmv*)*DEFAULT_HEADERS_AUX_SIZE); + + Hcontrol->expectedPorts = 0; + Hcontrol->validPorts = 0; + Hcontrol->declaredPortsNumber= 0; + Hcontrol->IO_RELATION = 0; + Hcontrol->multiPortDeclartion = 0; + Hcontrol->declaredPorts = malloc(sizeof(TDS*)*DEFAULT_HEADERS_AUX_SIZE); // NULL até sabermos o intervalo de tempo + Hcontrol->currentTDScontext = NULL; + + int i; + for (i = 0; i < DEFAULT_HEADERS_AUX_SIZE; i++) { + Hcontrol->functionsInfo[i] = NULL; + Hcontrol->portsInfo[i] = NULL; + Hcontrol->AUTOMATA_RELATED[i] = NULL; + Hcontrol->PORTS_RELATED[i] = NULL; + Hcontrol->FUNCTIONS[i] = NULL; + } + + setUpTypeSetDict(Hcontrol); + Hcontrol->modelHasFilter = 0; + Hcontrol->automatasToChange = NULL; + Hcontrol->F_AUTOMATAS_CHANGE_POINTER = 0; + Hcontrol->filterContext = 0; + Hcontrol->modelHasFinalAutomata = 0; + Hcontrol->filterUsed = 0; + Hcontrol->relationRef = 0; + return Hcontrol; +} + +void letGoHeadersStruct(EnvController *H) { + + letgoHeader(H->MAIN); + letGoRelatedHeaders(H->AUTOMATA_RELATED, H->H_AUTOMATA_CURRENT_SIZE); + letGoRelatedHeaders(H->PORTS_RELATED, H->H_PORTS_CURRENT_SIZE); + letGoRelatedHeaders(H->FUNCTIONS, H->H_FUNCTION_CURRENT_SIZE); + + letgoTable(H->mainInfo); + // assim como temos n headers de função temos n tabelas de simbolos auxiliares que pode ou não ter sido liberada + // antecipidamente (quando a função já terminou de ser escrita como smv) + if(H->functionsInfo){ + int i; + for (i=0; i < H->H_FUNCTION_CURRENT_SIZE; i++){ + if(H->functionsInfo[i]){ + letgoTable(H->functionsInfo[i]); + } + } + } + if(H->portsInfo){ + int i; + for (i=0; i < H->PORTS_INFO_CURRENT_SIZE; i++){ + if(H->portsInfo[i]){ + letgoTable(H->portsInfo[i]); + } + } + } + if(H->portsInfo){ + free(H->portsInfo); + H->portsInfo = NULL; + } + + if(H->typeSetWords){ + int i; + for (i = 0; i < TYPE_SET_DIR_SIZE; i++) { + if(H->typeSetWords[i]){ + free(H->typeSetWords[i]); + } + } + } + + if(H->declaredPorts){ + free(H->declaredPorts); + H->declaredPorts = NULL; + } + if(H->automatasToChange){ + free(H->automatasToChange); + H->automatasToChange = NULL; + } + letgoTable(H->originalPorts); + free(H); +} + + +void letGoHeaderControl(EnvController* Hcontrol) { + letGoHeadersStruct(Hcontrol); +} + +void printAllHeaders(EnvController* Hcontrol){ + int i; + printHeader(Hcontrol->MAIN); + + for (i = 0; i < Hcontrol->H_FUNCTION_CURRENT_SIZE; i++){ + printHeader(Hcontrol->FUNCTIONS[i]); + } + for (i = 0; i < Hcontrol->H_AUTOMATA_CURRENT_SIZE; i++){ + printHeader(Hcontrol->AUTOMATA_RELATED[i]); + } + for (i = 0; i < Hcontrol->H_PORTS_CURRENT_SIZE; i++){ + printHeader(Hcontrol->PORTS_RELATED[i]); + } +} + +HeaderSmv* accessHeader(EnvController* controller, smvtype cat, int indexOfHeader){ + HeaderSmv* toReturn = NULL; + if(cat == MAIN){ + toReturn = controller->MAIN; + } + + if(cat == AUTOMATA){ + toReturn = indexOfHeader >= 0? controller->AUTOMATA_RELATED[indexOfHeader] : controller->AUTOMATA_RELATED[controller->H_AUTOMATA_CURRENT_SIZE-1]; + } + if(cat == PORTS){ + toReturn = indexOfHeader >= 0? controller->PORTS_RELATED[indexOfHeader] : controller->PORTS_RELATED[controller->H_PORTS_CURRENT_SIZE-1]; + } + + if(cat == FUNCTION_SMV){ + toReturn = indexOfHeader >= 0? controller->FUNCTIONS[indexOfHeader] : controller->FUNCTIONS[controller->H_FUNCTION_CURRENT_SIZE-1]; + } + + if(!toReturn){ + fprintf(stderr, "[accessHeader] INVALID SMV TYPE FOR OPERATION"); + exit(-1); + } + return toReturn; +} + + +STable* accessSmvInfo(EnvController* controller, smvtype cat, int SMV_INFO_ID){ + if(cat == MAIN){ + return controller->mainInfo; + } + if(SMV_INFO_ID < controller->H_FUNCTION_CURRENT_SIZE && cat == FUNCTION_SMV){ + return SMV_INFO_ID >= 0? controller->functionsInfo[SMV_INFO_ID] : controller->functionsInfo[controller->H_FUNCTION_CURRENT_SIZE-1]; + } + if(SMV_INFO_ID < controller->H_PORTS_CURRENT_SIZE && cat == PORTS){ + return SMV_INFO_ID >= 0? controller->portsInfo[SMV_INFO_ID] : controller->portsInfo[controller->PORTS_INFO_CURRENT_SIZE-1]; + } + if(cat == AUTOMATA){ + return NULL; // melhorar, apesar que sabe-se que não tem operação em tabela de simbolos para automato (por enquanto) + } + fprintf(stderr, "[accessSmvInfo] INVALID SMV TYPE FOR OPERATION"); + exit(-1); +} + +void addNewHeader(EnvController* controller, HeaderSmv* newHeader){ + + if(newHeader->type == MAIN){ + controller->MAIN = newHeader; + } + if(newHeader->type == AUTOMATA){ + controller->AUTOMATA_RELATED[controller->H_AUTOMATA_CURRENT_SIZE] = newHeader; + controller->H_AUTOMATA_CURRENT_SIZE++; + } + if(newHeader->type == PORTS){ + controller->PORTS_RELATED[controller->H_PORTS_CURRENT_SIZE] = newHeader; + controller->H_PORTS_CURRENT_SIZE++; + } + if(newHeader->type == FUNCTION_SMV ){ + controller->FUNCTIONS[controller->H_FUNCTION_CURRENT_SIZE] = newHeader; + controller->H_FUNCTION_CURRENT_SIZE++; + } +} + +void addNewAuxInfo(EnvController* controller, STable* newTableInfo){ + if(newTableInfo->type == SMV_PORTS){ + controller->portsInfo[controller->PORTS_INFO_CURRENT_SIZE] = newTableInfo; + controller->PORTS_INFO_CURRENT_SIZE++; + } +} + + + +void validateTdsDeclaration(char* declarationName, EnvController* controller){ + TableEntry* expected_entry = lookup(controller->originalPorts,declarationName); + if(expected_entry){ + Object* info = expected_entry->val; + int* isDeclared = info->values[0]; + if(!(*isDeclared)){ + controller->validPorts++; + *isDeclared = 1; + } + else{ + controller->multiPortDeclartion = 1; + fprintf(stderr,"ERROR: Same TDS redeclared. Name: %s\n",declarationName); + exit(-1); + } + } +} + +/** + * Método auxiliar que para cada header de autta passado atualiza a referencia de sua variavel que tenha filter e/ou + * atualiza a referencia em main. Colocando um parametro novo nessa referencia + * @param controller o controlador de ambiente + * @param paramName a string do parametro + * @param automata o header do automato + */ +void addParamToAutomata(EnvController* controller, char* paramName, HeaderSmv* automata){ + if(addParamToModule(automata,paramName)){ + // mudar o main (se for o final automata) e também o ponto de interesse + if(controller->modelHasFinalAutomata && strstr(automata->moduleName,"final")){ + addParamInterestPointHeader(accessHeader(controller,MAIN,-1), paramName,1); + addParamInterestPointHeader(automata,paramName,0); + } + // só tem um filter + if(!controller->modelHasFinalAutomata){ + addParamInterestPointHeader(accessHeader(controller,MAIN,-1),paramName,1); + } + } +} + +void addParamToAutomatasFilter(EnvController* controller, char* paramName){ + // deve adicioanr a todos os automatos esse parâmetro, e deve atualizar também as referencias desses no main e no final automata + int i; + for (i = 0; i < controller->F_AUTOMATAS_CHANGE_POINTER; i++) { + HeaderSmv* automata = accessHeader(controller,AUTOMATA,i); + addParamToAutomata(controller,paramName,automata); + } +} + +void addParamToTdsDeclaration(EnvController* controller, char* param, TDS* currentTDS){ + // adiciona a TDS (tem uma variável de retorno dizendo se foi necessário adicionar esse parâmetro ou não + HeaderSmv* headerTDS = accessHeader(controller,PORTS,currentTDS->SMV_REF); + int paramAdd = addParamToModule(headerTDS,param); + if(paramAdd){ + // DEVE AGORA PROPAGAR A DEPENDENCIA PARA A DECLARAÇÃO DELE EM PORTS MODULE + // recuperar o indice da declaração + STable* portsAux = accessSmvInfo(controller, PORTS, 0); + TableEntry* infoOfTdsDec = lookup(portsAux,currentTDS->name); + int pos = *(int*) infoOfTdsDec->val->values[0]; + int size = *(int*) infoOfTdsDec->val->values[1]; + HeaderSmv* portsHeader = accessHeader(controller,PORTS,0); + char* bufferToUpdate = portsHeader->varBuffer[pos]; + char* newNameDeclaration = addParams(bufferToUpdate, param, "(", ")", 0); + free(bufferToUpdate); + portsHeader->varBuffer[pos] = newNameDeclaration; + size = strlen(newNameDeclaration); + void* vp[] = {&size}; + updateValue(currentTDS->name,vp,WRITE_SMV_INFO,1,1,-1,portsAux,-1); + } +} + +void addParamToTds(EnvController* controller, char* param, TDS* currentTDS){ + addParamToPortsModule(controller,param); + // adiciona a TDS (tem uma variável de retorno dizendo se foi necessário adicionar esse parâmetro ou não + addParamToTdsDeclaration(controller,param,currentTDS); +} + +/** + * Adiciona parâmetro para módulo qualquer do nuXmv. + * @param controller o controlador de ambiente e contexto + * @param param a string do parâmetro + * @param cat a categoria do header/tabela auxuliar a ser recuperada + * @param indexOfHeader o indice do header + * @return 1 se a operação foi realizada com sucesso (isto é foi necessária) + * ou 0 caso a operação não tenha sido realizada (o módulo já possui o parâmetro) + */ +void addParamToPortsModule(EnvController *controller, char *param) { + + HeaderSmv* portsModuleHeader = accessHeader(controller,PORTS,0); + int paramAdd = addParamToModule(portsModuleHeader,param); // deve adicionar ao portsModule É SEMPRE O PRIMEIRO + if(paramAdd){ + // agora deve propagar as alterações para todos os demais módulos + // OU SEJA JÁ QUE ESTÁ CENTRALIZADO NO MAIN (posição 3 do buffer de VAR), deve-se substituir esse + HeaderSmv* mainUpdate = accessHeader(controller,MAIN,-1); + char* refOldPt; + refOldPt = mainUpdate->varBuffer[mainUpdate->VAR_RENAME_POINTER]; + char* newDeclaration = addParams(refOldPt, param, "(", ")", 0); + free(refOldPt); + mainUpdate->varBuffer[mainUpdate->VAR_RENAME_POINTER] = newDeclaration; + +// if(!first){ +// propagParamDependence(controller->MAIN_RELATED,param,controller->H_MAIN_CURRENT_SIZE); +// } +// propagParamDependence(controller->AUTOMATA_RELATED,param,controller->H_AUTOMATA_CURRENT_SIZE); + } +} + + +char* getTypeSetWordFromDict(char* wordRef, EnvController* controller){ + int hashWord = hash(wordRef,TYPE_SET_DIR_SIZE); + if(controller->typeSetWords[hashWord]){ + return controller->typeSetWords[hashWord]; + } + else{ + // cria uma entrada para essa + addTypeSetWordToDict(wordRef,controller); + return controller->typeSetWords[hashWord]; + } + //return NULL; // garantia (até porque na verdade já preenchemos com null antes) +} + +void addTypeSetWordToDict(char* word, EnvController* controller){ + int hashWord = hash(word,TYPE_SET_DIR_SIZE); + if(controller->typeSetWords[hashWord]){ + if(strcmp(controller->typeSetWords[hashWord],word) != 0){ + fprintf(stderr,"[addTypeSetWordToDict] DICT WORD COLLISION!\n"); + exit(-1); + } + } + else{ + //char* newWord = formatString(word); + char* newWord = malloc(sizeof(char)*strlen(word)+1); + strcpy(newWord,word); + controller->typeSetWords[hashWord] = newWord; + } +} + +void validateAfterInterPost(EnvController* controller){ + if(!controller->declaredPortsNumber){ + fprintf(stderr, "\n[WARNING] THE MODEL GENERATION WAS SUCCESSFUL, HOWEVER, NO VALID TDS DEFINITION WAS FOUND.\nIT IS RECOMMENDED THAT YOU REVIEW YOUR .tds FILE\n"); + } + else{ + if(controller->validPorts != controller->expectedPorts){ + if(controller->validPorts){ + fprintf(stderr, "\n[WARNING] THE MODEL GENERATION WAS SUCCESSFUL,\nHOWEVER, OF THE %d PORTS DECLARED ONLY %d of %d PORTS WERE COMPLIANT TO THE ORIGINAL MODEL.\nIT IS RECOMMENDED THAT YOU REVIEW YOUR .tds FILE.\n", + controller->declaredPortsNumber, controller->validPorts,controller->expectedPorts); + } + else{ + fprintf(stderr, "\n[WARNING] THE MODEL GENERATION WAS SUCCESSFUL,\nHOWEVER, OF THE %d PORTS DECLARED NONE WERE COMPLIANT TO THE ORIGINAL MODEL.\nIT IS RECOMMENDED THAT YOU REVIEW YOUR .tds FILE.\n", + controller->declaredPortsNumber); + } + } + } + if(!controller->IO_RELATION){ + fprintf(stderr, "\n[WARNING] NO TDS RELATIONSHIP WAS DECLARED. IT IS RECOMMENDED THAT YOU REVIEW YOUR .tds FILE.\n"); + } + if(controller->modelHasFilter == 1 && !controller->filterUsed){ + fprintf(stderr, "\n[WARNING] FILTER WAS USED IN THE ORIGINAL MODEL, HOWEVER, NO FILTER RELATIONSHIP WAS DECLARED. \n IT IS RECOMMENDED THAT YOU REVIEW YOUR .tds FILE.\n"); + } + else{ + if(!controller->modelHasFilter && controller->filterUsed){ + fprintf(stderr, "\n[WARNING] FILTER WAS NOT USED IN THE ORIGINAL MODEL. \n IT IS RECOMMENDED THAT YOU REVIEW YOUR .tds FILE.\n"); + } + } +} diff --git a/src/Interpreter.c b/src/Interpreter.c index 022469b..89896ee 100644 --- a/src/Interpreter.c +++ b/src/Interpreter.c @@ -4,108 +4,52 @@ #include #include #include -#include "../headers/PostProcess.h" - -typedef enum MAP_OP { PLUS = 43, MINUS = 45, TIMES = 42, DIVIDE = 47, MOD = 37, LT = 60, GT = 62, NOTEQUAL = 94, NOT_PREFIX = 110, - LE = 121, EQUAL = 122, GE = 123} MAP_OP; - -Object *eval(Node *n, STable *scope, HeaderController *controllerSmv); -Object* evalNUM(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalBOOL(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalSTRING(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalNULL(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalIDVAR(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalTIME_DIRECTIVE(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalDataV(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalPARAMS_CALL(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalAC_V(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalOTHER_ASSIGN(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalV_PROP(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalADD_V(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalADD_V_PROP(Node* n, STable* scope, HeaderController* controllerSmv); -Object* evalV_PROP_TDS(Node* n, STable* scope, HeaderController* controllerSmv); -Object * evalEXPR(Node* n, STable* scope, HeaderController* controllerSmv); -Object * evalDEFINE_INTERVAL(Node* n, STable* scope, HeaderController* controllerSmv); -Object * evalCMD_IF(Node* n, STable* scope, HeaderController* controllerSmv); -//Object * evalTDS_DEF_COMPLETE(Node* n, STable* scope, HeaderController* controllerSmv); - -STable* selectSMV_SCOPE(STable* scope, HeaderController* controllerSmv){ - if(scope->type == FUNC || scope->childOfFunction){ - return accessSmvInfo(controllerSmv,FUNCTION_SMV,scope->indexRef); -// return controllerSmv->functionsInfo[scope->indexRef]; - } - else{ - return controllerSmv->mainInfo; // só vai retornar ports em casos de declarações de tds - } -} - -HeaderSmv * selectSMV_INFO(STable* scope, Object* functionPointer,HeaderController* controllerSmv){ - if(!functionPointer){ - return controllerSmv->MAIN; - } - else{ -// objeto função (parametros vão ser adicionados a STABLE, e vamos ter o número esperado de parâmetros) - // (vamos ter o index de referência do controller (header) e também o smvinfo - int ALL_FUNCTION = *(int*) functionPointer->values[3]; -// int TDS_FUNCTION = *(int*) functionPointer->values[4]; - if(ALL_FUNCTION){ - return accessHeader(controllerSmv,MAIN,ALL_FUNCTION); - } -// if(TDS_FUNCTION){ -// return accessHeader(controllerSmv,PORTS,TDS_FUNCTION); -// } - fprintf(stderr, "FUNCTION SMV INFO NOT FOUND"); - exit(-1); - } -} - -Object* (*executores[80]) (Node* n, STable* scope, HeaderController* controllerSmv) = { - - evalNUM, evalBOOL, evalSTRING, evalNULL, evalIDVAR, evalTIME_DIRECTIVE, evalDataV, evalPARAMS_CALL, evalDEFINE_INTERVAL ,evalAC_V, - evalOTHER_ASSIGN, evalV_PROP, evalADD_V, evalADD_V_PROP, evalV_PROP_TDS, evalEXPR, evalCMD_IF -}; +#include "../headers/Interpreter.h" +/* + * Funções de avaliação + */ -Object* evalNUM(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalNUM(Node* n, STable* scope, EnvController* controllerSmv) { int sint; sint = atoi(n->leafs[0]); - printf("[evalNUM] SINTH: %d \n",sint); + //printf("[evalNUM] SINTH: %d \n",sint); void* ip[] = {&sint}; - Object* o = createObject(NUMBER_ENTRY, 1, ip, -1, NULL); + Object* o = createObject(NUMBER_ENTRY, 1, ip, -1, n->leafs[0], createMinMaxByOneValue(sint)); return o; } -Object* evalBOOL(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalBOOL(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalBOOL] \n"); + //printf("[evalBOOL] \n"); int sint; - char* trueString = "true"; + char* trueString = "TRUE"; + char* falseString = "FALSE"; - sint= strstr(n->leafs[0],trueString)? 1 : 0; + sint= strstr(n->leafs[0],"true")? 1 : 0; - printf("[evalBOOL] SINTH: %d \n",sint); + //printf("[evalBOOL] SINTH: %d \n",sint); void* bp[] = {&sint}; - Object* o = createObject(LOGICAL_ENTRY, 1, bp, -1, NULL); + Object* o = createObject(LOGICAL_ENTRY, 1, bp, -1, sint ? trueString : falseString, NULL); return o; } -Object* evalSTRING(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalSTRING(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalSTRING] \n"); + //printf("[evalSTRING] \n"); char* sint = n->leafs[0]; void* sp[] = {sint}; - printf("[evalSTRING] SINTH: %s \n",sint); - - Object* o = createObject(LABEL_ENTRY, 1, sp, -1, NULL); - + //printf("[evalSTRING] SINTH: %s \n",sint); + TypeSet *newTypeSet = computeTypeSet(controllerSmv, sint); + Object* o = createObject(LABEL_ENTRY, 1, sp, -1, sint, newTypeSet); return o; } @@ -115,25 +59,20 @@ Object* evalSTRING(Node* n, STable* scope, HeaderController* controllerSmv) */ -Object* evalNULL(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalNULL(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalNULL] \n"); - // se eu interpretar como "NULL" do C mesmo podemos ter problemas(?) + //printf("[evalNULL] \n"); + // se eu interpretar como "NULL" do C mesmo podemos ter problemas(?) SIM NULL SERÁ UMA "LABEL" ESPECIAL char* sint = n->leafs[0]; - - void* np[] = {sint}; - - printf("[evalNULL] SINTH: %s \n",sint); - - Object* o = createObject(NULL_ENTRY, 1, np, -1, NULL); - + // TALVEZ TENHAMOS QUE ADICIONAR AO NULL o 0 (para não ficar uma constante) + Object* o = createObject(NULL_ENTRY, 0, NULL, -1, sint, computeTypeSet(controllerSmv,sint)); return o; } -Object* evalIDVAR(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalIDVAR(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalIDVAR] \n"); + //printf("[evalIDVAR] \n"); // VAI RECUPERAR UM OBJETO NA TABELA DE SIMBOLOS e então SUBIR COM ELE //(já que o tipo pode ser qualquer e a gente vai decidir o que fazer com ele ainda) @@ -160,25 +99,44 @@ Object* evalIDVAR(Node* n, STable* scope, HeaderController* controllerSmv) // criar MÉTODO DE COPIA DE OBJETO (variavel) - if(entry->val->OBJECT_SIZE > 1) + // retorna a referência (ai pode sim ter colaterais) (não permite "passagem de referência" gerar conversão no nuXmv (não existe) + if(entry->val->type == TDS_ENTRY || entry->val->OBJECT_SIZE > 1) { - // retorna a referência (ai pode sim ter colaterais) + if(controllerSmv->currentTDScontext){ + fprintf(stderr, "TDS VALIDATION ERROR: INCOMPATIBLE SPECIFICATION FOR TDS %s. DATA STRUCTURES ARE NOT ACCEPTED AS VALUES, ONLY SYMBOLIC VALUES.", controllerSmv->currentTDScontext->name); + exit(-1); + } return entry->val; } else { - // copia o objeto atomico (TEM QUE PASSAR O BIND NOVO!) - return refCopyOfVariable(entry); - //return copyObject(entry->val); + int tdsContext = !!controllerSmv->currentTDScontext; + int filterContext = controllerSmv->filterContext; + if(tdsContext) { + if (entry->val->type == LOGICAL_ENTRY) { + fprintf(stderr,"TDS VALIDATION ERROR: INCOMPATIBLE SPECIFICATION FOR TDS %s. ONLY SYMBOLIC VALUES ARE ACCEPTED, %s is a BOOLEAN value",controllerSmv->currentTDScontext->name, entry->name); + // poderia ter um cast implicito também... + exit(-1); + } + } + Object *copy = refCopyOfVariable(entry, controllerSmv); + if (tdsContext) { + addParamToTds(controllerSmv, entry->name, controllerSmv->currentTDScontext); + // encapsular em método depois + //addToTdsWatchList(controllerSmv->currentTDScontext,entry->name,C_TIME); + } + if(filterContext && controllerSmv->modelHasFilter){ + addParamToAutomatasFilter(controllerSmv,entry->name); + } + return copy; } } } -Object* evalTIME_DIRECTIVE(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalTIME_DIRECTIVE(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalTIME_DIRECTIVE] \n"); - + //printf("[evalTIME_DIRECTIVE] \n"); TableEntry* entry = lookup(scope,n->leafs[0]); // teoricamente é impossível uma time Directive não estar na tabela mas é só um check @@ -189,405 +147,489 @@ Object* evalTIME_DIRECTIVE(Node* n, STable* scope, HeaderController* controller } else { + char* bind; + char smvBind[150]; + if(n->leafs[0][0] != 'C'){ + sprintf(smvBind,"%d",*(int*)entry->val->values[0]); + bind = smvBind; + } + else{ + bind = "time"; + } // retorna cópia numérica das TIME_DIRECTIVES (elas SÃO UNICAS NO CÓDIGO, só alteradas mas não copiadas ) - return createObject(NUMBER_ENTRY, 1, entry->val->values, -1, NULL); + return createObject(NUMBER_ENTRY, 1, entry->val->values, -1, bind, createMinMaxByOneValue(*(int*)entry->val->values[0])); } } +Object* evalDataV(Node* n, STable* scope, EnvController* controllerSmv){/*notused*/} - -Object* evalDataV(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalPARAMS_CALL(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalDataV] \n"); - - - //str= evalSTRING(n, scope, writeSmvTypeTable, controllerSmv); - - //printf("[evalDataV] DATA_V SINTH: %s \n",str); - - //return sint; - - // esse vai ser bem diferente... - - // vai chamar evalParams , e sintetizar um Object Vetor (ou um vetor void que será jogado em um object) + //printf("[evalPARAMS_CALL] \n"); } -Object* evalPARAMS_CALL(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalPARAMS(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalPARAMS_CALL] \n"); + //printf("[evalPARAMS_CALL] \n"); } - - -Object* evalPLUS(Object* o1, Object* o2) +Object* evalPLUS(Node* n, STable* scope, EnvController* controller) { - printf("[evalPLUS] \n"); - int* r; - void* rp[1]; - if(o1->type == NUMBER_ENTRY) - { - *r = (*(int*)o1->values[0]) + (*(int*)o2->values[0]); - rp[0] = r; - return createObject(NUMBER_ENTRY, 1, rp, -1, NULL); + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + if(!o1->aList && !o2->aList && o1->type == NUMBER_ENTRY && o2->type == o1->type){ + int r; + void* rp[] = {&r}; + r = (*(int*)o1->values[0]) + (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +4]; // + espaco + espaco + '+' + 1 + createExprBind(resultingBind, o1, o2, "+"); + Object* SUM_OBJECT = createObject(NUMBER_ENTRY, 1, rp, -1, + resultingBind, computeMinMaxSum(o1->type_smv_info,o2->type_smv_info)); + letgoObject(o1); + letgoObject(o2); + return SUM_OBJECT; + } + else if(!o1->aList && !o2->aList && o1->type == LABEL_ENTRY && o2->type == o1->type){ + char* str1 = o1->values[0]; + char* str2 = o2->values[0]; + char r[strlen(str1)+ strlen(str2)]; + r[0] = '\0'; + char* refToEnd = customCat(r,str1,0,0); + customCat(refToEnd,str2,0,0); + void* rp[] = {r}; + Object* CONCAT_OBJECT = createObject(LABEL_ENTRY, 1, rp, + -1, r,computeTypeSet(controller,r)); + letgoObject(o1); + letgoObject(o2); + return CONCAT_OBJECT; } - if(o1->type == LABEL_ENTRY) - { - // concatena - + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (+) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); } - } -Object* evalMINUS(Object* o1, Object* o2) +Object* evalMINUS(Node* n, STable* scope, EnvController* controller) { - if(o1->type != NUMBER_ENTRY || (o2 && o2->type != NUMBER_ENTRY)) + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = NULL; + if(n->nchild > 1){ + o2 = eval(n->children[1],scope,controller); + } + if(o1->aList || (o2 && o2->aList) || (o1->type != NUMBER_ENTRY || (o2 && o2->type != NUMBER_ENTRY))) { - fprintf(stderr, "INCOMPATIBLE OPERANDS FOR THE (-) OPERATION!"); + if(o2){ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (-) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); + } + else{ + fprintf(stderr, "INCOMPATIBLE OPERAND %s FOR THE (-) OPERATION!",o1->SINTH_BIND); + } exit(-1); } - printf("[evalMINUS] \n"); + validateOpsTdsValue(o1,o2); int r; r = o2 == NULL? (-1)*(*(int*) o1->values[0]) : (*(int*)o1->values[0]) - (*(int*)o2->values[0]); void* rp[] = {&r}; + char resultingBind[o2? strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +4: strlen(o1->SINTH_BIND) +2]; // + espaco + espaco + '-' + 1 ou '-' + +1 + createExprBind(resultingBind, o1, o2, "-"); + Object* MINUS_OBJECT = createObject(NUMBER_ENTRY, 1, rp, -1, resultingBind, + o2? computeMinMaxSub(o1->type_smv_info,o2->type_smv_info) : computeMinMaxNeg(o1->type_smv_info)); letgoObject(o1); if(o2){ letgoObject(o2); } - return createObject(NUMBER_ENTRY, 1, rp, -1, NULL); + return MINUS_OBJECT; } -Object* evalNOT(Object* o) +Object* evalNOT(Node* n, STable* scope, EnvController* controller) { - if(o->type != LOGICAL_ENTRY) - { - fprintf(stderr, "INCOMPATIBLE OPERANDS FOR THE (not) OPERATION!"); - exit(-1); - } - printf("[evalNOT] \n"); - int r; - r = !(*(int*) o->values[0]); - void* rp[] = {&r}; - char resultingBind[strlen(o->SINTH_BIND)+2]; - createExprBind(resultingBind, o, NULL, "!"); - letgoObject(o); - return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind); + Object* o = eval(n->children[0],scope,controller); + validateOpsTdsValue(o,NULL); + return notObjectOperation(o); } -Object* evalTIMES(Object* o1, Object* o2) +Object* evalMULTI(Node* n, STable* scope, EnvController* controller) { - int* r; - *r = (*(int*)o1->values[0]) * (*(int*)o2->values[0]); - void* rp[] = {r}; - return createObject(NUMBER_ENTRY, 1, rp, -1, NULL); + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + if(!o1->aList && !o2->aList && o1->type == NUMBER_ENTRY && o2->type == o1->type){ + int r; + void* rp[] = {&r}; + r = (*(int*)o1->values[0]) * (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +4]; // + espaco + espaco + '*' + 1 + createExprBind(resultingBind, o1, o2, "*"); + Object* MULT_OBJECT = createObject(NUMBER_ENTRY, 1, rp, -1, resultingBind, + computeMinMaxMul(o1->type_smv_info,o2->type_smv_info)); + letgoObject(o1); + letgoObject(o2); + return MULT_OBJECT; + } + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (*) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); } -Object* evalDIVIDE(Object* o1, Object* o2, int type) +Object* evalDIV(Node* n, STable* scope, EnvController* controller) { - printf("[evalDIVIDE] \n"); - void* rp[1]; - if(*(int*)o2->values[0] == 0) - { - fprintf(stderr, "CANNOT DIVIDE BY ZERO!"); - exit(-1); + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + int isDivision = n->leafs[0][0] == DIVIDE; + char* op = isDivision ? "/" : "mod"; + + if(!o1->aList && !o2->aList && o1->type == NUMBER_ENTRY && o2->type == o1->type){ + int r; + void* rp[] = {&r}; + int SYNTH_O2 = *(int*)o2->values[0]; + if(!SYNTH_O2){ + fprintf(stderr, "CANNOT DIVIDE %s BY ZERO!",o1->SINTH_BIND); + exit(-1); + } + int aloca = isDivision ? 4 : 7; + r = isDivision? (*(int*)o1->values[0]) / (SYNTH_O2) : (*(int*)o1->values[0]) % (SYNTH_O2); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +aloca]; // + espaco + espaco + '/' + 1 + createExprBind(resultingBind, o1, o2, op); + Object* DIV_OBJECT = createObject(NUMBER_ENTRY, 1, rp, -1, resultingBind, + isDivision? computeMinMaxDiv(o1->type_smv_info,o2->type_smv_info) : + computeMinMaxMod(o1->type_smv_info,SYNTH_O2 == 2)); + letgoObject(o1); + letgoObject(o2); + return DIV_OBJECT; } - int* r; - *r = type == DIVIDE? (*(int*)o1->values[0]) / (*(int*)o2->values[0]) : (*(int*)o1->values[0]) % (*(int*)o2->values[0]); - rp[0] = r; - - return createObject(NUMBER_ENTRY, 1, rp, -1, NULL); + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (%s) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND,op); + exit(-1); } -Object* evalLESS(Object* o1, Object* o2, int opCode) -{ - printf("[evalLESS] \n"); - void* rp[1]; - int* r; - if(o1->OBJECT_SIZE > 1 || o2->OBJECT_SIZE > 1) - { - *r = opCode == LT? o1->OBJECT_SIZE < o2->OBJECT_SIZE : o1->OBJECT_SIZE <= o2->OBJECT_SIZE; +Object * evalLE(Node* n, STable* scope, EnvController* controller){ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + int r; + void* rp[] = {&r}; + if(o1->type == NUMBER_ENTRY && o2->type == o1->type){ + r = (*(int*)o1->values[0]) <= (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +5]; // + espaco + espaco + '<=' + 1 + createExprBind(resultingBind, o1, o2, "<="); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); } - else - { - if(o1->type == NUMBER_ENTRY) - { - *r = opCode == LT? (*(int*)o1->values[0]) < (*(int*)o2->values[0]) : (*(int*)o1->values[0]) <= (*(int*)o2->values[0]); + else if(o1->type != TDS_ENTRY && o1->type != LOGICAL_ENTRY && o2->type != TDS_ENTRY && o2->type != LOGICAL_ENTRY){ + // compara tamanhos + r = o1->OBJECT_SIZE <= o2->OBJECT_SIZE; + char resultingBind[300]; + sprintf(resultingBind,"%d <= %d",o1->OBJECT_SIZE,o2->OBJECT_SIZE); + if(!o1->aList){ + letgoObject(o1); } - if(o1->type == LABEL_ENTRY) - { - //teste o tamanho salvo no object 1 e object 2 + if(!o2->aList){ + letgoObject(o2); } + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); + } + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (<=) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); } - rp[0] = r; - return createObject(LOGICAL_ENTRY, 1, rp, -1, NULL); } -Object* evalGREAT(Object* o1, Object* o2, int opCode) -{ - printf("[evalGREAT] \n"); - void* rp[1]; - int* r; - if(o1->OBJECT_SIZE > 1 ||o2->OBJECT_SIZE > 1) - { - *r = opCode == GT? o1->OBJECT_SIZE > o2->OBJECT_SIZE : o1->OBJECT_SIZE >= o2->OBJECT_SIZE; + +Object * evalGE(Node* n, STable* scope, EnvController* controller){ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + int r; + void* rp[] = {&r}; + if(o1->type == NUMBER_ENTRY && o2->type == o1->type){ + r = (*(int*)o1->values[0]) >= (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +5]; // + espaco + espaco + '<=' + 1 + createExprBind(resultingBind, o1, o2, ">="); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); } - else - { - if(o1->type == NUMBER_ENTRY) - { - *r = opCode == GT? (*(int*)o1->values[0]) > (*(int*)o2->values[0]) : (*(int*)o1->values[0]) >= (*(int*)o2->values[0]); + else if(o1->type != TDS_ENTRY && o1->type != LOGICAL_ENTRY && o2->type != TDS_ENTRY && o2->type != LOGICAL_ENTRY){ + // compara tamanhos + r = o1->OBJECT_SIZE >= o2->OBJECT_SIZE; + char resultingBind[300]; + sprintf(resultingBind,"%d >= %d",o1->OBJECT_SIZE,o2->OBJECT_SIZE); + if(!o1->aList){ + letgoObject(o1); } - if(o1->type == LABEL_ENTRY) - { - //teste o tamanho salvo no object 1 e object 2 + if(!o2->aList){ + letgoObject(o2); } + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); + } + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (>=) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); } - rp[0] = r; - return createObject(LOGICAL_ENTRY, 1, rp, -1, NULL); - } -Object* evalEqual(Object* o1, Object* o2, int opCode) -{ - printf("[evalEqual] \n"); - void* rp[1]; - int* r; - if(o1->OBJECT_SIZE > 1 ||o2->OBJECT_SIZE > 1) - { - *r = opCode == EQUAL? o1->OBJECT_SIZE == o2->OBJECT_SIZE : o1->OBJECT_SIZE != o2->OBJECT_SIZE; +Object * evalLT(Node* n, STable* scope, EnvController* controller){ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + int r; + void* rp[] = {&r}; + if(o1->type == NUMBER_ENTRY && o2->type == o1->type){ + r = (*(int*)o1->values[0]) < (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +5]; // + espaco + espaco + '<=' + 1 + createExprBind(resultingBind, o1, o2, "<"); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); } - else - { - if(o1->type == NUMBER_ENTRY) - { - *r = opCode == EQUAL? (*(int*)o1->values[0]) == (*(int*)o2->values[0]) : (*(int*)o1->values[0]) != (*(int*)o2->values[0]); + else if(o1->type != TDS_ENTRY && o1->type != LOGICAL_ENTRY && o2->type != TDS_ENTRY && o2->type != LOGICAL_ENTRY){ + // compara tamanhos + r = o1->OBJECT_SIZE < o2->OBJECT_SIZE; + char resultingBind[300]; + sprintf(resultingBind,"%d < %d",o1->OBJECT_SIZE,o2->OBJECT_SIZE); + if(!o1->aList){ + letgoObject(o1); } - if(o1->type == LABEL_ENTRY) - { - //teste o tamanho salvo no object 1 e object 2 + if(!o2->aList){ + letgoObject(o2); } + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); + } + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (<) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); } - rp[0] = r; } +Object * evalGT(Node* n, STable* scope, EnvController* controller){ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); - -Object* evalEXPR(Node* n, STable* scope, HeaderController* controllerSmv) -{ - printf("[evalEXPR] \n"); - // operação unária ou simplesmente FOLHA - if(n->nchild <= 1) - { - Object * sintUni = eval(n->children[0], scope, controllerSmv); - - char ops[1]; - // caso de operação unária (tem folhas e filhos) - if(n->nchild == 1 && n->nleafs == 1 ) - { - ops[0] = n->leafs[0][0]; // recupera a operação - - if(ops[0] == MINUS && sintUni->type == NUMBER_ENTRY) - { - return evalMINUS(sintUni,NULL); - } - if(ops[0] == NOT_PREFIX && sintUni->type == LOGICAL_ENTRY) - { - return evalNOT(sintUni); - } - fprintf(stderr, "INCOMPATIBLE OPERANDS FOR THE %c OPERATION!", ops[0]); - exit(-1); - } - return sintUni; + int r; + void* rp[] = {&r}; + if(o1->type == NUMBER_ENTRY && o2->type == o1->type){ + r = (*(int*)o1->values[0]) > (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +5]; // + espaco + espaco + '<=' + 1 + createExprBind(resultingBind, o1, o2, ">"); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); } - // operação binária - else - { - // CUIDADO (ordem avaliação) - Object* o1 = evalEXPR(n->children[0], scope, controllerSmv); - Object* o2 = evalEXPR(n->children[1],scope, controllerSmv); - - int sOp = strlen(n->leafs[0]); - char ops[2]; - ops[1] = '\0'; - - if(sOp > 1) - { - ops[1] = n->leafs[0][1]; + else if(o1->type != TDS_ENTRY && o1->type != LOGICAL_ENTRY && o2->type != TDS_ENTRY && o2->type != LOGICAL_ENTRY){ + // compara tamanhos + r = o1->OBJECT_SIZE > o2->OBJECT_SIZE; + char resultingBind[300]; + sprintf(resultingBind,"%d > %d",o1->OBJECT_SIZE,o2->OBJECT_SIZE); + if(!o1->aList){ + letgoObject(o1); } - ops[0] = n->leafs[0][0]; - - - // validações (adicionar uma para vetores depois (não deixar fazer nenhuma operação com eles exceto comparação de tamanho)) - if(o1->type == TDS_ENTRY || o2->type == TDS_ENTRY) - { - if(sOp < 1) - { - fprintf(stderr, "TDS INCOMPATIBLE FOR THE %c OPERATION! ", ops[0]); - exit(-1); - } - else - { - fprintf(stderr, "TDS INCOMPATIBLE FOR THE %c%c OPERATION!", ops[0],ops[1]); - exit(-1); - } + if(!o2->aList){ + letgoObject(o2); } + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); + } + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (>) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); + } +} - if(o1->type == NULL_ENTRY || o2->type == TDS_ENTRY) - { - fprintf(stderr, "NULL REFERENCE FOR THE %c%c OPERATION! ", ops[0],ops[1]); - exit(-1); - } - if(o1->type != o2->type) - { - if(sOp < 1) - { - fprintf(stderr, "INCOMPATIBLE TYPES FOR THE %c OPERATION!", ops[0]); - exit(-1); - } - else - { - fprintf(stderr, "INCOMPATIBLE TYPES FOR THE %c%c OPERATION!", ops[0],ops[1]); - exit(-1); - } - } +Object* evalEQUAL(Node* n, STable* scope, EnvController* controller){ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + int r = comparator(o1,o2,"=="); + void* rp[] = {&r}; + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +5]; + createExprBind(resultingBind, o1, o2, "="); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); +} - int vetOp = o1->OBJECT_SIZE > 1 ||o2->OBJECT_SIZE > 1; +Object* evalNEQUAL(Node* n, STable* scope, EnvController* controller){ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + int r = !comparator(o1,o2,"!="); + void* rp[] = {&r}; + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +5]; + createExprBind(resultingBind, o1, o2, "!="); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); +} - if(!vetOp && ops[0] == PLUS) - { - return evalPLUS(o1,o2); - } - if(!vetOp && ops[0] == MINUS && o1->type != LABEL_ENTRY) - { - return evalMINUS(o1,o2); - } - if(!vetOp && ops[0] == TIMES && o1->type != LABEL_ENTRY) - { - return evalTIMES(o1,o2); - } - if(!vetOp && ops[0] == DIVIDE && o1->type != LABEL_ENTRY) - { - return evalDIVIDE(o1,o2,DIVIDE); - } - if(!vetOp && ops[0] == MOD && o1->type != LABEL_ENTRY) - { - return evalDIVIDE(o1,o2,MOD); - } - if(ops[0] == LT) - { - if(sOp > 1) - { - return evalLESS(o1,o2,LE); - } - else - { - evalLESS(o1,o2,LT); - } - } - if(ops[0] == GT) - { - if(sOp > 1) - { - return evalGREAT(o1,o2,GE); - } - return evalGREAT(o1,o2,GT); - } - else - { - return(evalEqual(o1,o2,ops[0]+ops[2])); - } - fprintf(stderr, "INCOMPATIBLE OPERANDS FOR THE %c%c OPERATION!", ops[0],ops[1]); +Object* evalAND(Node* n, STable* scope, EnvController* controller) +{ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + if(!o1->aList && !o2->aList && o1->type == LOGICAL_ENTRY && o2->type == o1->type){ + int r; + void* rp[] = {&r}; + r = (*(int*)o1->values[0]) && (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +4]; // + espaco + espaco + '+' + 1 + createExprBind(resultingBind, o1, o2, "&"); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); + } + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (and) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); exit(-1); } - } - -Object* evalProp(Node* fatherRef, Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalOR(Node* n, STable* scope, EnvController* controller) { - printf("[evalProp] \n"); - if(!n) - { - printf("[evalProp] VARIAVEL: \n"); - // NÃO PRECISA RETORNAR NADA, já temos a referência no nó acima - // até porque não temos nada - return NULL; + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + if(!o1->aList && !o2->aList && o1->type == LOGICAL_ENTRY && o2->type == o1->type){ + int r; + void* rp[] = {&r}; + r = (*(int*)o1->values[0]) || (*(int*)o2->values[0]); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +4]; // + espaco + espaco + '+' + 1 + createExprBind(resultingBind, o1, o2, "|"); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); } - if(n->type == V_PROP) - { + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (or) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); + } +} - char* propName; - printf("[evalProp] PROP VARIAVEL: %s \n",propName); - //return createObject(); - return NULL; +Object* evalIMP(Node* n, STable* scope, EnvController* controller) +{ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + if(!o1->aList && !o2->aList && o1->type == LOGICAL_ENTRY && o2->type == o1->type){ + int r; + void* rp[] = {&r}; + r = IMP((*(int*)o1->values[0]) , (*(int*)o2->values[0])); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +5]; // + espaco + espaco + '->' + 1 + createExprBind(resultingBind, o1, o2, "->"); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); } - if(n->type == ADD_V) - { - Object* expr = evalEXPR(n->children[0],scope, controllerSmv); - if(expr->type != NUMBER_ENTRY) - { - fprintf(stderr, "%s: INVALID INDEX!", fatherRef->leafs[0]); - exit(-1); - } - printf("[evalProp] VARIAVEL pos: %d \n",expr->values[0]); - return expr; + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (->) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); } +} - char* propName; - printf("[evalProp] VARIAVEL pos prop %d \n",propName); - return NULL; +Object* evalBIMP(Node* n, STable* scope, EnvController* controller) +{ + Object* o1 = eval(n->children[0],scope,controller); + Object* o2 = eval(n->children[1],scope,controller); + validateOpsTdsValue(o1,o2); + + if(!o1->aList && !o2->aList && o1->type == LOGICAL_ENTRY && o2->type == o1->type){ + int r; + void* rp[] = {&r}; + r = BIMP((*(int*)o1->values[0]) , (*(int*)o2->values[0])); + char resultingBind[strlen(o1->SINTH_BIND)+strlen(o2->SINTH_BIND) +6]; // + espaco + espaco + '+' + 1 + createExprBind(resultingBind, o1, o2, "<->"); + letgoObject(o1); + letgoObject(o2); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); + } + else{ + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (<->) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND); + exit(-1); + } } - -Object* evalAC_V(Node* n, STable* scope, HeaderController* controllerSmv) +Object* evalPRI_EXPR(Node* n, STable* scope, EnvController* controllerSmv) { - printf("[evalAC_V] \n"); + Object* pri = eval(n->children[0],scope,controllerSmv); + char* NEW_BIND = malloc(sizeof(char)*(strlen(pri->SINTH_BIND)+3)); // ( ) e \0 + NEW_BIND[0] = '\0'; + char* refToNew = NEW_BIND; + refToNew = customCat(refToNew,"(",0,0); + refToNew = customCat(refToNew,pri->SINTH_BIND,0,0); + customCat(refToNew,")",0,0); + free(pri->SINTH_BIND); + pri->SINTH_BIND = NEW_BIND; + return pri; +} + +Object* evalEXPR(Node* n, STable* scope, EnvController* controllerSmv) +{ + return eval(n->children[0],scope,controllerSmv); +} - // recupera a variável e o nome do atributo dela logo após +Object* evalAC_V(Node* n, STable* scope, EnvController* controllerSmv){ TableEntry* entry = lookup(scope,n->leafs[0]); - if(!entry) { fprintf(stderr, "%s NOT DECLARED!", n->leafs[0]); exit(-1); } - else - { - Object* prop = evalProp(n,n->children[0], scope, controllerSmv); - - if(entry->val->OBJECT_SIZE > 1) - { - // retorna a referência (ai pode sim ter colaterais) - return entry->val; - } - else - { - // copia o objeto atomico - return refCopyOfVariable(entry); + else{ + if(n->children[0] && n->children[0]->type == V_PROP){ + char* propertyName = n->children[0]->children[0]->children[0]->leafs[0]; + if(entry->val->type != TDS_ENTRY || propertyName[0] != 'v'){ + fprintf(stderr, "ERROR: %s does not contains %s property", n->leafs[0],propertyName); + exit(-1); + } + TDS* SINTH_TDS = entry->val->values[0]; + Object* tdsValue = NULL; + char* pathToProp = NULL; + + int C_TIME = *(int*) lookup(scope,"C_TIME")->val->values[0]; + int I_TIME = *(int*) lookup(scope,"I_TIME")->val->values[0]; + int tdsContext = !!controllerSmv->currentTDScontext; + int filterContext = controllerSmv->filterContext; + + if (!filterContext && tdsContext) { + addParamToTdsDeclaration(controllerSmv, SINTH_TDS->name, controllerSmv->currentTDScontext); + pathToProp = createPropPathBind(SINTH_TDS->name,propertyName); + } + else{ + char* pathParcial = createPropPathBind("ports",SINTH_TDS->name); + pathToProp = createPropPathBind(pathParcial,propertyName); + free(pathParcial); + } + if(C_TIME > I_TIME){ + char* nextPathToProp = encapsulateWithNext(pathToProp); + tdsValue = getTdsValue(SINTH_TDS, C_TIME, nextPathToProp); + free(nextPathToProp); + } + else{ + tdsValue = getTdsValue(SINTH_TDS, C_TIME, pathToProp); + } + free(pathToProp); + controllerSmv->relationRef = 1; + return tdsValue; } + fprintf(stderr, "ERROR: %s does not contains any property", n->leafs[0]); + exit(-1); } } -Object* evalV_PROP(Node* n, STable* scope, HeaderController* controllerSmv){ - printf("[evalV_PROP] \n"); - -} -Object* evalADD_V(Node* n, STable* scope, HeaderController* controllerSmv){ - printf("[evalADD_V] \n"); -} -Object* evalADD_V_PROP(Node* n, STable* scope, HeaderController* controllerSmv){ - printf("[evalADD_V_PROP] \n"); -} - -Object* evalV_PROP_TDS(Node* n, STable* scope, HeaderController* controllerSmv){ - printf("[evalV_PROP_TDS] \n"); -} +Object* evalProp(Node* fatherRef, Node* n, STable* scope, EnvController* controllerSmv){/*notused*/} +Object* evalV_PROP(Node* n, STable* scope, EnvController* controllerSmv){/*notused*/} +Object* evalADD_V(Node* n, STable* scope, EnvController* controllerSmv){/*notused*/} +Object* evalADD_V_PROP(Node* n, STable* scope, EnvController* controllerSmv){/*notused*/} +Object* evalV_PROP_TDS_VALUE(Node* n, STable* scope, EnvController* controllerSmv){/*notused*/} +Object* evalV_PROP_TDS(Node* n, STable* scope, EnvController* controllerSmv){/*notused*/} -Object * evalDEFINE_INTERVAL(Node* n, STable* scope, HeaderController* controllerSmv){ +Object * evalDEFINE_INTERVAL(Node* n, STable* scope, EnvController* controllerSmv){ int I_TIME; int* ptitime = NULL; @@ -613,7 +655,7 @@ Object * evalDEFINE_INTERVAL(Node* n, STable* scope, HeaderController* controll } } if( (ptitime != NULL && ptftime != NULL && I_TIME > F_TIME) || - ( ptitime != NULL && I_TIME < 0 ) || ( ptftime != NULL && F_TIME <= 0 ) ) { + ( ptitime != NULL && I_TIME < 0 ) || ( ptftime != NULL && F_TIME <= 0 ) ) { fprintf(stderr, "ERROR: BAD USE OF INTERVAL TIME DIRECTIVE, INVALID INTERVAL! \n"); exit(-1); } @@ -623,7 +665,7 @@ Object * evalDEFINE_INTERVAL(Node* n, STable* scope, HeaderController* controll void* vp[] = {ptitime}; updateValue("I_TIME", vp, T_DIRECTIVE_ENTRY, 1, -1, -1, scope, 0); sprintf(smvBind,"%d",I_TIME); - updateTime(controllerSmv->MAIN,controllerSmv->mainInfo,smvBind,NUMBER_ENTRY,0,0); + updateTime(controllerSmv->MAIN, controllerSmv->mainInfo, smvBind, T_DIRECTIVE_ENTRY, 0, *ptitime); // necessita atualizar C_TIME updateValue("C_TIME", vp, T_DIRECTIVE_ENTRY, 1, -1, -1, scope, 0); } @@ -631,186 +673,135 @@ Object * evalDEFINE_INTERVAL(Node* n, STable* scope, HeaderController* controll void* vp[] = {ptftime}; updateValue("F_TIME", vp, T_DIRECTIVE_ENTRY, 1, -1, -1, scope, 0); sprintf(smvBind,"%d",F_TIME); - updateTime(controllerSmv->MAIN,controllerSmv->mainInfo,smvBind,NUMBER_ENTRY,1,1); + updateTime(controllerSmv->MAIN, controllerSmv->mainInfo, smvBind, T_DIRECTIVE_ENTRY, 1, *ptftime); } return NULL; } -Object* evalOTHER_ASSIGN(Node* n, STable* scope, HeaderController* controllerSmv) -{ + +Object* eval_ASSIGN_TDIRECTIVE(Node* n, STable* scope, EnvController* controllerSmv){ Object* expr = NULL; Object** sintExpr = NULL; // recuperação de diretiva temporal principal para uso TableEntry* ctimeEntry = lookup(scope, "C_TIME"); int C_TIME = *(int*) ctimeEntry->val->values[0]; // caso de atribuição de diretiva - if(n->children[0]->type == ASSIGN_TDIRECTIVE) + // verificação semântica (se pode atribuir)(essas atribuições só são válidas no programa principal) ? seria uma boa tratar na gramática (?) + if(scope->type != GLOBAL) { - // verificação semântica (se pode atribuir)(essas atribuições só são válidas no programa principal) ? seria uma boa tratar na gramática (?) - if(scope->type != GLOBAL) - { - fprintf(stderr, "ERROR: BAD USE OF %s TIME DIRECTIVE, THE CONTEXT IS LOCKED! \n", n->children[0]->leafs[0]); - exit(-1); - } - // dois casos: alterar o valor na tabela de simbolos - //Mudou intervalos: alterar intervalo no main do SMV e mudar o init ou next (dependendo da diretiva) - //Mudou CONTEXTO (C_TIME) : seguir o caso default - // objeto sintetizado (chamar fora ou dentro do if depois das validações? avisa erros mais rapido) - expr = eval(n->children[1], scope, controllerSmv); - if(expr && expr->type != NUMBER_ENTRY && expr->OBJECT_SIZE > 1) - { - fprintf(stderr, "ERROR: BAD USE OF %s TIME DIRECTIVE, ONLY NUMERICAL VALUES ARE ACCEPTED \n", n->children[0]->leafs[0]); - exit(-1); - } - if(*(int*)expr->values[0] < C_TIME ){ - fprintf(stderr, "ERROR: BAD USE OF %s TIME DIRECTIVE, IMPOSSIBLE TO RETURN TO PAST CONTEXTS \n", n->children[0]->leafs[0]); - exit(-1); - } - // validaçao de intervalo - TableEntry* itimeEntry = lookup(scope,"F_TIME"); - int ftime = *(int*)itimeEntry->val->values[0]; - if(C_TIME > ftime){ - fprintf(stderr, "WARNING: %s IS BEYOND THE OBSERVATION INTERVAL \n", n->children[0]->leafs[0]); - } - /* TOMAR NOTA: NUNCA MAIS FAZER ISSO - * int* v; - * v = 5; (PODE LITERALMENTE ALOCAR QUALQUER, REPITO QUALQUER REGIÃO DE MEMÓRIA PARA MEU 5! - * void* vp[] = {v}; - * */ - // só fazer isso se eu tiver dado malloc em v! + fprintf(stderr, "ERROR: BAD USE OF %s TIME DIRECTIVE, THE CONTEXT IS LOCKED! \n", n->leafs[0]); + exit(-1); + } + // dois casos: alterar o valor na tabela de simbolos + //Mudou CONTEXTO (C_TIME) : seguir o caso default + // objeto sintetizado (chamar fora ou dentro do if depois das validações? avisa erros mais rapido) + expr = eval(n->children[0], scope, controllerSmv); + if(expr && expr->type != NUMBER_ENTRY || expr->OBJECT_SIZE > 1) + { + fprintf(stderr, "ERROR: BAD USE OF %s TIME DIRECTIVE, ONLY NUMERICAL VALUES ARE ACCEPTED \n", n->leafs[0]); + exit(-1); + } + if(*(int*)expr->values[0] < C_TIME ){ + fprintf(stderr, "ERROR: BAD USE OF %s TIME DIRECTIVE, IMPOSSIBLE TO RETURN TO PAST CONTEXTS \n", n->leafs[0]); + exit(-1); + } + // validaçao de intervalo + TableEntry* itimeEntry = lookup(scope,"F_TIME"); + int ftime = *(int*)itimeEntry->val->values[0]; + if(*(int*)expr->values[0] > ftime){ + fprintf(stderr, "WARNING: %s IS BEYOND THE OBSERVATION INTERVAL. The statement has no effect \n", n->leafs[0]); + } + else if(*(int*) expr->values[0] != C_TIME){ + commitCurrentTime(scope,controllerSmv,*(int*) expr->values[0]); void* vp[] = {expr->values[0]}; - updateValue(n->children[0]->leafs[0], vp, T_DIRECTIVE_ENTRY, 1, -1, -1, scope, 0); + updateValue(n->leafs[0], vp, T_DIRECTIVE_ENTRY, 1, -1, -1, scope, 0); letgoObject(expr); } - else{ - // busca expressão - expr = eval(n->children[1], scope, controllerSmv); - - // busca a variável e seu contexto - char* varName = n->children[0]->leafs[0]; - TableEntry* varEntry = lookup(scope,varName); - Object* var = varEntry == NULL ? NULL : varEntry->val; - - STable* refAuxTable = selectSMV_SCOPE(scope,controllerSmv); - // ports ou main - HeaderSmv* refHeader = selectSMV_INFO(scope,NULL,controllerSmv); + return NULL; +} - TableEntry* itimeEntry = lookup(scope,"I_TIME"); - int I_TIME = *(int*)itimeEntry->val->values[0]; - int changeContext = C_TIME > I_TIME; // verifica se mudou o contexto +Object* evalOTHER_ASSIGN(Node* n, STable* scope, EnvController* controllerSmv) +{ + Object* expr = NULL; + Object** sintExpr = NULL; + // busca expressão + expr = eval(n->children[1], scope, controllerSmv); + // busca a variável e seu contexto + char* varName = n->children[0]->leafs[0]; + TableEntry* varEntry = lookup(scope,varName); + Object* var = varEntry == NULL ? NULL : varEntry->val; + + // ports ou main + STable* refAuxTable = selectSMV_SCOPE(scope,controllerSmv); + HeaderSmv* refHeader = selectSMV_INFO(scope,NULL,controllerSmv); + + // validação de tempo + TableEntry* ctimeEntry = lookup(scope, "C_TIME"); + int C_TIME = *(int*) ctimeEntry->val->values[0]; + TableEntry* itimeEntry = lookup(scope,"I_TIME"); + int I_TIME = *(int*)itimeEntry->val->values[0]; + int changeContext = C_TIME > I_TIME; // verifica se mudou o contexto - // atribuição simples - if(n->children[0]->type == ASSIGN_IDVAR) + // atribuição simples + if(expr && (expr->type != TDS_ENTRY || expr->aList ) && n->children[0]->type == ASSIGN_IDVAR) + { + //primeira vez da variavel (ou não inicializada, mudança para depois) + if(!var) { - //primeira vez da variavel (ou não inicializada, mudança para depois - if(!var) - { - if(!scope->notEvaluated){ - addValue(varName, expr->values, expr->type, expr->OBJECT_SIZE, 0, scope, C_TIME); - } - //inicialização "com next", necessita criar um default para os instantes anteriores e o seu next - // note que temporal condition tem que ser um cubo de condição e tempo - if(changeContext){ - specAssign(1, varName, changeContext, refHeader, scope, refAuxTable, expr, 0, 0, C_TIME); - specAssign(1, varName, changeContext, refHeader, scope, refAuxTable, expr, 0, 1, C_TIME); - } - else{ - specAssign(1, varName, changeContext, refHeader, scope, refAuxTable, expr, 0, 0, C_TIME); - } + if(!scope->notEvaluated){ + addValue(varName, expr->values, expr->type, expr->OBJECT_SIZE, 0, scope, C_TIME); } - else{ - // VALIDAÇÃO DE TIPOS - if(var->type != expr->type){ - fprintf(stderr, "ASSIGN ERROR: incompatible type for %s \n", varEntry->name); - exit(-1); - } - int prevDef = var->redef; - int prevContext = var->timeContext; - if(!scope->notEvaluated){ - updateValue(varName, expr->values, expr->type, expr->OBJECT_SIZE, -1, -1, scope, C_TIME); - } - // tempo > 0 e não ocorreu redefinição - if(changeContext && var->redef == prevDef){ - specAssign(0, varName, changeContext, refHeader, scope, refAuxTable, expr, var->redef, 1, C_TIME); + //inicialização "com next", necessita criar um default para os instantes anteriores e o seu next + if(expr->type != NULL_ENTRY && !scope->notWrite){ + if(changeContext){ + specAssign(1, varName, changeContext, refHeader, scope, refAuxTable, expr, 0, 0, C_TIME, controllerSmv); + specAssign(1, varName, changeContext, refHeader, scope, refAuxTable, expr, 0, 1, C_TIME, controllerSmv); } else{ - fprintf(stderr, "ASSIGN ERROR: redefinition of %s in same time interval \n", varEntry->name); - exit(-1); - /* casos de redefinição (devemos dar free na entrada anterior (otimização) - letGoOldEntry(varEntry,refAuxTable); - // tempo = 0, redefinição - if(!changeContext){ - specAssign(0, varEntry, changeContext, refHeader, scope, refAuxTable, expr, var->redef, 0, - C_TIME); - } - // tempo > 0 e redefinição - else{ - specAssign(0, varEntry, changeContext, refHeader, scope, refAuxTable, expr, var->redef, 0, - C_TIME); - specAssign(0, varEntry, changeContext, refHeader, scope, refAuxTable, expr, var->redef, 1, - C_TIME); - } - */ + specAssign(1, varName, changeContext, refHeader, scope, refAuxTable, expr, 0, 0, C_TIME, controllerSmv); } } - letgoObject(expr); } else{ - if(var && expr->type != var->type){ - fprintf(stderr, "TYPE ERROR: %s datastructure type is imutable \n",varName); - exit(-1); + if(!scope->notEvaluated){ + updateVariable(varName,var,expr,scope,-1,C_TIME); } - - printf("[evalOTHER_ASSIGN] atribui variável (atributo ou indice) \n"); - if(!var) - { - fprintf(stderr, "ERROR: %s is not defined as datastruct \n",varName); - exit(-1); - } - - Node* ref = n->children[0]->children[0]; - Object* indexRef = ref->type == V_PROP ? NULL : eval(n, scope, controllerSmv); - - if(ref->type == V_PROP || ref->type == ADD_V_PROP) - { - if(var->type != TDS_ENTRY) - { - // TODO: FUNÇÃO AVALIADORA DE TDS_PROP - fprintf(stderr, "ERROR: %s does not contain the %s property \n",varName,ref->children[0]->leafs[0]); - exit(-1); - } - - else{ - // retorna a prop... + // tempo > 0 e não ocorreu redefinição + if((expr->type != NULL_ENTRY && !scope->notWrite)){ + if(changeContext){ + specAssign(0, varName, changeContext, refHeader, scope, refAuxTable, expr, var->redef, 1, + C_TIME, controllerSmv); } } - else{ - if(indexRef->type != NUMBER_ENTRY || indexRef->OBJECT_SIZE > 1) - { - fprintf(stderr, "ERROR: %s cannot be indexed by non numerical values! \n",varName); - exit(-1); - } - int index = *(int*) indexRef->values[0]; - if(index >= var->OBJECT_SIZE){ - fprintf(stderr, "ERROR: %s[%d] is out of bounds! \n",varName,index); - exit(-1); - } - // ainda parcialmente incompleto - updateValue(varName, expr->values, var->type, var->OBJECT_SIZE, index, -1, scope, 0); + } + letgoObject(expr); + } + else if(expr){ + if(var && expr->type != var->type){ + fprintf(stderr, "TYPE ERROR: %s datastructure type is imutable \n",varName); + exit(-1); // por enquanto declarações unicas de estruturas de dados + } + if(!var) + { + addReferenceCurrentScope(varName,expr,0,scope); + if(expr->type != TDS_ENTRY){ + // spec de lista } } - + else{ + // update ref + } } return NULL; } -Object * evalCMD_IF(Node* n, STable* scope, HeaderController* controllerSmv){ +Object * evalCMD_IF(Node* n, STable* scope, EnvController* controllerSmv){ Object* conditionalExpr = NULL; STable* IF_SCOPE = addSubScope(scope,IF_BLOCK); conditionalExpr = eval(n->children[0], scope, controllerSmv); - printObject(conditionalExpr); + //printObject(conditionalExpr); bindCondition(IF_SCOPE,conditionalExpr); IF_SCOPE->notEvaluated = !(!IF_SCOPE->parent->notEvaluated && *(int*)conditionalExpr->values[0]); eval(n->children[1], IF_SCOPE, controllerSmv); @@ -818,7 +809,7 @@ Object * evalCMD_IF(Node* n, STable* scope, HeaderController* controllerSmv){ if(n->children[2]){ STable* ELSE_SCOPE = addSubScope(scope,ELSE_BLOCK); ELSE_SCOPE->notEvaluated = !(!ELSE_SCOPE->parent->notEvaluated && !*(int*)conditionalExpr->values[0]); - Object* notExpr = evalNOT(conditionalExpr); + Object* notExpr = notObjectOperation(conditionalExpr); bindCondition(ELSE_SCOPE,notExpr); eval(n->children[2]->children[0], ELSE_SCOPE, controllerSmv); //letgoTable(ELSE_SCOPE); @@ -830,39 +821,81 @@ Object * evalCMD_IF(Node* n, STable* scope, HeaderController* controllerSmv){ return NULL; } -/* -Object * evalTDS_DEF_COMPLETE(Node* n, STable* scope, HeaderController* controllerSmv){ - int x = 1; - // leaf 4 (3) - // filho 1 (0) -> fazer via eval -> -> é loop que termina em eval expr - // filho 2 (1) -> via eval também -> são os extras +Object * evalTDS_DEF_COMPLETE(Node* n, STable* scope, EnvController* controllerSmv){ + + if(scope->type != GLOBAL){ + fprintf(stderr, "ERROR: BAD USE OF TDS DEFINITION, CONDITIONAL DEFINITIONS OF MODULES ARE NOT SUPPORTED BY nuXmv.\nPlease refer to the documentation for further info. \n"); + exit(-1); + } char* portName = n->leafs[3]; - Object ** domainInfo = eval(n->children[0],scope,controllerSmv); - Object** extraInfo = eval(n->children[1],scope,controllerSmv); + void* domainInfo = NULL; + TDS_TYPE type; + if(n->children[0]->type == DOMAIN_FUNCTION){ + domainInfo = n->children[0]->children[0]; + type = FUNCTION_APPLY; + } + else{ + domainInfo = eval(n->children[0],scope,controllerSmv); + type = DATA_LIST; + } + return computeTDSBasicOperations(NULL, portName, type, domainInfo, 0, scope, NULL, controllerSmv); +} +Object * evalANON_TDS(Node* n, STable* scope, EnvController* controllerSmv){ + int isDelayed = n->children[1]->type == TDS_ANON_OP_DPASS; + int hasFilter = n->children[1]->type == TDS_ANON_OP_FPASS; + if(lookup(scope,n->leafs[2])){ + fprintf(stderr,"TDS for port %s already declared!\n",n->leafs[2]); + } + Node* pathFilter = hasFilter ? n->children[1]->children[0] : NULL; + Object* encapsulatedTDS = computeTDSBasicOperations(n, n->leafs[2], TDS_DEPEN, NULL, + isDelayed, scope, pathFilter, + controllerSmv); + TDS* newTDS = encapsulatedTDS->values[0]; + addReferenceCurrentScope(newTDS->name,encapsulatedTDS,0,scope); + return encapsulatedTDS; +} - return NULL; +Object* evalTDS_DEF_DEPENDECE(Node* n, STable* scope, EnvController* controllerSmv){ + int hasOption = n->children[0]->nchild == 2; + int isDelayed = hasOption && n->children[0]->children[1]->type == DEF_EXTRAS_DELAYED; + Node* pathFilter = hasOption && !isDelayed ? + n->children[0]->children[1]->children[0] + : NULL; + return computeTDSBasicOperations(n->children[0], n->leafs[3], TDS_DEPEN, NULL, + isDelayed, scope, pathFilter, controllerSmv); } -Object * evalTDS_DATA_TIME_COMPONENT(Node* n, STable* scope, HeaderController* controllerSmv){ +Object * evalTDS_DATA_TIME_COMPONENT(Node* n, STable* scope, EnvController* controllerSmv){ - Object** SYNTH = eval(n->children[0],scope,controllerSmv); - Object* TIME_COMPONENT = SYNTH[0]; - free(SYNTH); - return TIME_COMPONENT; // retona uma "time component" (mas essa sempre vai ser um "vetor" quando subir o nível + //Object* (*SYNTH) (Node*, STable*, EnvController*) = eval; + Node* PROGRAM_PATH = n->children[0]; +/* if(SYNTH->OBJECT_SIZE > 1){ + fprintf(stderr, "TDS data per time not compatible with lists. Please reffer to the documentation for further info. \n"); + exit(-1); + } + // VALIDAR NO PARSER? Ou na hora de sintetizar o que veio dessa time_component? +*/ + int* TIME = malloc(sizeof(int)); + *TIME = atoi(n->leafs[0]); + void* TC[] = {TIME,PROGRAM_PATH}; + Object* SYNTH_TIME_COMPONENT = createObjectDS(TIME_COMPONENT,2,TC,-1,NULL,0); + return SYNTH_TIME_COMPONENT; } -Object * evalTDS_DATA_LIST_DOMAIN(Node* n, STable* scope, HeaderController* controllerSmv){ + +Object * eval_ITERATOR(Node* n, STable* scope, EnvController* controllerSmv){ if(n->nchild > 1){ // deve retornar uma lista com ambos - Object ** list = eval(n->children[0],scope,controllerSmv); // vai ter sempre uma outra lista (que possui uma lista e 1 componente) + Object * LEFT_COMPONENT = eval(n->children[0],scope,controllerSmv); // vai ter sempre uma outra lista (que possui uma lista e 1 componente) // onde a lista possui uma lista e uma componente ... // essa lista tem tamanho: n - Object ** SYNTH_TIME_COMPONENT = eval(n->children[1],scope,controllerSmv); - Object* TIME_COMPONENTE = SYNTH_TIME_COMPONENT[0]; - free(SYNTH_TIME_COMPONENT); + Object * RIGHT_COMPONENT = eval(n->children[1],scope,controllerSmv); + // ao terminar temos os membros da lista MAIS A ESQUERDA e MAIS A DIREITA + + Object* MERGED = mergeGenericList(LEFT_COMPONENT,RIGHT_COMPONENT); // juntando a lista com a componente -> n + 1 (a chamada de cima vai sintetizar uma lista com n+1 membros e outra componnete) // mas como saber o tamanho quando ele subir o nível? @@ -881,61 +914,23 @@ Object * evalTDS_DATA_LIST_DOMAIN(Node* n, STable* scope, HeaderController* con // problema: poderia ficar "redundante" e dificil de manipular considerando as listas. // note que essa estrutura deve ser construida em um método generico + return MERGED; } - - return NULL; -} - -Object* eval_ITERATOR(Node* STARTING_NODE, STable* scope, HeaderController* controllerSmv, int LIST_TYPE){ - - Object* SYNTH_LIST = NULL; - if(STARTING_NODE){ - if(STARTING_NODE->nchild == 1){ - // deixar assim por enquanto; - // é igual ao eval - SYNTH_LIST = eval(STARTING_NODE->children[0],scope,controllerSmv)[0]; - } - else{ - // join list (pega dois objects e "junta" suas listas. - // vai sintetizar primeiro a lista mais a esquerda (contem os primeiros membros ("mais fundo") - // depois vai sintetizar o ultimo membro da lista atual - } + else{ + Object * HEAD = eval(n->children[0],scope,controllerSmv); + return HEAD; } - return SYNTH_LIST; } -*/ - -Object *eval(Node *n, STable *scope, HeaderController *controllerSmv) -{ - //printf("[eval] %s \n",n->name); - if(n) - { - // sintetizado dos filhos - //void** SYNTH_C[n->nchild]; - // sintetizado dos filhos - //void** SYNTH_L[n->nleafs]; - Object* SYNTH_O = NULL; - if(executores[n->type]) - { - printf("[PostProcess - eval] eval especifico \n\n"); - // o nó pode ou não ter mais dem filho, e esse trata o processamento desses nao sendo somente uma varredura e largura. - SYNTH_O = executores[n->type](n,scope,controllerSmv); - } - else - { - //printf("[PostProcess - eval] eval genérico \n"); - if(n->nchild && n->children) - { - int i; // passa a diante (varredura em pos ordem) - for (i=0; i < n->nchild; i++){ - eval(n->children[i],scope,controllerSmv); - } - } - } - return SYNTH_O; - } - return NULL; +void startInterpreter(Node* n, STable* scope, EnvController* controller){ + /* + * Realização de estrutura auxiliar + */ + //Object ** REALIZATION = malloc(sizeof(Object*)*DEFAULT_MEMOI); + //MEMOI = REALIZATION; + eval(n,scope,controller); + commitCurrentTime(scope,controller,*(int*) lookup(scope,"F_TIME")->val->values[0]+1); + letgoNode(n); } diff --git a/src/PostProcess.c b/src/PostProcess.c index d0ffeed..d287e86 100644 --- a/src/PostProcess.c +++ b/src/PostProcess.c @@ -7,26 +7,40 @@ typedef enum MAP_CONVERSIONS { ANY, ANY_TERM, ANY_BREAK_LINE, UN_OP, OP, REDEF_NAME, NAME_BY_SCOPE, NAME_SSCOPE, INIT, NEXT, ASSIGN_TO, ASSIGN_TO_TAB_BREAK_LINE, CASE, CASE_EVAL, N_CASE_EVAL, DEFAULT_CASE_EVAL, EQUAL_CASE_EVAL, - INTERVAL_DEC, BOOLEAN_DEC ,SET, PAR } MAP_CONVERSIONS; + INTERVAL_DEC, BOOLEAN_DEC ,SET, V_MODULE_DEC ,PAR, TDS_MODULE_NAME, TDS_VALUE_REF, + TDS_DELAYED_EXPR_NEXT, TDS_DELAYED_EXPR_NEXT_TIMEV, + TDS_INPUT_EXPR, TDS_INPUT_EXPR_TIMEV, + MODULE_BREAK_LINE } MAP_CONVERSIONS; // ex: 1 + 1 -char* SmvConversions[] = {"%s", "%s;", "%s \n", "%s%s", "%s %s %s ", "%s_redef%d%", "%s_scope%d_%d","%s_scope%d_%d_%d_%d", +char* SmvConversions[] = {"%s", "%s;", "%s\n", "%s%s", "%s %s %s", "%s_redef%d%", "%s_scope%d_%d","%s_scope%d_%d_%d_%d", "init(%s)", "next(%s)", "%s:= %s;", "\t%s:= %s;\n", "case \n\t\t%s\n\t\tTRUE : %s; \n\tesac", "%s : %s;", "\n\t\t%s : %s;\n", "TRUE : %s; \n", "%s = %s : %s; \n", - "\t%s : %d..%d;\n", "\t%s : boolean;\n" , "\t%s : {%s};", "%s, %s" }; - -int ALOC_SIZE_LINE = 300; - - -void copyValueBind(Object* o, char* bind,int index,int defaultValue) + "\t%s : %d..%d;\n", "\t%s : boolean;\n" , "\t%s : {%s};\n", "\t%s : %s;\n", "%s, %s", "tds_%s", "%s.value", + "%s = NULL : %s.value;\n\t\t%s.value = NULL & %s != NULL : NULL;", "next(time) > %d & %s = NULL : %s.value;\n\t\tnext(time) > %d & %s.value = NULL & %s != NULL : NULL;", + "%s = NULL : %s;\n\t\t%s = NULL : %s;", "%s >= %d & %s = NULL : %s;\n\t\t%s >= %d & %s = NULL : %s;", + "MODULE %s\n" }; + + + +/** + * + * @param o + * @param bind + * @param index + * @param defaultValue + * @param valueNotRef serve para quando atualizarmos um type-set (só considera os valores possíveis). + * Assim, a conversão não vai pegar o nome da variável ou a expressão e sim o resultado + */ +void copyValueBind(Object *o, char *bind, int index, int defaultValue, int valueNotRef) { char* formatS = "%s"; char* formatN = "%d"; char* formatRef = "%s[%d]"; if(!index) { - if (o->SINTH_BIND) { + if (!defaultValue && o->SINTH_BIND && !valueNotRef) { sprintf(bind, formatS, o->SINTH_BIND); } else { if (o->type == NUMBER_ENTRY || o->type == T_DIRECTIVE_ENTRY) { @@ -35,16 +49,21 @@ void copyValueBind(Object* o, char* bind,int index,int defaultValue) if (o->type == LOGICAL_ENTRY) { sprintf(bind, formatS, *(int *) o->values[0] && !defaultValue ? "TRUE" : "FALSE"); } - if (o->type == LABEL_ENTRY || o->type == NULL_ENTRY) { + if (o->type == LABEL_ENTRY) { sprintf(bind, formatS, defaultValue? "NULL" : (char *) o->values[0]); } + if(o->type == NULL_ENTRY){ + sprintf(bind, formatS, "NULL"); + } if (o->type == TDS_ENTRY) { // ... } } } else{ - + // listas vão ser objetos (de tamanho > 1) que guardam objetos + Object* listComponent = (Object*) o->values[index]; + copyValueBind(o, bind, 0, defaultValue, 0); } } @@ -53,7 +72,7 @@ void createExprBind(char *result, Object *o1, Object *o2, char *op) { sprintf(result,SmvConversions[UN_OP],op,o1->SINTH_BIND); } else{ - sprintf(result,SmvConversions[OP],o1->SINTH_BIND,o2->SINTH_BIND); + sprintf(result,SmvConversions[OP],o1->SINTH_BIND,op,o2->SINTH_BIND); } } @@ -121,13 +140,6 @@ void bindCondition(STable* scope, Object* conditionExpr){ } - -char* formatDirective(int ctime){ - char* directiveValueBind = malloc(sizeof(char)*ALOC_SIZE_LINE/10); - sprintf(directiveValueBind, "%d", ctime); - return directiveValueBind; -} - char* formatCondtion(STable* scope, int ignoreCond, int ignoreTemporal, char* valueBind, char* directiveValueBind, int firstCondition){ char* condition = !ignoreCond && (scope->type == IF_BLOCK || scope->type == ELSE_BLOCK) ? scope->conditionBind : NULL; // SINTH_BIND do escopo // SINTH_BIND da condição temporal, ex: "next(time) = 2" @@ -156,7 +168,7 @@ char *formatBinds(int ctime, int changeContext, char *directiveValueBind, char * Object *expr, STable *scope, int firstCondition, int initVar, int ignoreTemporal, int ignoreCond) { sprintf(directiveValueBind, "%d", ctime); // SINTH_BIND da diretiva temporal corrente - copyValueBind(expr,valueBind,0,0); // SINTH_BIND da expressão, pode variar para vetores e estruturas complexas + copyValueBind(expr, valueBind, 0, 0, 0); // SINTH_BIND da expressão, pode variar para vetores e estruturas complexas char* condition = !ignoreCond && (scope->type == IF_BLOCK || scope->type == ELSE_BLOCK) ? scope->conditionBind : NULL; // SINTH_BIND do escopo // SINTH_BIND da condição temporal, ex: "next(time) = 2" @@ -181,7 +193,7 @@ char *formatBinds(int ctime, int changeContext, char *directiveValueBind, char * // "otimização" para criar o caso default, se necessário if(initVar){ - copyValueBind(expr,defaultValueBind,0,1); + copyValueBind(expr, defaultValueBind, 0, 1, 0); } // o default vai ser ele mesmo (usado depois na criação de expressão) else{ @@ -193,55 +205,129 @@ char *formatBinds(int ctime, int changeContext, char *directiveValueBind, char * } -void createType(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, const char *newValueBind, Object *newValue, - int type) +void createType(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, char *newValueBind, Object *newValue, + int type, EnvController* controller) { char* newType = malloc(sizeof(char)*ALOC_SIZE_LINE); + int pos = header->VAR_POINTER; if(type == NUMBER_ENTRY || type == T_DIRECTIVE_ENTRY){ - int valSin = newValue? *(int*) newValue->values[0] : 0; - int min = 0; - int max = 1; - if(valSin <= 0){ - min = valSin; - sprintf(newType, SmvConversions[INTERVAL_DEC], varName, valSin, max); - } - if(valSin > 0){ - max = valSin; - sprintf(newType, SmvConversions[INTERVAL_DEC], varName, min, valSin); - } + TypeMinMax* SYNTH_MIN_MAX = (TypeMinMax*) newValue->type_smv_info; + sprintf(newType, SmvConversions[INTERVAL_DEC], varName, SYNTH_MIN_MAX->min, SYNTH_MIN_MAX->max); char* auxDelim = strstr(newType,":"); char* auxFim = strstr(auxDelim,".."); int pointIni = (auxDelim-newType+2); int pointEnd = ((auxFim-newType))-1; - int pos = header->VAR_POINTER; int tam = strlen(newType); - void* po[] = {&pos, &tam, &pointIni, &pointEnd, &min, &max}; - addValue(varName, po, WRITE_SMV_INFO, 6, 0, writeSmvTypeTable, 0); + void* po[] = {&pos, &tam, &pointIni, &pointEnd}; + addSmvInfoDeclaration(varName,po,WRITE_SMV_INFO,4,writeSmvTypeTable,newValue->type_smv_info); } - if(type == LOGICAL_ENTRY){ - sprintf(newType, SmvConversions[BOOLEAN_DEC], varName, newValueBind, newValueBind); - int pos = header->VAR_POINTER; + else if(type == LOGICAL_ENTRY){ + sprintf(newType, SmvConversions[BOOLEAN_DEC], varName); int tam = strlen(newType); void* po[] = {&pos, &tam}; - addValue(varName, po, WRITE_SMV_INFO, 2, 0, writeSmvTypeTable, 0); + addSmvInfoDeclaration(varName,po,WRITE_SMV_INFO,2,writeSmvTypeTable,newValue->type_smv_info); + //addValue(varName, po, WRITE_SMV_INFO, 2, 0, writeSmvTypeTable, 0); } - if(type == TDS_ENTRY || LABEL_ENTRY) + else if(type == LABEL_ENTRY || type == NULL_ENTRY) { - //void* po[] = {&pos, &tam}; - //addTypeSetSmv(varName,po,TYPE_SET,2,writeSmvTypeTable); + sprintf(newType, SmvConversions[SET], varName, newValueBind); + int tam = strlen(newType); + void* po[] = {&pos, &tam}; + addSmvInfoDeclaration(varName,po,WRITE_SMV_INFO,2,writeSmvTypeTable,newValue->type_smv_info); + //addTypeSetSmv(varName, pos, tam, newValueBind, type, writeSmvTypeTable, controller); + } + // cria uma variável que é instancia de modulo nuXmv + else{ + sprintf(newType,SmvConversions[V_MODULE_DEC],varName,newValueBind); + int tam = strlen(newType); + void* po[] = {&pos, &tam}; + addSmvInfoDeclaration(varName,po,WRITE_SMV_INFO,2,writeSmvTypeTable,NULL); + //addValue(varName, po, WRITE_SMV_INFO, 2, 0, writeSmvTypeTable, 0); } header->varBuffer[header->VAR_POINTER] = newType; header->VAR_POINTER += 1; } -void updateType(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, const char *newValue, int type, int minmax, - Object *newValueNumber) +void unionTypeSetMinMaX(HeaderSmv* headerOriginal, TableEntry* entry_info_type_smv, TypeMinMax* other, EnvController* controller){ + TypeSet* original = entry_info_type_smv->val->type_smv_info; + int i; + int *pos = entry_info_type_smv->val->values[0]; + int *size = entry_info_type_smv->val->values[1]; + for(i = other->min; i <= other->max; i++){ + char numString[ALOC_SIZE_LINE/2]; + sprintf(numString,"%d",i); + if(addElementToTypeSet(original,getTypeSetWordFromDict(numString,controller))){ + headerOriginal->varBuffer[*pos] = addParams(headerOriginal->varBuffer[*pos],numString,"{","}",1); + } + } + *size = strlen(headerOriginal->varBuffer[*pos]); +} + +void unionTypeSets(HeaderSmv* headerOriginal, TableEntry* entry_info_type_smv, TypeSet* other) { + TypeSet* original = entry_info_type_smv->val->type_smv_info; + char** hash_set_other = other->hash_set; + int i; + int *pos = entry_info_type_smv->val->values[0]; + int *size = entry_info_type_smv->val->values[1]; + for (i = 0; i <= other->lastIndex; i++) { + if(hash_set_other[i]){ + if(addElementToTypeSet(original,hash_set_other[i])){ + headerOriginal->varBuffer[*pos] = addParams(headerOriginal->varBuffer[*pos],hash_set_other[i],"{","}",1); + } + } + } + *size = strlen(headerOriginal->varBuffer[*pos]); +} + +/** + * Realiza as operações de hash e atualização de um type-set + * @param newValue o novo objeto que foi sintetizado e sua equivalencia em strin vai ser adicionada ao conjunto + * @param varName o nome da variável + * @param writeSmvTypeTable a tabela de simbolos auxiliar + * @param header o header + * @SideEffects: Altera as informações do objeto type-set recuperado da tabela auxiliar + */ +void updateTypeSet(Object* newValue, char* varName, STable* writeSmvTypeTable, HeaderSmv* header, EnvController* controller) +{ + if(!newValue->type_smv_info){ + fprintf(stderr,"[updateTypeSet] ERROR: No SMV_INFO!\n"); + } + TableEntry* entryTypeSetInfo; + entryTypeSetInfo = lookup(writeSmvTypeTable,varName); + if(newValue->type == NUMBER_ENTRY || newValue->type == WRITE_SMV_INFO){ + unionTypeSetMinMaX(header,entryTypeSetInfo,newValue->type_smv_info,controller); + } + else{ + if(newValue->type == LABEL_ENTRY || newValue->type == TYPE_SET){ + unionTypeSets(header,entryTypeSetInfo,newValue->type_smv_info); + } + } + + /* + TableEntry* entryTypeSetInfo; + entryTypeSetInfo = lookup(writeSmvTypeTable,varName); + int* pos = (int*) entryTypeSetInfo->val->values[0]; + int* size = (int*) entryTypeSetInfo->val->values[1]; + TypeSet* typeSet = entryTypeSetInfo->val->type_smv_info; + addTypeSetWordToDict(newValue,controller); + if(addElementToTypeSet(typeSet,getTypeSetWordFromDict(newValue,controller))){ + char* original = header->varBuffer[*pos]; + char* newTypeSet = addParams(original, newValue, "{", "}", 0); + header->varBuffer[*pos] = newTypeSet; + free(original); + *size = strlen(newTypeSet); + } + */ +} + +void updateType(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, const char *newValueBind, int type, + void *newValue, EnvController* controller) { // começando com numérico x..y; // criar enum mapeador ao decorrer... - if(minmax != -1 && type == NUMBER_ENTRY || type == T_DIRECTIVE_ENTRY) + if(type == NUMBER_ENTRY || type == T_DIRECTIVE_ENTRY) { int pos; int size; @@ -255,61 +341,83 @@ void updateType(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, con size = *(int*) entryPosType->val->values[1]; pointIni = *(int*) entryPosType->val->values[2]; pointEnd = *(int*) entryPosType->val->values[3]; - + TypeMinMax* minMaxEntry = entryPosType->val->type_smv_info; + Object* newValueObject = type == T_DIRECTIVE_ENTRY? NULL : newValue; int newPointIni = 0; int newPointEnd = 0; - int sizeNew = strlen(newValue); - // min..max; - if(minmax) - { + int sizeNew = strlen(newValueBind); + int minmax = -1; + if(newValueObject && newValueObject->type_smv_info) { + TypeMinMax* newMinMax = newValueObject->type_smv_info; + if(minMaxEntry){ + minmax = mergeTypeMinMax(minMaxEntry,newMinMax); + } + else{ + fprintf(stderr,"[updateType] Error: %s entry does not contains MIN-MAX!\n",varName); + exit(-1); + } + } + else{ + if(type != T_DIRECTIVE_ENTRY){ + fprintf(stderr,"[updateType] Error: new value does not contains MIN-MAX!\n"); + exit(-1); + } + minmax = changeMinMax(minMaxEntry,*(int*)newValue); + } + if(minmax == 2 || minmax == 0){ + // atualiza o inicio + header->varBuffer[pos] = updateSubStringInterval(newValueBind, header->varBuffer[pos], sizeNew, pointIni, pointEnd, size, &newPointIni, + &newPointEnd, 0); + void* vpInEnd[] = {&newPointEnd}; + updateValue(varName, vpInEnd, WRITE_SMV_INFO, 1, 3, -1, writeSmvTypeTable, 0); + pointEnd = newPointEnd; + } + if(minmax == 2 || minmax == 1){ pointIni = pointEnd+3; // n..max; // nota! o size já está indexbased! pointEnd = header->varBuffer[pos][size-1] == '\n' ? size-3 : size-2; // max;\n (-1 do index based) - (-2 ou -1 dependendo do fim) //size = header->varBuffer[pos][size-1] == '\n' ? size-1 : size; + header->varBuffer[pos]= updateSubStringInterval(newValueBind, header->varBuffer[pos], sizeNew, pointIni, pointEnd, size, &newPointIni, + &newPointEnd, 0); } - updateSubStringInterval(newValue, header->varBuffer[pos], sizeNew, pointIni, pointEnd, size, &newPointIni, - &newPointEnd, 0); - size = -1*((pointEnd-pointIni+1) - sizeNew) + size; - void* vpSize[] = {&size}; - updateValue(varName, vpSize, WRITE_SMV_INFO, 1, 1, -1, writeSmvTypeTable, 0); - - // atualizar o fim do intervalo não mudar a nossa variável pointEnd também! Só atualiza o tamanho - if(!minmax) - { - void* vpInEnd[] = {&newPointEnd}; - updateValue(varName, vpInEnd, WRITE_SMV_INFO, 1, 3, -1, writeSmvTypeTable, 0); - int min = newValueNumber? *(int*) newValueNumber->values[0] : 0; - void* vpmin[] = {&min}; - updateValue(varName, vpmin, WRITE_SMV_INFO, 1, 4, -1, writeSmvTypeTable, 0); - } - else{ - int max = newValueNumber? *(int*) newValueNumber->values[0] : 1; - void* vpmax[] = {&max}; - updateValue(varName, vpmax, WRITE_SMV_INFO, 1, 5, -1, writeSmvTypeTable, 0); + if(minmax != -1){ + //size = -1*((pointEnd-pointIni+1) - sizeNew) + size; + size = strlen(header->varBuffer[pos]); + void* vpSize[] = {&size}; + updateValue(varName, vpSize, WRITE_SMV_INFO, 1, 1, -1, writeSmvTypeTable, 0); } } else{ - printf("[updateType] WARNING: type of %s not declared on headers \n",varName); + printf("[updateType] WARNING: type of %s not declared on aux headers \n",varName); + exit(-1); } } - if(type == LOGICAL_ENTRY){ - // não faz nada + if(type == TDS_ENTRY || type == LABEL_ENTRY || type == NULL_ENTRY){ + updateTypeSet(newValue,varName,writeSmvTypeTable,header,controller); } } -// quebrar em spec next e spec init -void createAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, const char *newValue, char *condition, - int typeExpr, char *defaultEvalCond) -{ +/** + * Encapsula as operações básicas usadas para criar um assign tipo init/next + * @param statenamevar o nome de estado da variavel + * @param varName o nome da variável + * @param newValue o bind do novo valor + * @param condition a condição de um case junto de sua avaliação + * @param typeExpr o tipo de expressão (init/next) + * @param defaultEvalCond a avaliação default do case que será construído (ex: TRUE : nomeVariável ou TRUE: NULL) + * @param freeCondition uma flag usada para verificar a necessidade de dar free em uma condição passada como parâmetro (usado para simplificar responsabilidades) + * @param size o ponteiro para o tamanho da nova string, calculado e passado para função chamadora + * @param pointIni ponteiro para o ponto de inicio do intervalo de interesse da nova string, calculado e passado para função chamadora + * @param pointEnd ponteiro para o ponto de fim do intervalo de interesse da nova string, calculado e passado para função chamadora + * @return um assign em string ao computar todas as informações. + * @SideEffects: Para generalidade, os variáveis fornecidas pelo chamador (size, pointIni, pointEnd) são atualizadas a medida + * que a nova string é constrúida. Além disso o retorno dessa função deve ser liberado da memória após uso. + */ +char * assignCreationOperations(char* statenamevar, char *varName, const char *newValue, char *condition, int typeExpr, char *defaultEvalCond, + int freeCondition, int *size, int *pointIni, int *pointEnd) { - printf("...\n"); char* exprResultString = malloc(sizeof(char)*ALOC_SIZE_LINE); - char exprInterL[300]; - char exprInterR[300]; - sprintf(exprInterL, SmvConversions[typeExpr], varName); + char exprInterR[ALOC_SIZE_LINE]; // parâmetros a ser salvo na tabela auxiliar SMV - int size; - int pointIni; - int pointEnd; if(condition) { @@ -324,15 +432,17 @@ void createAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, c sprintf(exprInterR,SmvConversions[CASE],condition,varName); // default sendo o inicial } } - free(condition); - sprintf(exprResultString,SmvConversions[ASSIGN_TO_TAB_BREAK_LINE],exprInterL,exprInterR); + if(freeCondition){ + free(condition); + } + sprintf(exprResultString,SmvConversions[ASSIGN_TO_TAB_BREAK_LINE],statenamevar,exprInterR); char* auxChPoint; auxChPoint = strstr(exprResultString,";\n"); // devolve exatamente o ponto, devemos ir para o \n long dif = auxChPoint-exprResultString; - size = strlen(exprResultString); - pointIni = dif+1; - pointEnd = pointIni; + *size = strlen(exprResultString); + *pointIni = dif+1; + *pointEnd = *pointIni; } else{ // atualiza o init/next dessa função @@ -343,28 +453,46 @@ void createAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, c // posEnd = posIni + tamanhoString(expressão) sprintf(exprInterR,SmvConversions[ANY],newValue); - sprintf(exprResultString,SmvConversions[ASSIGN_TO_TAB_BREAK_LINE],exprInterL,exprInterR); + sprintf(exprResultString,SmvConversions[ASSIGN_TO_TAB_BREAK_LINE],statenamevar,exprInterR); - size = strlen(exprResultString); - pointIni = (strlen(exprInterL) - 1) + 5; // %s:= %s (+2 para pular ele mesmo e o : e depois = e espaço, e fora o \t no inicio) - pointEnd = pointIni + strlen(exprInterR)-1; + *size = strlen(exprResultString); + *pointIni = (strlen(statenamevar) - 1) + 5; // %s:= %s (+2 para pular ele mesmo e o : e depois = e espaço, e fora o \t no inicio) + *pointEnd = *pointIni + strlen(exprInterR)-1; } - // escreve atribuição no buffer - // encapsular em método(!) - header->assignBuffer[header->ASSIGN_POINTER] = exprResultString; - int pos = header->ASSIGN_POINTER; - header->ASSIGN_POINTER += 1; - //atualiza tabela auxiliar para init/next(var) - void* po[] = {&pos, &size,&pointIni,&pointEnd}; - addValue(exprInterL, po, WRITE_SMV_INFO, 4, 0, writeSmvTypeTable, 0); + return exprResultString; } +// quebrar em spec next e spec init +void createAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, const char *newValue, char *condition, + int typeExpr, char *defaultEvalCond, int freeCondition, int initialNext) +{ + int pos; + int size; + int pointIni; + int pointEnd; + char exprInterL[ALOC_SIZE_LINE]; + sprintf(exprInterL, SmvConversions[typeExpr], varName); + char* assign = assignCreationOperations(exprInterL,varName, newValue, condition, typeExpr, + defaultEvalCond, freeCondition, &size, &pointIni, &pointEnd); + + // escreve atribuição no buffer + // encapsular em método(!) + header->assignBuffer[header->ASSIGN_POINTER] = assign; + pos = header->ASSIGN_POINTER; + header->ASSIGN_POINTER++; + + //atualiza tabela auxiliar para init/next(var) (se necessário) + if(writeSmvTypeTable) { + void* po[] = {&pos, &size,&pointIni,&pointEnd,&initialNext}; + addValue(exprInterL, po, WRITE_SMV_INFO, 5, 0, writeSmvTypeTable, 0); + } +} -void updateAssign(char* varName ,HeaderSmv* header, STable* writeSmvTypeTable, char* newValue, char* condition, int type ,int typeExpr, int minmax) +void updateAssign(char *varName, HeaderSmv *header, STable *writeSmvTypeTable, char *newValue, char *condition, int type, int typeExpr) { // tratamento de init/next(varName):= case ... TRUE : x; esac; , geralmente TRUE: NULL ou outra condição parecida // é sempre o "delmitador final", vai ser um caso similar ao anterior porém entre ponto de interesse - condição default, já que condições não mudam! @@ -396,24 +524,13 @@ void updateAssign(char* varName ,HeaderSmv* header, STable* writeSmvTypeTable, c int newPointInit = 0; int newPointEnd = 0; - // verifica o tamanho possível após a mudança (o +1 é justamente porque se o intervalo é x-y = 0, o tamanho é 1, + // verifica o tamanho possível após audan mça (o +1 é justamente porque se o intervalo é x-y = 0, o tamanho é 1, // ou seja torna como size based ao inves de index based) - if((-1*((pointEnd-pointIni+1) - sizeNew) + size) >= ALOC_SIZE_LINE) - { - char* newStrSize = realloc(header->assignBuffer[pos],ALOC_SIZE_LINE*2); - ALOC_SIZE_LINE = ALOC_SIZE_LINE*2; - if(newStrSize == NULL) - { - fprintf(stderr, "FAIL IN REALLOCATE HEADER SIZE FOR %s !",upVar); - exit(-1); - } - header->assignBuffer[pos] = newStrSize; - } updated = header->assignBuffer[pos]; // é um simples next(x)/init(x):= yyyyyyy; -> substituir y's por expressão nova em newValue antes do delmitador (;) // os delmitadores podem variar, ex: em caso de next(time) o delimitador é (:) - updateSubStringInterval(newValue, updated, sizeNew, pointIni, pointEnd, size, &newPointInit, &newPointEnd, 1); + header->assignBuffer[pos] = updateSubStringInterval(newValue, updated, sizeNew, pointIni, pointEnd, size, &newPointInit, &newPointEnd, 1); // atualizar range de interesse e tamanho da string na tabela! // fazer duas chamadas por enquanto @@ -432,65 +549,167 @@ void updateAssign(char* varName ,HeaderSmv* header, STable* writeSmvTypeTable, c } -char *processActiveName(STable *currentScope, char *varName, int notExistsOutScope, int isOnNextContext) { +char *processActiveName(STable *currentScope, char *varName, int notExistsOutScope, int isOnNextContext, int type) { char* useVar = NULL; - char interScope[ALOC_SIZE_LINE]; //nome com info de scope - char interRedef[ALOC_SIZE_LINE]; //nome com redefinição - // qualquer escopo diferente de GLOBAL/MAIN - if(notExistsOutScope && (currentScope->order || currentScope->level) ){ - // if, else, fors .... - if(currentScope->parent->type != GLOBAL){ - sprintf(interScope,SmvConversions[NAME_SSCOPE],varName,currentScope->parent->level, - currentScope->parent->order,currentScope->level,currentScope->order); + if(type != TDS_ENTRY) { + char interScope[ALOC_SIZE_LINE]; //nome com info de scope + char interRedef[ALOC_SIZE_LINE]; //nome com redefinição + // qualquer escopo diferente de GLOBAL/MAIN + if (notExistsOutScope && (currentScope->order || currentScope->level)) { + // if, else, fors .... + if (currentScope->parent->type != GLOBAL) { + sprintf(interScope, SmvConversions[NAME_SSCOPE], varName, currentScope->parent->level, + currentScope->parent->order, currentScope->level, currentScope->order); + } else { + sprintf(interScope, SmvConversions[NAME_BY_SCOPE], varName, currentScope->level, currentScope->order); + } + useVar = interScope; + } else { + useVar = varName; } - else{ - sprintf(interScope,SmvConversions[NAME_BY_SCOPE],varName,currentScope->level,currentScope->order); + if (isOnNextContext) { + sprintf(interRedef, SmvConversions[NEXT], useVar); + useVar = interRedef; } - useVar = interScope; - } - else{ - useVar = varName; - } - if(isOnNextContext){ - sprintf(interRedef,SmvConversions[NEXT],useVar); - useVar = interRedef; } - char* activeName = malloc(sizeof(ALOC_SIZE_LINE)); + char* activeName = malloc((sizeof(char)*ALOC_SIZE_LINE)+1); strcpy(activeName,useVar); return activeName; } +/** +* Retorna um bind para um valor. Seja uma versão em String do mesmo ou ainda o nome de variável desse valor dentro do +* contexto do nuXmv. +* @param varName o nome da variável recuperado do escopo +* @param parentScope o escopo da entrada da tabela de simbolos +* @param expr o objeto associado +* @param index o indice caso seja uma estrutura de dados +* @param isDefault flag para avaliar para o valor default daquele tipo (0 inteiro, NULL : labels, FALSE : booleans) +* @param isSelf é usado para retornar o bind como sendo o próprio nome da variável (independente do estado, sem init ou next). +* Caso seja usado, esse sobrescreve o isDefault. +* @return retorna uma string alocada com o nome da variável dentro do contexto do nuXmv. +*/ char *formatValueBind(char *varName, STable *parentScope, Object *expr, int index, int isDefault, int isSelf) { if(isSelf){ - char* useVar = processActiveName(parentScope, varName, 1, 0); + char* useVar = processActiveName(parentScope, varName, 1, 0, expr->type); return useVar; } else{ char* valueBind = malloc(sizeof(char)*ALOC_SIZE_LINE); - copyValueBind(expr,valueBind,index,isDefault); + copyValueBind(expr, valueBind, index, isDefault, 0); return valueBind; } } -Object* refCopyOfVariable(TableEntry* var){ +Object *refCopyOfVariable(TableEntry *varLang, EnvController *controller) { char* useVar = NULL; // temos que usar escopo de VAR não o escopo atual de onde a chamada ocorre! // como nesse caso é necessário referênciar EXATAMENTE o nome da variável, - useVar = processActiveName(var->parentScope, var->name, 1, var->val->timeContext); - Object* copyRef = copyObject(var->val); + int C_TIME = *(int*) lookup(varLang->parentScope, "C_TIME")->val->values[0]; + int I_TIME = *(int*) lookup(varLang->parentScope, "I_TIME")->val->values[0]; + useVar = processActiveName(varLang->parentScope, varLang->name, 1, C_TIME > I_TIME, varLang->val->type); + Object* copyRef = copyObject(varLang->val); if(useVar){ - free(copyRef->SINTH_BIND); -// copyRef->SINTH_BIND[0] = '\0'; + if(copyRef->SINTH_BIND){ + free(copyRef->SINTH_BIND); + } copyRef->SINTH_BIND = malloc(sizeof(char)*(strlen(useVar)+ 1)); strcpy(copyRef->SINTH_BIND,useVar); } + + // o nome da variável sem init/next + char* varDeclarationNameRefSmv = processActiveName(varLang->parentScope, varLang->name, 1, 0, varLang->val->type); + if(varDeclarationNameRefSmv){ + // devemos recuperar o type-min-max/type-set do escopo smv apropriado + //(TODO) devemos adaptar isso para o funcionamento das funções usadas por tds. + STable* smv_info = accessSmvInfo(controller,varLang->parentScope->type == GLOBAL || !varLang->parentScope->childOfFunction? + MAIN : FUNCTION_SMV,0); + Object* var_dec_info_smv = lookup(smv_info,varDeclarationNameRefSmv)->val; + if(varLang->val->type != LOGICAL_ENTRY && !var_dec_info_smv->type_smv_info){ + fprintf(stderr,"[refCopyOfVariable] %s missing type SMV info!\n",varLang->name); + exit(-1); + } + if (var_dec_info_smv->type == TYPE_SET) { + copyRef->type_smv_info = copyTypeSet(var_dec_info_smv->type_smv_info); + } else { + copyRef->type_smv_info = copyTypeMinMax(var_dec_info_smv->type_smv_info); + } + free(varDeclarationNameRefSmv); + } free(useVar); return copyRef; } +/** + * Dado que é possível criar ASSIGNS default, vale verificar se devemos sobrescrever esse após a variável + * não ser mais não deterministica. + * @param writeSmvTypeTable a tabela de simbolos auxiliar + * @param statevarname o nome de estado da variável + * @param headerSmv o header auxiliar + * @return 1 caso exista um assign next default + */ +int checkFristDefaultAssign(STable* writeSmvTypeTable, char* statevarname, HeaderSmv* headerSmv){ + TableEntry * defaultNextReg = lookup(writeSmvTypeTable,statevarname); + int isFirst = *(int*) defaultNextReg->val->values[4]; + if(defaultNextReg && isFirst){ + return 1; + } + else{ + return 0; + } +} + +/** + * Cria uma string de assign NEXT sobrescrevendo todas as informações dessa na tabela de simbolos auxiliar. + * @param statevarname o nome de estado da variável + * @param varName o nome da variável + * @param header o header utilizado + * @param writeSmvTypeTable a tabela auxiliar + * @param newValue o novo valor em string + * @param condition a condição para avaliação do valor + * @param defaultEvalCond a condição default de avaliação + */ +void overwriteAssign(char* statevarname, char *varName, HeaderSmv *header, STable *writeSmvTypeTable, const char *newValue, + char *condition, char *defaultEvalCond){ + + int pos; + int size; + int pointIni; + int pointEnd; + int initialNext = 0; + char* assign = assignCreationOperations(statevarname,varName, newValue, condition, NEXT, + defaultEvalCond, 1, &size, &pointIni, &pointEnd); + + TableEntry * defaultNextReg = lookup(writeSmvTypeTable,statevarname); + pos = *(int*) defaultNextReg->val->values[0]; + int sizeOld = *(int*) defaultNextReg->val->values[1]; + memset(header->assignBuffer[pos],0,sizeOld); + + int hashforreg = calculateHashPos(statevarname,writeSmvTypeTable); + writeSmvTypeTable->tableData[hashforreg] = NULL; + letgoEntry(defaultNextReg); + + strcpy(header->assignBuffer[pos],assign); + free(assign); + + //sobrescreve tabela auxiliar para next + void* po[] = {&pos, &size,&pointIni,&pointEnd,&initialNext}; + addValue(statevarname, po, WRITE_SMV_INFO, 5, 0, writeSmvTypeTable, 0); +} + +/** + * Cria um assign NEXT default, para evitar variáveis com estados futuros não deterministicos + * @param useVar o nome da variável + * @param header o header atual + * @param writeSmvTypeTable a tabela de simbolos auxiliar + */ +void createDefaultNext(char* useVar, HeaderSmv* header, STable* writeSmvTypeTable){ + createAssign(useVar, header, writeSmvTypeTable, useVar, NULL, NEXT, NULL, 1, 1); +} + void specAssign(int varInit, char *varName, int contextChange, HeaderSmv *header, STable *scope, STable *writeSmvTypeTable, - Object *newValue, int redef, int typeExpr, int C_TIME) + Object *newValue, int redef, int typeExpr, int C_TIME, EnvController *controller) { // strings para binds //binds da expressão @@ -501,21 +720,10 @@ void specAssign(int varInit, char *varName, int contextChange, HeaderSmv *header // decide o nome apropriado para a variável char* useVar = NULL; // por default, usamos o nome da varável (se não for, em escopos diferentes ou ainda em redef ) - useVar = processActiveName(scope, varName, varInit, 0); + useVar = processActiveName(scope, varName, varInit, 0, newValue->type); - int minmax = -1; - if(typeExpr && newValue->type == NUMBER_ENTRY) { - TableEntry* info = lookup(writeSmvTypeTable,useVar); - if(info){ - int min = *(int*) info->val->values[4]; - int max = *(int*) info->val->values[5]; - int new = *(int *) newValue->values[0]; - - minmax = new < min ? 0 : - new > max ? 1 : minmax; - } - } - int defaultSelf = !varInit && scope->type == IF_BLOCK || scope->type == ELSE_BLOCK; + //int defaultSelf = !varInit && scope->type == IF_BLOCK || scope->type == ELSE_BLOCK; + int defaultSelf = !varInit; defaultValueBind = formatValueBind(varName, scope, newValue, 0, 1, defaultSelf); newValueBind = formatValueBind(varName, scope, newValue, 0, 0, 0); @@ -525,37 +733,44 @@ void specAssign(int varInit, char *varName, int contextChange, HeaderSmv *header char statevarname[ALOC_SIZE_LINE]; sprintf(statevarname,SmvConversions[NEXT],useVar); //verifica se existe next(statevarname) - directiveValueBind = formatDirective(C_TIME); + directiveValueBind = formatNumeric(C_TIME); //defaultValueBind = formatValueBind(newValue,0,1); // vai ser só para o caso de ref de uma variável que foi atualizada dentro de um if (já existe fora do escopo atual) if(lookup(writeSmvTypeTable,statevarname)){ - conditionCube = formatCondtion(scope,0,0,newValueBind,directiveValueBind,0); - updateAssign(useVar, header, writeSmvTypeTable, newValueBind, conditionCube, newValue->type, NEXT, minmax); + if(checkFristDefaultAssign(writeSmvTypeTable, statevarname, header)){ + conditionCube = formatCondtion(scope,0,0,newValueBind,directiveValueBind,1); + overwriteAssign(statevarname,varName,header,writeSmvTypeTable,newValueBind,conditionCube,defaultValueBind); + } + else{ + conditionCube = formatCondtion(scope,0,0,newValueBind,directiveValueBind,0); + updateAssign(useVar, header, writeSmvTypeTable, newValueBind, conditionCube, newValue->type, NEXT); + } } else{ conditionCube = formatCondtion(scope,0,0,newValueBind,directiveValueBind,1); - createAssign(useVar, header, writeSmvTypeTable, newValueBind, conditionCube, NEXT, NULL); + createAssign(useVar, header, writeSmvTypeTable, newValueBind, conditionCube, NEXT, NULL, 1, 0); } - Object* auxRefValue = newValue->type == NUMBER_ENTRY? newValue : NULL; - updateType(useVar, header, writeSmvTypeTable, newValueBind, newValue->type, minmax, auxRefValue); + //Object* auxRefValue = newValue->type == NUMBER_ENTRY? newValue : NULL; + updateType(useVar, header, writeSmvTypeTable, newValueBind, newValue->type, newValue, controller); free(directiveValueBind); } // init casos // caso 1 : init default + next ( seja de variável que só existe em t>0(pode também ser uma redefinição) (devem ignorar condições nesse init) - // caso 2 : init unico, seja para variáveis que foram redefinidas em t = 0 ou declarações comuns + // caso 2 : init unico, seja para variáveis que foram redefinidas em t = 0 ou declarações comuns (e agora com um next default para evitar estouro de estados) else{ if((C_TIME && redef) || contextChange){ conditionCube = formatCondtion(scope,1,1,newValueBind,directiveValueBind,1); - - createType(useVar, header, writeSmvTypeTable, defaultValueBind, newValue, newValue->type); - createAssign(useVar, header, writeSmvTypeTable, defaultValueBind, conditionCube, INIT, defaultValueBind); + createType(useVar, header, writeSmvTypeTable, defaultValueBind, newValue, newValue->type, controller); + createAssign(useVar, header, writeSmvTypeTable, defaultValueBind, conditionCube, INIT, defaultValueBind, 1, + 0); } else{ conditionCube = formatCondtion(scope,0,1,newValueBind,directiveValueBind,1); - createType(useVar, header, writeSmvTypeTable, newValueBind, newValue, newValue->type); - createAssign(useVar, header, writeSmvTypeTable, newValueBind, conditionCube, INIT, defaultValueBind); + createType(useVar, header, writeSmvTypeTable, newValueBind, newValue, newValue->type, controller); + createAssign(useVar, header, writeSmvTypeTable, newValueBind, conditionCube, INIT, defaultValueBind, 1, 0); + createDefaultNext(useVar,header,writeSmvTypeTable); } } free(defaultValueBind); @@ -563,33 +778,519 @@ void specAssign(int varInit, char *varName, int contextChange, HeaderSmv *header free(useVar); } -void updateTime(HeaderSmv* main , STable * writeSmvTypeTable, char* newValue, int type, int typeExpr, int minmax) +void updateTime(HeaderSmv *main, STable *writeSmvTypeTable, char *newValueBind, int type, int typeExpr, int newValue) { - updateType("time", main, writeSmvTypeTable, newValue, type, minmax, NULL); - typeExpr ? updateAssign("time",main,writeSmvTypeTable,newValue,NULL,type,NEXT,minmax) : - updateAssign("time",main,writeSmvTypeTable,newValue,NULL,type,INIT,minmax); + updateType("time", main, writeSmvTypeTable, newValueBind, type, &newValue, NULL); + typeExpr ? updateAssign("time", main, writeSmvTypeTable, newValueBind, NULL, type, NEXT) : + updateAssign("time", main, writeSmvTypeTable, newValueBind, NULL, type, INIT); } -void letGoOldEntry(TableEntry* var, STable* refAuxTable){ - char* useVar = NULL; - // temos que usar escopo de VAR não o escopo atual de onde a chamada ocorre! - // como nesse caso é necessário referênciar EXATAMENTE o nome da variável, +char* createReferenceTDS(char* declaredName){ - int redefNum = var->val->redef == 0? 0 : var->val->redef-1; - useVar = processActiveName(var->parentScope, var->name, 1, 0); - char varInit[ALOC_SIZE_LINE/2]; - char varNext[ALOC_SIZE_LINE/2]; - sprintf(varInit,SmvConversions[INIT],useVar); - sprintf(varNext,SmvConversions[NEXT],useVar); + char interTDS[ALOC_SIZE_LINE]; + sprintf(interTDS, SmvConversions[TDS_MODULE_NAME], declaredName); + char* BIND_TDS = malloc(sizeof(char)*ALOC_SIZE_LINE); + strcpy(BIND_TDS,interTDS); + return BIND_TDS; +} - letGoEntryByName(refAuxTable,useVar); - letGoEntryByName(refAuxTable,varInit); - letGoEntryByName(refAuxTable,varNext); - free(useVar); +/** + * Cria um Header padrão que será escrito no arquivo SMV, sendo salvo até lá no controlador para futuras modificações + * @param type o tipo do HEADER {MAIN = 1, AUTOMATA = 2, PORTS = 3, FUNCTION_SMV = 4} + * @param name o nome processado anteriomente de maneira compor a declaração de módulo + * @param varP o ponteiro de alocaçao de linhas de da parte var (util para controlar casos que o modulo nao venha a necessitar de alguma parte) + * @param assignP o ponteiro de alocaçao de linhas de da parte var + * @param transP o ponteiro de alocaçao de linhas de da parte trans + * @param controller o controlador de ambiente para armazenar o header + * @return o novo header alocado + * @SideEffects: Aloaca um header que deve ser liberado como responsabilidade do chamador + */ +HeaderSmv* specHeader(smvtype type, char* name, int varP, int assignP, int transP, EnvController* controller){ + HeaderSmv* newHeader = createHeader(type, name, varP, assignP, transP, 0); + addNewHeader(controller,newHeader); + selectBuffer(VAR,"VAR\n",newHeader,0); + selectBuffer(ASSIGN,"ASSIGN\n",newHeader,0); + return newHeader; +} + +/*** + * Baseada na validação anterior (para tds's de time-components) verifica se deve criar init vazio ou init e next vazios. + * Isso evita estouro de estados no nuXmv, considerando que caso esses não sejam especificados a TDS pode variar de forma + * não deterministica. + * @param newTDS + * @param controller + * @param initialIsInvalid + * @param someIsValid + */ + +void specAssignForInvalidTds(TDS* newTDS, EnvController* controller, int initialIsInvalid, int someIsValid){ + if(initialIsInvalid){ + // só o inicial é invalido + createAssign("value", accessHeader(controller, PORTS, newTDS->SMV_REF), + accessSmvInfo(controller, PORTS, newTDS->AUX_REF), "NULL", NULL, INIT, NULL, 1, 0); + }else{ + // nenhum é válido + if(!someIsValid){ + createAssign("value", accessHeader(controller, PORTS, newTDS->SMV_REF), + accessSmvInfo(controller, PORTS, newTDS->AUX_REF), "NULL", NULL, INIT, NULL, 1, 0); + createAssign("value", accessHeader(controller, PORTS, newTDS->SMV_REF), + accessSmvInfo(controller, PORTS, newTDS->AUX_REF), "value", NULL, NEXT, NULL, 1, 0); + } + } +} +/** + * Valida se a nova TDS de time-component é válida, isto é, se nenhuma especificação para instantes exatos de tempo + * violam I_TIME ~ F_TIME. Ou ainda, se a especificação da time-component é de um tempo já do passado + * (gerando tornando um assign inútil e avaliações inúteis que podem ter efeitos indesejados no modelo e no interpretador) + * @param encapsulatedTDS o objeto encapsulado da TDS, serve para notificar o usuário por meio do seu SYNTH_BIND em qual variável de TDS ocorreu a violação de validação + * @param newTDS a nova TDS especificada + * @param controller o controlador de ambiente + * @param C_TIME o tempo corrente do intervalo + * @param I_TIME o tempo inícial do intervalo + * @param F_TIME o tempo final do intervalo + * @return + */ + +int validateTdsTimeList(Object* encapsulatedTDS, TDS* newTDS, EnvController* controller, int C_TIME, int I_TIME, int F_TIME){ + int someIsValidToLazy = 0; // nenhum é valido = 0 , algum é valido = 1, -1 a gente pode falar que algum é valido mas o primeiro é invalid (C_TIME = 0) + int initialIsInvalid = 1; + int i; + Object * timeComponentList = newTDS->DATA_SPEC; + for (i = 0; i < timeComponentList->OBJECT_SIZE; i++){ + Object* timeComponent = (Object*) timeComponentList->values[i]; + int time = *(int*) timeComponent->values[0]; + if(time < C_TIME){ + fprintf(stderr, "\n[WARNING] %s TDS's specification on time = %d was not evaluated.\nThe specification was defined on a C_TIME >= %d context! \n", + encapsulatedTDS->SINTH_BIND,time,C_TIME); + initialIsInvalid = time == 0? 1 : initialIsInvalid; + } + else if(time < I_TIME || time > F_TIME){ + fprintf(stderr, "\n[WARNING] %s TDS's specification on time = %d was not evaluated.\nThe specification was defined out of the model time interval: %d ~ %d \n", + encapsulatedTDS->SINTH_BIND,time,I_TIME,F_TIME); + } + else{ + if(!someIsValidToLazy){ + someIsValidToLazy = 1; + } + initialIsInvalid = time == I_TIME? 0 : initialIsInvalid; + newTDS->COMPONENT_TIMES[time] = i; + } + } + specAssignForInvalidTds(newTDS,controller,initialIsInvalid,someIsValidToLazy); + return someIsValidToLazy; +} + +/** + * Adiciona a nova TDS a lista de callby need das TDS (após o COMMIT de C_TIME). Note que, nos casos de Time list nem todas são sempre + * adicionadas a lazy caso o instante de tempo especificado não seja alcançável (validação de time-list). + * Vale ressaltar, que escolhemos epsular o tratamento da validaçao da Time list aqui para nao realizar a validaçao 2 vezes. + * @param encapsulatedTDS o objeto da tds encapsulado + * @param newTDS a TDS em si + * @param controller o controlador de ambiente + * @param C_TIME o tempo corrente + * @param I_TIME o tempo inicial + * @param F_TIME o tempo final + * @SideEffects: Adiciona a TDS a lista de pendentes, e caso seja necessario algum tratamento sobre a data-list seus + * init ou next sao declarados (linha alocada) + */ + +void addTdsToLazyControl(Object* encapsulatedTDS, TDS* newTDS, EnvController* controller, int C_TIME, int I_TIME, int F_TIME){ + int addToLazy = newTDS->type != DATA_LIST? 1: validateTdsTimeList(encapsulatedTDS,newTDS,controller,C_TIME, I_TIME,F_TIME); + if(addToLazy){ + controller->declaredPorts[controller->declaredPortsNumber] = newTDS; + controller->declaredPortsNumber++; + } +} + + + +/** + * Para uma TDS que possuia dependencias, cria os assigns apropriados baseado nas diretivas (delayed, link e filter). + * Essas são especificadas no portsModule para explicitar o relacionamento entre as TDS's. + * @param newTDS a nova TDS + * @param controller o controlador de ambiente + */ +void addTdsRelationOnSmv(TDS *newTDS, EnvController *controller, int I_TIME) { + // adiciona informações de relacionamento no nuXmv (separar em método) + TDS** dependencies = newTDS->linkedDependency; + int limitedByTime = newTDS->I_INTERVAL > I_TIME; + int i; + if(newTDS->delayed){ + if(newTDS->TOTAL_DEPENDENCIES_PT > 1){ + fprintf(stderr, "[WARNING] %s with delayed property and more than one dependency \n",newTDS->name); + exit(-1); + } + + char refToTdsValue[ALOC_SIZE_LINE]; + sprintf(refToTdsValue,SmvConversions[TDS_VALUE_REF],newTDS->name); + char defaultDelayedEvalCond[ALOC_SIZE_LINE]; + if(newTDS->I_INTERVAL > I_TIME){ + sprintf(defaultDelayedEvalCond, SmvConversions[TDS_DELAYED_EXPR_NEXT_TIMEV], newTDS->I_INTERVAL, refToTdsValue, + dependencies[0]->name, newTDS->I_INTERVAL ,dependencies[0]->name, refToTdsValue); + } + else{ + sprintf(defaultDelayedEvalCond, SmvConversions[TDS_DELAYED_EXPR_NEXT], refToTdsValue, + dependencies[0]->name, dependencies[0]->name, refToTdsValue); + } + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0), "NULL", NULL, + INIT, NULL, 0, 0); + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0), NULL, defaultDelayedEvalCond, NEXT, + refToTdsValue, 0, 0); + } + else if(newTDS->TOTAL_DEPENDENCIES_PT > 0){ + + char refToTdsValue[ALOC_SIZE_LINE]; + sprintf(refToTdsValue,SmvConversions[TDS_VALUE_REF],newTDS->name); + + if(newTDS->limitCondition){ + if(newTDS->TOTAL_DEPENDENCIES_PT > 1){ + fprintf(stderr, "[WARNING] %s with filter property and more than one dependency \n",newTDS->name); + exit(-1); + } + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0), "NULL", NULL, + INIT, NULL, 0, 1); + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0), refToTdsValue, NULL, + NEXT, NULL, 0, 1); + } + else { + char defaultDelayedEvalCond[ALOC_SIZE_LINE]; + char refNextToTdsValue[strlen(newTDS->name)+14]; + sprintf(refNextToTdsValue,SmvConversions[NEXT],refToTdsValue); + TDS* firstDependence = dependencies[0]; + + char refToDepTdsValue[strlen(firstDependence->name)+8]; // .value0 + sprintf(refToDepTdsValue,SmvConversions[TDS_VALUE_REF],firstDependence->name); + char refNextToDepTdsValue[strlen(firstDependence->name)+14]; // next(.value) + sprintf(refNextToDepTdsValue,SmvConversions[NEXT],refToDepTdsValue); + + if(newTDS->TOTAL_DEPENDENCIES_PT > 1){ + char resultExprInit[ALOC_SIZE_LINE*2]; + char resultExprNext[ALOC_SIZE_LINE*2+(newTDS->TOTAL_DEPENDENCIES_PT*6)]; + + TDS* secondDependence = dependencies[1]; + char refToDep2TdsValue[strlen(secondDependence->name)+8]; + sprintf(refToDep2TdsValue,SmvConversions[TDS_VALUE_REF],secondDependence->name); + char refNextToDep2TdsValue[strlen(secondDependence->name)+14]; + sprintf(refNextToDep2TdsValue,SmvConversions[NEXT],refToDep2TdsValue); + if(limitedByTime){ + sprintf(resultExprNext,SmvConversions[TDS_INPUT_EXPR_TIMEV], + "next(time)",newTDS->I_INTERVAL,refNextToDep2TdsValue, refNextToDepTdsValue, + "next(time)",newTDS->I_INTERVAL,refNextToDepTdsValue,refNextToDep2TdsValue); + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0), "NULL", NULL, + INIT, NULL, 0, 0); + } + else{ + sprintf(resultExprInit,SmvConversions[TDS_INPUT_EXPR], + refToDep2TdsValue, refToDepTdsValue, + refToDepTdsValue,refToDep2TdsValue); + sprintf(resultExprNext,SmvConversions[TDS_INPUT_EXPR], + refNextToDep2TdsValue, refNextToDepTdsValue, + refNextToDepTdsValue,refNextToDep2TdsValue); + + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), accessSmvInfo(controller, PORTS, 0), + NULL, resultExprInit, INIT, "NULL", 0, 0); + } + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), accessSmvInfo(controller, PORTS, 0), + NULL, resultExprNext, NEXT, "NULL", 0, 0); + } + else{ + if(limitedByTime){ + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0), "NULL", NULL, + INIT, NULL, 0, 0); + + char timeBind[ALOC_SIZE_LINE/2]; + sprintf(timeBind,"%d",newTDS->I_INTERVAL); + char* evalByTimeNext = createConditionCube("next(time)",timeBind,">=",refNextToDepTdsValue,1); + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0), "NULL", evalByTimeNext, + NEXT, NULL, 1, 0); + } + else{ + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), accessSmvInfo(controller, PORTS, 0), + refToDepTdsValue, NULL, INIT, NULL, 0, 0); + createAssign(refToTdsValue, accessHeader(controller, PORTS, 0), accessSmvInfo(controller, PORTS, 0), + refNextToDepTdsValue, NULL, NEXT, NULL, 0, 0); + } + } + } + // limitado a duas dependencias + } +} + + + +/** + * Adiciona a referência de declaração ao novo módulo TDS ao nuXmv (portsModule). + * Caso a TDS seja relacional, o relacionamento será explicitado no portsModule. + * @param moduleName + * @param newEncapsulatedTDS + * @param newTDS + * @param controller + */ + +void addTdsOnSmv(char* moduleName, Object * newEncapsulatedTDS, TDS* newTDS, EnvController* controller){ + char nameWithNoBreakL[ALOC_SIZE_LINE]; + nameWithNoBreakL[0] = '\0'; + char* declarationDetails = strstr(moduleName,"t"); + removeAfter(nameWithNoBreakL,declarationDetails,'\n'); + char* declarationName = newTDS->name? newTDS->name : newEncapsulatedTDS->SINTH_BIND; + createType(declarationName,accessHeader(controller, PORTS, 0), + accessSmvInfo(controller, PORTS, 0),nameWithNoBreakL,NULL,V_MODULE_DEC,controller); + if(newTDS->type == MATH_EXPRESSION || newTDS->type == FUNCTION_APPLY){ + // deve criar um init e next BÁSICOS + // deve-se instanciar a funçao dentro do modulo SMV dessa TDS. (se não fosse inline) + if(newTDS->type == FUNCTION_APPLY){ + createAssign("value", accessHeader(controller, PORTS, newTDS->SMV_REF), + accessSmvInfo(controller, PORTS, newTDS->AUX_REF), "NULL", NULL, + INIT, NULL, 0, 1); + createAssign("value", accessHeader(controller, PORTS, newTDS->SMV_REF), + accessSmvInfo(controller, PORTS, newTDS->AUX_REF), "value", NULL, + NEXT, NULL, 0, 1); + } + } } +TypeSet *computeTypeSet(EnvController *controllerSmv, char *sint_value) { + addTypeSetWordToDict(sint_value, controllerSmv); + TypeSet* newTypeSet = createTypeSet(getTypeSetWordFromDict("NULL",controllerSmv)); + addElementToTypeSet(newTypeSet,getTypeSetWordFromDict(sint_value,controllerSmv)); + return newTypeSet; +} + +/** + * Para uma TDS processada, cria a declaração da variável "value" em seu módulo. Que tem o type-set default com os valores + * NULL, 0, 1 + * @param tdsHeader o header (módulo) associado a tds + * @param auxTable a tabela de simbolos auxiliar + * @param controller o controlador de ambiente (útil para consultar o dicionário de type-sets) + */ +void createDefaultTypeSetTDS(HeaderSmv *tdsHeader, STable* auxTable, EnvController* controller) { + TypeSet* tdsValueTypeSet = computeTypeSet(controller,"0"); + addElementToTypeSet(tdsValueTypeSet,getTypeSetWordFromDict("1",controller)); + char* newType = malloc(sizeof(char)*ALOC_SIZE_LINE); + sprintf(newType, SmvConversions[SET], "value", "NULL, 0, 1"); + int pos = tdsHeader->VAR_POINTER; + int tam = strlen(newType); + void* po[] = {&pos, &tam}; + addSmvInfoDeclaration("value",po,TYPE_SET,2,auxTable,tdsValueTypeSet); + tdsHeader->varBuffer[tdsHeader->VAR_POINTER] = newType; + tdsHeader->VAR_POINTER += 1; +} + + + +void preProcessTDS(Object* encapsulatedTDS, EnvController* controller, int C_TIME, int I_TIME, int F_TIME){ + TDS* SYNTH_TDS = (TDS*)encapsulatedTDS->values[0]; + + SYNTH_TDS->AUX_REF = controller->PORTS_INFO_CURRENT_SIZE; + SYNTH_TDS->SMV_REF = controller->H_PORTS_CURRENT_SIZE; + + char moduleName[ALOC_SIZE_LINE]; + moduleName[0] = '\0'; + sprintf(moduleName,SmvConversions[MODULE_BREAK_LINE],encapsulatedTDS->SINTH_BIND); + HeaderSmv* newTdsHeader = specHeader(PORTS, moduleName, 0, 0, -1, controller); + + STable* auxTable = createTable(SMV_PORTS, NULL, 0, 0, -1); + addNewAuxInfo(controller,auxTable); + + createDefaultTypeSetTDS(newTdsHeader,auxTable,controller); + + char* declarationName = SYNTH_TDS->name? SYNTH_TDS->name : encapsulatedTDS->SINTH_BIND; + + addTdsOnSmv(newTdsHeader->moduleName, encapsulatedTDS, SYNTH_TDS, controller); + if(SYNTH_TDS->type == TDS_DEPEN){ + addTdsRelationOnSmv(SYNTH_TDS, controller, I_TIME); + } + addTdsToLazyControl(encapsulatedTDS,SYNTH_TDS,controller,C_TIME,I_TIME,F_TIME); + validateTdsDeclaration(declarationName,controller); +} + +/** + * Para tds's de avaliação "constante" atualiza seu init e next caso seja necessário + * @param currentTDS a tds corrente + * @param name o nome da variável de atualização + * @param eval o resultado de avaliação (que será da condição ou atribuido direto) + * @param stateId se é init ou next + * @param I_TIME o tempo inicial usado para controle temporal + * @param currentHeader o header usado + * @param currentInfo a info usada + * @param controller o controlador de ambiente + */ +void specTdsAssignOnRevaluation(TDS* currentTDS, char* name, char* eval, int stateId, int I_TIME, + HeaderSmv* currentHeader, STable* currentInfo, EnvController* controller){ + + // validaçoes + // next/init + char stateVarNameTds[strlen(name)+2+4+1+1]; // () init ou next \0 + formatStateVar(name,stateId,stateVarNameTds); + // condição em conjunto (filter + temporal) (se for necessario alguma delas for necessária) + char* condition = NULL; + char* temporalCondition = NULL; // caso seja next, vamos atribuir com uma condição que considera tempo > initTDS + char* cubeFinal = NULL; + //deve então verificar se tem que criar assign ou overwrite para o state selecionado + int hasDefault = checkFristDefaultAssign(currentInfo, stateVarNameTds, currentHeader); + if(hasDefault){ + if(stateId == NEXT && currentTDS->I_INTERVAL != I_TIME){ + char* directiveValueBind = formatNumeric(currentTDS->I_INTERVAL); + temporalCondition = createConditionCube("next(time)", directiveValueBind, ">=", NULL, 1); + } + if(currentTDS->limitCondition){ + condition = currentTDS->currenCondBindRef; + if(controller->relationRef){ + char* originalConditionRef = condition; + // a condição é liberada junto da expressão, podemos substituir diretamente (mas temos que liberar depois) + condition = removeAllSubStrings(originalConditionRef,"ports."); + } + } + cubeFinal = temporalCondition && condition ? + createConditionCube(temporalCondition, condition, "&", eval, 1) : + temporalCondition ? createConditionCube(temporalCondition, "", "", eval,1) : + condition ? createConditionCube(condition, "", "", eval, 1) : + NULL; + overwriteAssign(stateVarNameTds,name,currentHeader,currentInfo,eval,cubeFinal,"NULL"); + if(temporalCondition){ + free(temporalCondition); + } + if(controller->relationRef){ + free(condition); + } + } +} + +void specTDS(TDS* currentTDS, Object* lazyValue, int C_TIME, int I_TIME, EnvController *controller, STable *currentScope) { + + HeaderSmv *currentHeader = !currentTDS->limitCondition? + accessHeader(controller, PORTS, currentTDS->SMV_REF) + : accessHeader(controller,PORTS,0); + STable *currentInfo = !currentTDS->limitCondition? + accessSmvInfo(controller, PORTS, currentTDS->AUX_REF) + : accessSmvInfo(controller,PORTS,0); + + // só necessita de atualizações complexas para data-list as demais vão ser feitas só uma vez + if (currentTDS->type == DATA_LIST) { + if (C_TIME == I_TIME) { + createAssign("value", currentHeader, currentInfo, lazyValue->SINTH_BIND, NULL, INIT, NULL, 1, 0); + } else { + char *conditionCube = NULL; + char *directiveValueBind = formatNumeric(C_TIME); + if (lookup(currentInfo, "next(value)")) { + conditionCube = formatCondtion(currentScope, 0, 0, lazyValue->SINTH_BIND, directiveValueBind, 0); + updateAssign("value", currentHeader, currentInfo, lazyValue->SINTH_BIND, conditionCube, TDS_ENTRY, + NEXT); + } else { + conditionCube = formatCondtion(currentScope, 0, 0, lazyValue->SINTH_BIND, directiveValueBind, 1); + createAssign("value", currentHeader, currentInfo, lazyValue->SINTH_BIND, conditionCube, NEXT, "NULL", + 1, 0); + } + } + } + // só tem que criar um init e next unicos ou somente atualizar o type-set (na verdade essa atualização deve ser feita sempre) + else { + int stateId = C_TIME > I_TIME? NEXT : INIT; + char* evalBind = NULL; + if(currentTDS->limitCondition){ + //{nome_da_TDS}.value + char refToTdsValue[strlen(currentTDS->name)+1+5+1]; // .value\0 + formatTdsValueRef(currentTDS,refToTdsValue); + char* evalRef = NULL; + //{nome_da_dependencia_filtro}.value + char depNameOnSmv[strlen(currentTDS->name)+1+5+1]; // .value\0 + formatTdsValueRef(currentTDS->linkedDependency[0],depNameOnSmv); + //nome da dependencia com next ou o nome anterior + char depNameOnSmvNext[strlen(depNameOnSmv)+2+4+1+1]; // () next \0 + if(stateId == NEXT){ + formatStateVar(depNameOnSmv,stateId,depNameOnSmvNext); + evalBind = depNameOnSmvNext; + } + else{ + evalBind = depNameOnSmv; + } + specTdsAssignOnRevaluation(currentTDS, refToTdsValue, evalBind, stateId, I_TIME, currentHeader, currentInfo, controller); + } + else{ + specTdsAssignOnRevaluation(currentTDS, "value", lazyValue->SINTH_BIND, stateId, I_TIME, currentHeader, currentInfo, controller); + //specTdsAssignOnRevaluation("value", I_TIME, C_TIME, controller); + } + } + if(lazyValue){ + updateType("value",currentHeader,currentInfo,lazyValue->SINTH_BIND,TDS_ENTRY,lazyValue,controller); + } +} + + +void propagateValueToTypeSet(TDS* currentTDS, TDS* dependency, EnvController* controller){ + STable* auxTdsDependant = accessSmvInfo(controller,PORTS,currentTDS->AUX_REF); + HeaderSmv* headerDependant = accessHeader(controller,PORTS,currentTDS->AUX_REF); + Object* newValue = lookup(accessSmvInfo(controller,PORTS,dependency->AUX_REF),"value")->val; + updateTypeSet(newValue,"value",auxTdsDependant,headerDependant,controller); +} + +char* encapsulateExpressionWithNegation(char* expression){ + int newSize = strlen(expression) + 1 + 2; // ! ( ) + char* resultExpr = malloc(sizeof(char)*newSize+1); + sprintf(resultExpr,"!(%s)",expression); + return resultExpr; +} + +void updateAllAutomataFilter(Object* condFilter, EnvController* controller){ + int i; + if(controller->F_AUTOMATAS_CHANGE_POINTER && controller->modelHasFilter){ + //char* cond = "next(x) = 2"; // onde X já vai estar no parâmetro + //char* condNeg = "!next(x) = 2"; // essas condições só estão marretadas ai para testes + char* condNeg = encapsulateExpressionWithNegation(condFilter->SINTH_BIND); + for (i = 0; i < controller->F_AUTOMATAS_CHANGE_POINTER; i++) { + int id_automata = controller->automatasToChange[i]; + HeaderSmv* automata = accessHeader(controller,AUTOMATA,id_automata); + updateAutomataFilterCond(condNeg, automata,0); + updateAutomataFilterCond(condFilter->SINTH_BIND, automata,1); + } + free(condNeg); + } + controller->F_AUTOMATAS_CHANGE_POINTER = 0; + // poderia até dar free nesses caras +} + +void formatStateVar(char* varName, int stateId, char* refToUpdate){ + // init/next(nomeVariavel) (statevar) + //char stateVarNameOnSmv[strlen(varName) + 14]; + sprintf(refToUpdate, SmvConversions[stateId], varName); +} + +void formatTdsValueRef(TDS* currentTds, char* refToUpdate){ + //{nome_da_TDS}.value + //char refToTdsValue[strlen(currentTds->name)+1+5+1]; // .value\0 + sprintf(refToUpdate,SmvConversions[TDS_VALUE_REF],currentTds->name); +} + +char* createPropPathBind(char* parcialPath, char* propName){ + int sizeParcial = strlen(parcialPath); + int sizePropName = strlen(propName); + char* resultPath = malloc(sizeof(char)*(sizeParcial+sizePropName)+1+1); + resultPath[0] = '\0'; + char * refResultPath = resultPath; + refResultPath = customCat(refResultPath,parcialPath,0,0); + refResultPath = customCat(refResultPath,".",0,0); + customCat(refResultPath,propName,0,0); + return resultPath; +} + +char* encapsulateWithNext(char* expression){ + int originalSize = strlen(expression); + int newSize = originalSize + 1 + 4 + 1 + 1; + char* encapsulated = malloc(sizeof(char)*newSize); + sprintf(encapsulated,SmvConversions[NEXT],expression); + return encapsulated; +} + + -void writeResultantHeaders(HeaderController* controller, const char* path){ +void writeResultantHeaders(EnvController* controller, const char* path){ int i; FILE* smvoutput = fopen(path, "w"); diff --git a/src/PreProcess.c b/src/PreProcess.c index 7cbdfe3..f943170 100644 --- a/src/PreProcess.c +++ b/src/PreProcess.c @@ -7,88 +7,38 @@ /* salva o headerSMV do módulo lido anteriormente. se for um automato o ponteiro de transição não é vázio. - efeito colateral: * ao criar ao salvar o header incrementa o tamanho de headers do HeaderController + efeito colateral: * ao criar ao salvar o header incrementa o tamanho de headers do EnvController * cria um header (necessita de free depois) */ -void initPreProcessHeader(smvtype type, char* moduleName, HeaderController* Hcontrol) { +void initPreProcessHeader(smvtype type, char* moduleName, EnvController* Hcontrol) { int transP = type == AUTOMATA? 0 : -1; - HeaderSmv* newHeader = createHeader(type, moduleName, 0, 0, transP); + HeaderSmv* newHeader = createHeader(type, moduleName, 0, 0, transP, Hcontrol->modelHasFilter); + if(type == AUTOMATA && newHeader->expectFilter){ + Hcontrol->modelHasFilter = 1; + if(!Hcontrol->automatasToChange){ + Hcontrol->automatasToChange = malloc(sizeof(int)*100); + } + Hcontrol->automatasToChange[Hcontrol->F_AUTOMATAS_CHANGE_POINTER] = Hcontrol->H_AUTOMATA_CURRENT_SIZE; + Hcontrol->F_AUTOMATAS_CHANGE_POINTER++; + if(strstr(newHeader->moduleName,"final")){ + Hcontrol->modelHasFinalAutomata = 1; + } + } addNewHeader(Hcontrol,newHeader); } - -void selectBuffer(headerpart part, char* line, HeaderSmv* header, int controlRename) { - int pt; - int tam = strlen(line); - char* aloc = malloc((tam+1) * sizeof(char)); - if(part != TRANS) - { - if(part == VAR) - { - - if(header->type == AUTOMATA || (header->type == MAIN && header->VAR_POINTER != header->VAR_RENAME_POINTER) ){ - - char* ref = strstr(line,"("); - if(ref){ - ref = overwriteParam(line,"ports"); - strcpy(aloc,ref); - free(ref); - } - else{ - strcpy(aloc,line); - } - }else{ - strcpy(aloc,line); - } - pt = header->VAR_POINTER; - header->varBuffer[pt] = aloc; - header->VAR_POINTER += 1; - } - if(part == ASSIGN) - { - strcpy(aloc,line); - pt = header->ASSIGN_POINTER; - header->assignBuffer[pt] = aloc; - header->ASSIGN_POINTER += 1; - } - } - else - { - pt = header->TRANS_POINTER; - if(!controlRename) - { - strcpy(aloc,line); - header->transBuffer[pt] = aloc; - } - else - { - //char** bufferAux = clearOldPortsRefs(line); - //printf("[selectBuffer] tratamento de rename refs a portsModule ANTES:%s\n\n",line); - //strcpy(aloc,bufferAux); - clearOldPortsRefs(line,aloc); - header->transBuffer[pt] = aloc; - //printf("[selectBuffer] tratamento de rename refs a portsModule DEPOIS:%s\n\n",header->transBuffer[pt]); - //if(bufferAux){ - // free(bufferAux); - //} - } - header->TRANS_POINTER += 1; - - } -} - /* prepara para chamar a função de escolha de buffer, t ratando a posição (pos) que representa o tamanho do vetor de HEADERS do controller (LEN-1) */ -void saveLineOnBuffer(smvtype currentHeader, headerpart part, char *line, HeaderController *Hcontrol, int controlRename) { +void saveLineOnBuffer(smvtype currentHeader, headerpart part, char *line, EnvController *Hcontrol, int controlRename) { HeaderSmv* current = accessHeader(Hcontrol,currentHeader,-1); selectBuffer(part, line, current, controlRename); } -void processPhase(smvtype stage, headerpart part, HeaderController *Hcontrol, char *line, int controlRename) { +void processPhase(smvtype stage, headerpart part, EnvController *Hcontrol, char *line, int controlRename) { // modulo if(part == CREATE_MODULE) { @@ -103,7 +53,7 @@ void processPhase(smvtype stage, headerpart part, HeaderController *Hcontrol, ch } -void setUpMainSmvTable(HeaderController *Hcontrol, STable *global) +void setUpMainSmvTable(EnvController *Hcontrol, STable *global) { // seta alguns pontos de interesse da diretiva temporal char nome[] = "time"; @@ -124,8 +74,9 @@ void setUpMainSmvTable(HeaderController *Hcontrol, STable *global) pointIni = (auxDelim-linhaLida+2); pointEnd = ((auxFim-linhaLida))-1; - void* po[] = {&pos, &tam, &pointIni, &pointEnd, &min,&max}; - addValue(nome, po, WRITE_SMV_INFO, 6, 0, Hcontrol->mainInfo, 0); + void* po[] = {&pos, &tam, &pointIni, &pointEnd}; + //createMinMax(min,max); + addSmvInfoDeclaration(nome,po,WRITE_SMV_INFO,4,Hcontrol->mainInfo,createMinMax(min,max)); // remover depois? (assim como a gente deve fazer o no pré processamento o "loop do time") @@ -137,10 +88,8 @@ void setUpMainSmvTable(HeaderController *Hcontrol, STable *global) auxFim = strstr(auxDelim,";"); pointIni = auxDelim - linhaLidaInit+2; // pointEnd = auxFim - linhaLidaInit-1; // entra no intervalo de sobrescrita - addValue("init(time)", po, WRITE_SMV_INFO, 4, 0, Hcontrol->mainInfo, 0); - char* linhaLidaNext = Hcontrol->MAIN->assignBuffer[3]; pos = 3; // note que a posição de inicio de leitura do next é irrelevante pela formatação do case tam = strlen(linhaLidaNext); @@ -166,7 +115,7 @@ void setUpMainSmvTable(HeaderController *Hcontrol, STable *global) } -void processPorts(char* buffer, char* varString, char *fVarString, int stage, HeaderController *Hcontrol) { +void processPorts(char* buffer, char* varString, char *fVarString, int stage, EnvController *Hcontrol) { HeaderSmv* portsHeader = accessHeader(Hcontrol, stage, -1); int iniVar = portsHeader->VAR_POINTER == 0; if(iniVar && strstr(buffer,fVarString)) { @@ -181,11 +130,39 @@ void processPorts(char* buffer, char* varString, char *fVarString, int stage, He void* po[] = {&used}; char name[] = {buffer[1],'\0'}; addValue(name,po,LOGICAL_ENTRY,1,0,Hcontrol->originalPorts,-1); + Hcontrol->expectedPorts++; } - Hcontrol->expectedPorts++; } -void preProcessSmv(FILE *smvP, HeaderController *Hcontrol) { +void setDefaultMainSmv(EnvController* controllerSmv){ + saveLineOnBuffer(MAIN,VAR,"VAR\n",controllerSmv,0); + saveLineOnBuffer(MAIN,VAR,"\ttime: 0..3;\n",controllerSmv,0); + HeaderSmv* MAIN_HEADER = accessHeader(controllerSmv,MAIN,0); + MAIN_HEADER->VAR_RENAME_POINTER = MAIN_HEADER->VAR_POINTER; + saveLineOnBuffer(MAIN,VAR,"\tports: portsModule(time);\n",controllerSmv,0); + saveLineOnBuffer(MAIN,ASSIGN,"ASSIGN\n",controllerSmv,0); + saveLineOnBuffer(MAIN,ASSIGN,"\tinit(time) := 0;\n",controllerSmv,0); + saveLineOnBuffer(MAIN,ASSIGN,"\tnext(time) := case\n",controllerSmv,0); + saveLineOnBuffer(MAIN,ASSIGN,"\t\ttime < 3: time + 1;\n",controllerSmv,0); + saveLineOnBuffer(MAIN,ASSIGN,"\t\tTRUE: time;\n",controllerSmv,0); + saveLineOnBuffer(MAIN,ASSIGN,"esac;\n",controllerSmv,0); +} + +void setDefaultPortsSmv(EnvController* controllerSmv){ + saveLineOnBuffer(PORTS,VAR,"VAR\n",controllerSmv,0); + saveLineOnBuffer(PORTS,ASSIGN,"ASSIGN\n",controllerSmv,0); + addNewAuxInfo(controllerSmv,createTable(SMV_PORTS,NULL,0,0,-1)); +} + +void setDefaultSmv(EnvController* controllerSmv){ + initPreProcessHeader(MAIN,"MODULE main\n",controllerSmv); + setDefaultMainSmv(controllerSmv); + initPreProcessHeader(PORTS,"MODULE portsModule\n",controllerSmv); + setDefaultPortsSmv(controllerSmv); + controllerSmv->modelHasFilter = -1; +} + +void preProcessSmv(FILE *smvP, EnvController *Hcontrol) { /*Strings que são usadas para a busca no arquivo*/ char varString[] = "VAR \n"; char assignString[] = "ASSIGN"; @@ -210,7 +187,7 @@ void preProcessSmv(FILE *smvP, HeaderController *Hcontrol) { char* buffer; char* bufferAux; - size_t bufsize = 300; + size_t bufsize = ALOC_SIZE_LINE; buffer = (char *) malloc(bufsize * sizeof(char)); //bufferAux = (char *) malloc(bufsize * sizeof(char)); @@ -277,6 +254,7 @@ void preProcessSmv(FILE *smvP, HeaderController *Hcontrol) { } else { + addNewAuxInfo(Hcontrol,createTable(SMV_PORTS,NULL,0,0,-1)); break; // não precisa mais ler(vai ser lido da arvore) } @@ -294,6 +272,15 @@ void preProcessSmv(FILE *smvP, HeaderController *Hcontrol) { if(readPortsModule){ processPorts(buffer,varString,fVarString,stage,Hcontrol); } + if(stage == AUTOMATA){ + if(bufferAux[1] == 'p'){ + HeaderSmv* current = accessHeader(Hcontrol,AUTOMATA,-1); + char* depCenterFilter = "filter"; + if(strstr(bufferAux,depCenterFilter)){ + current->VAR_RENAME_POINTER = current->VAR_POINTER; + } + } + } } else { diff --git a/src/Visitor.c b/src/Visitor.c new file mode 100644 index 0000000..e148ee8 --- /dev/null +++ b/src/Visitor.c @@ -0,0 +1,54 @@ +// +// Created by mateus on 22/03/2021. +// +#include +#include +#include "../headers/Visitor.h" + +Object* (*realizacaoAvaliaco[160]) (Node* n, STable* scope, EnvController* controllerSmv) = { + evalNUM, evalBOOL, evalSTRING, evalNULL, evalIDVAR, evalTIME_DIRECTIVE, + evalDataV, evalPARAMS_CALL, evalPARAMS ,evalDEFINE_INTERVAL ,evalAC_V, + eval_ASSIGN_TDIRECTIVE, evalOTHER_ASSIGN, evalV_PROP, evalADD_V, evalADD_V_PROP, evalV_PROP_TDS, evalEXPR, + evalMINUS, evalPLUS, evalMULTI, evalDIV, evalLE, evalGE, evalLT, evalGT, evalEQUAL, evalNEQUAL, evalNOT, evalAND, evalOR, evalIMP, evalBIMP, + evalPRI_EXPR, evalCMD_IF, + evalTDS_DEF_COMPLETE, evalTDS_DEF_DEPENDECE, evalANON_TDS, eval_ITERATOR, evalTDS_DATA_TIME_COMPONENT, + evalV_PROP_TDS_VALUE +}; + +Object* (* *executores) (Node* n, STable* scope, EnvController* controllerSmv) = realizacaoAvaliaco; + + +Object *eval(Node *n, STable *scope, EnvController *controllerSmv) +{ + //printf("[eval] %s \n",n->name); + if(n) + { + // sintetizado dos filhos + //void** SYNTH_C[n->nchild]; + // sintetizado dos filhos + //void** SYNTH_L[n->nleafs]; + Object* SYNTH_O = NULL; + + if(executores[n->type]) + { + //printf("[PostProcess - eval] eval especifico \n\n"); + // o nó pode ou não ter mais dem filho, e esse trata o processamento desses nao sendo somente uma varredura e largura. + SYNTH_O = executores[n->type](n,scope,controllerSmv); + } + else + { + //printf("[PostProcess - eval] eval genérico \n"); + if(n->nchild && n->children) + { + int i; // passa a diante (varredura em pos ordem) + for (i=0; i < n->nchild; i++){ + eval(n->children[i],scope,controllerSmv); + } + } + } + return SYNTH_O; + } + return NULL; +} + + diff --git a/src/datastructures/HeaderSmv.c b/src/datastructures/HeaderSmv.c index 93e9fb2..228d1aa 100644 --- a/src/datastructures/HeaderSmv.c +++ b/src/datastructures/HeaderSmv.c @@ -3,27 +3,51 @@ #include #include "../../headers/HeaderSmv.h" - - -HeaderSmv* createHeader(int type, char* moduleName, int varP, int assignP, int transP) { +/** + * Adiciona a um header as informaçoes de filter (caso seja necessario) + * @param header o header corrente + * @param finalAutomataFilterModel a informaçao de contexto fornecida pelo controlador de ambiente que diz se o modelo lido tem filter no final automata + */ +void filterAutomataHeaderCheck(HeaderSmv* header, int finalAutomataFilterModel); + +/** + * Adiciona os pontos de interesse da transiçao de um automato as informaçoes do header. + * NOTA: Assume que as strings do modelo sejam da forma xxxxxxxxxx & TRUE) ... Onde o true é uma condição parametrizável, + * o primeiro a ser encontrado deve a condição de negação e o segundo a condição em si + * @param pHeadersmv o header tendo a transiçao avaliada + */ +void getFilterPoints(HeaderSmv *pHeadersmv); + +HeaderSmv * createHeader(enum smvtype type, char *moduleName, int varP, int assignP, int transP, int finalAutomataFilterModel) { HeaderSmv* header = (HeaderSmv*) malloc(sizeof(HeaderSmv)); + if(type != MAIN){ + header->PARAM_MAP = malloc(sizeof(int)*MAX_PARAM); // NOTE ! ele não inicia com zeros! Deve fazer limpeza. + for (int i = 0; i < 200; i++) { + header->PARAM_MAP[i] = 0; + } + } if(type == PORTS){ char* refOldPt; // só adiciona parâmetro se for portsModule refOldPt = moduleName; - char* newDeclaration = addParams(refOldPt,"time","(",")"); + char* newDeclaration = addParams(refOldPt, "time", "(", ")", 0); header->moduleName = newDeclaration; + int mapTime = hash("time",MAX_PARAM); + header->PARAM_MAP[mapTime] = 1; } else{ if(type == AUTOMATA){ header->moduleName = overwriteParam(moduleName,"ports"); + int mapPorts = hash("ports",MAX_PARAM); + header->PARAM_MAP[mapPorts] = 1; } else{ char* name = malloc((strlen(moduleName)+1) * sizeof(char)); strcpy(name, moduleName); header->moduleName = name; + header->expectFilter = -1; } } @@ -41,12 +65,13 @@ HeaderSmv* createHeader(int type, char* moduleName, int varP, int assignP, int t else{ header->transBuffer = NULL; } + filterAutomataHeaderCheck(header,finalAutomataFilterModel); // if(type == MAIN){ // header->VAR_RENAME_POINTER = 2; // } // else{ - header->VAR_RENAME_POINTER = -1; // ref a ports Module ficará em main + header->VAR_RENAME_POINTER = -1; // ref a ports Module ficará em main e filter de finalAutomata // } return header; @@ -59,6 +84,7 @@ void letgoHeader(HeaderSmv* h){ } //printf("[letgoHeader] DEBUG: liberando %s \n",h->moduleName); free(h->moduleName); + h->moduleName = NULL; int i; for(i = 0; i< h->VAR_POINTER; i++){ @@ -73,7 +99,8 @@ void letgoHeader(HeaderSmv* h){ //rintf("[letgoHeader] DEBUG: liberando buffer VAR! \n"); free(h->varBuffer); - + h->varBuffer = NULL; + for(i = 0; i< h->ASSIGN_POINTER; i++) { if(h->assignBuffer[i]){ free(h->assignBuffer[i]); @@ -81,19 +108,30 @@ void letgoHeader(HeaderSmv* h){ } //printf("[letgoHeader] DEBUG: liberando buffer ASSIGN! \n"); free(h->assignBuffer); + h->assignBuffer = NULL; if(h->transBuffer) { - for(i = 0; i< h->TRANS_POINTER; i++) { - //printf("???\n"); - if(h->transBuffer[i]){ - free(h->transBuffer[i]); - } - } - //printf("[letgoHeader] DEBUG: liberando buffer TRANS! \n"); - free(h->transBuffer); + for (i = 0; i < h->TRANS_POINTER; i++) { + if (h->transBuffer[i]) { + free(h->transBuffer[i]); + } + } + //printf("[letgoHeader] DEBUG: liberando buffer TRANS! \n"); + free(h->transBuffer); + h->transBuffer = NULL; + } + if(h->PARAM_MAP){ + free(h->PARAM_MAP); + h->PARAM_MAP = NULL; + } + if(h->filterPosNeg){ + free(h->filterPosNeg); + h->filterPosNeg = NULL; + } + if(h->filterPosCond){ + free(h->filterPosCond); + h->filterPosCond = NULL; } - - free(h); } @@ -107,77 +145,7 @@ void letGoRelatedHeaders(HeaderSmv** RHeader, int size){ } } -void letGoHeadersStruct(HeaderController *H) { - - letgoHeader(H->MAIN); - letGoRelatedHeaders(H->AUTOMATA_RELATED, H->H_AUTOMATA_CURRENT_SIZE); - letGoRelatedHeaders(H->PORTS_RELATED, H->H_PORTS_CURRENT_SIZE); - letGoRelatedHeaders(H->FUNCTIONS, H->H_FUNCTION_CURRENT_SIZE); - - letgoTable(H->mainInfo); - // assim como temos n headers de função temos n tabelas de simbolos auxiliares que pode ou não ter sido liberada - // antecipidamente (quando a função já terminou de ser escrita como smv) - if(H->functionsInfo){ - int i; - for (i=0; i < H->H_FUNCTION_CURRENT_SIZE; i++){ - if(H->functionsInfo[i]){ - letgoTable(H->functionsInfo[i]); - } - } - } - //letgoTable(H->portsInfo); - letgoTable(H->originalPorts); - free(H); -} - -HeaderController *createController() { - - int DEFAULT_HEADERS_SIZE = 100; - - HeaderController* Hcontrol = malloc(sizeof(HeaderController)); - Hcontrol->H_AUTOMATA_CURRENT_SIZE = 0; - Hcontrol->H_PORTS_CURRENT_SIZE = 0; - Hcontrol->H_FUNCTION_CURRENT_SIZE = 0; - - Hcontrol->originalPorts = createTable(SMV_PORTS, NULL, 0, 0, -1); - Hcontrol->mainInfo = createTable(SMV_V_MAIN, NULL, 0, 0, -1); - Hcontrol->functionsInfo = malloc(sizeof(STable*)*DEFAULT_HEADERS_SIZE); - int i; - for (i = 0; i < DEFAULT_HEADERS_SIZE; i++) { - Hcontrol->functionsInfo[i] = NULL; - } - - //Hcontrol->portsInfo = createTable(SMV_PORTS,NULL,0,0); - - Hcontrol->MAIN = NULL; - Hcontrol->AUTOMATA_RELATED = malloc(sizeof(HeaderSmv*)*DEFAULT_HEADERS_SIZE); - Hcontrol->PORTS_RELATED = malloc(sizeof(HeaderSmv*)*DEFAULT_HEADERS_SIZE); - Hcontrol->FUNCTIONS = malloc(sizeof(HeaderSmv*)*DEFAULT_HEADERS_SIZE); - - Hcontrol->expectedPorts = 0; - Hcontrol->declaredPorts= 0; - return Hcontrol; -} - -void letGoHeaderControl(HeaderController* Hcontrol) { - letGoHeadersStruct(Hcontrol); -} - -void printAllHeaders(HeaderController* Hcontrol){ - int i; - printHeader(Hcontrol->MAIN); - - for (i = 0; i < Hcontrol->H_FUNCTION_CURRENT_SIZE; i++){ - printHeader(Hcontrol->FUNCTIONS[i]); - } - for (i = 0; i < Hcontrol->H_AUTOMATA_CURRENT_SIZE; i++){ - printHeader(Hcontrol->AUTOMATA_RELATED[i]); - } - for (i = 0; i < Hcontrol->H_PORTS_CURRENT_SIZE; i++){ - printHeader(Hcontrol->PORTS_RELATED[i]); - } -} void printHeaderBuffer(HeaderSmv* h, int part, char* partString) { int i; @@ -225,7 +193,7 @@ void printHeader(HeaderSmv* h) { } // if(h->type == PORTS){ -// printf("ports: %s\n",h->declaredPorts[0]); +// printf("ports: %s\n",h->declaredPortsNumber[0]); // } char* tiposBuffers[] = { @@ -279,66 +247,161 @@ void writeHeader(HeaderSmv* header, FILE* smvoutput){ } -HeaderSmv* accessHeader(HeaderController* controller, smvtype cat, int indexOfHeader){ - HeaderSmv* toReturn = NULL; - if(cat == MAIN){ - toReturn = controller->MAIN; +void selectBuffer(headerpart part, char* line, HeaderSmv* header, int controlRename) { + int pt; + char* aloc = malloc(ALOC_SIZE_LINE*sizeof(char)); // o +2 é estritamente para acomodar tamanho extra do buffer + if(part != TRANS) + { + if(part == VAR) + { + + if(header->type == AUTOMATA || (header->type == MAIN && header->VAR_POINTER != header->VAR_RENAME_POINTER) ){ + + char* ref = strstr(line,"("); + if(ref){ + ref = overwriteParam(line,"ports"); + strcpy(aloc,ref); // CUIDADO, strcpy copia mesmo que o buffer dest não tenha tamanho o suficiente + free(ref); + } + else{ + strcpy(aloc,line); + } + }else{ + strcpy(aloc,line); + } + pt = header->VAR_POINTER; + header->varBuffer[pt] = aloc; + header->VAR_POINTER += 1; + } + if(part == ASSIGN) + { + strcpy(aloc,line); + pt = header->ASSIGN_POINTER; + header->assignBuffer[pt] = aloc; + header->ASSIGN_POINTER += 1; + } } + else + { + pt = header->TRANS_POINTER; + if(!controlRename) + { + strcpy(aloc,line); + header->transBuffer[pt] = aloc; + } + else + { + clearOldPortsRefs(line,aloc); + header->transBuffer[pt] = aloc; + if(header->expectFilter){ + getFilterPoints(header); + } + } + header->TRANS_POINTER += 1; - if(cat == AUTOMATA){ - toReturn = indexOfHeader != -1? controller->AUTOMATA_RELATED[indexOfHeader] : controller->AUTOMATA_RELATED[controller->H_AUTOMATA_CURRENT_SIZE-1]; - } - if(cat == PORTS){ - toReturn = indexOfHeader != -1? controller->PORTS_RELATED[indexOfHeader] : controller->PORTS_RELATED[controller->H_PORTS_CURRENT_SIZE-1]; } +} - if(cat == FUNCTION_SMV){ - toReturn = indexOfHeader != -1? controller->FUNCTIONS[indexOfHeader] : controller->FUNCTIONS[controller->H_FUNCTION_CURRENT_SIZE-1]; - } +void getFilterPoints(HeaderSmv *pHeadersmv) { + char* transString = pHeadersmv->transBuffer[pHeadersmv->TRANS_POINTER]; + char* ref = strstr(transString," TRUE"); + if(ref){ + int ini = (ref-transString)+1; + int end = ini+3; - if(!toReturn){ - fprintf(stderr, "[accessHeader] INVALID SMV TYPE FOR OPERATION"); - exit(-1); - } - return toReturn; + int negPos = pHeadersmv->filterPosNeg[0]; + if(!negPos){ + pHeadersmv->filterPosNeg[0] = pHeadersmv->TRANS_POINTER; + pHeadersmv->filterPosNeg[1] = ini; + pHeadersmv->filterPosNeg[2] = end; + } + else{ + pHeadersmv->filterPosCond[0] = pHeadersmv->TRANS_POINTER; + pHeadersmv->filterPosCond[1] = ini; + pHeadersmv->filterPosCond[2] = end; + } + } } - -STable* accessSmvInfo(HeaderController* controller, smvtype cat, int SMV_INFO_ID){ - if(cat == MAIN){ - return controller->mainInfo; +void filterAutomataHeaderCheck(HeaderSmv* header, int finalAutomataFilterModel){ + int nameFilter = 0; + int nameFinal = 0; + if(header->type == AUTOMATA){ + if(header->moduleName[7] == 'f'){ + nameFilter = !!strstr(header->moduleName,"filter"); + if(finalAutomataFilterModel && !nameFilter){ + nameFinal = !!strstr(header->moduleName,"final"); + } + } } - if(SMV_INFO_ID > 0 && SMV_INFO_ID < controller->H_FUNCTION_CURRENT_SIZE && cat == FUNCTION_SMV){ - return controller->functionsInfo[SMV_INFO_ID]; + header->expectFilter = nameFilter || nameFinal; + if(header->expectFilter){ + header->filterPosNeg = malloc(sizeof(int)*3); + header->filterPosCond = malloc(sizeof(int)*3); } -// if(cat == PORTS){ -// return controller->portsInfo; -// } - if(cat == AUTOMATA){ - return NULL; // melhorar, apesar que sabe-se que não tem operação em tabela de simbolos para automato (por enquanto) + else{ + header->filterPosNeg = NULL; + header->filterPosCond = NULL; } - fprintf(stderr, "[accessSmvInfo] INVALID SMV TYPE FOR OPERATION"); - exit(-1); } -void addNewHeader(HeaderController* controller, HeaderSmv* newHeader){ - if(newHeader->type == MAIN){ - controller->MAIN = newHeader; +void updateAutomataFilterCond(const char *cond, const HeaderSmv *automata, int type) { + int pos; + int newIni; + int newEnd; + if(type){ + pos = automata->filterPosCond[0]; + newIni = automata->filterPosCond[1]; + newEnd = automata->filterPosCond[2]; } - if(newHeader->type == AUTOMATA){ - controller->AUTOMATA_RELATED[controller->H_AUTOMATA_CURRENT_SIZE] = newHeader; - controller->H_AUTOMATA_CURRENT_SIZE++; + else{ + pos = automata->filterPosNeg[0]; + newIni = automata->filterPosNeg[1]; + newEnd = automata->filterPosNeg[2]; } - if(newHeader->type == PORTS){ - controller->PORTS_RELATED[controller->H_PORTS_CURRENT_SIZE] = newHeader; - controller->H_PORTS_CURRENT_SIZE++; + char* refLine = automata->transBuffer[pos]; + int sizeOld = strlen(refLine); + int sizeCond = strlen(cond); + automata->transBuffer[pos] = updateSubStringInterval(cond,refLine,sizeCond,newIni,newEnd, + sizeOld,&newIni,&newEnd,0); + if(type){ + automata->filterPosCond[1] = newIni; + automata->filterPosCond[2] = newEnd; } - if(newHeader->type == FUNCTION_SMV ){ - controller->FUNCTIONS[controller->H_FUNCTION_CURRENT_SIZE] = newHeader; - controller->H_FUNCTION_CURRENT_SIZE++; + else{ + automata->filterPosNeg[1] = newIni; + automata->filterPosNeg[2] = newEnd; + } +} + +int addParamToModule(HeaderSmv* updated , char* param){ + int possibleParamPos = hash(param,MAX_PARAM); + if(updated->PARAM_MAP[possibleParamPos]){ + return 0; } + char* newName = addParams(updated->moduleName, param, "(", ")", 0); + free(updated->moduleName); + updated->moduleName = newName; + updated->PARAM_MAP[possibleParamPos] = 1; + return 1; +} + + +void addParamInterestPointHeader(HeaderSmv* header, char *paramName, int offSetPointer) { + char* refOldPt; + refOldPt = header->varBuffer[header->VAR_RENAME_POINTER-offSetPointer]; + char* newDeclaration = addParams(refOldPt, paramName, "(", ")", 0); + free(refOldPt); + header->varBuffer[header->VAR_RENAME_POINTER-offSetPointer] = newDeclaration; +} + +void addParamToHeader(HeaderSmv* headerSmv, char* param){ + char* refOldPt = headerSmv->moduleName; + char* newDeclaration = addParams(refOldPt, param, "(", ")", 0); + free(headerSmv->moduleName); + headerSmv->moduleName = newDeclaration; } void propagParamDependence(HeaderSmv** headers, char* param, int sizeHeaders){ @@ -346,30 +409,9 @@ void propagParamDependence(HeaderSmv** headers, char* param, int sizeHeaders){ char* refOldPt; for(i = 0; i < sizeHeaders; i++){ refOldPt = headers[i]->varBuffer[headers[i]->VAR_RENAME_POINTER]; - char* newDeclaration = addParams(refOldPt,param,"(",")"); + char* newDeclaration = addParams(refOldPt, param, "(", ")", 0); free(refOldPt); headers[i]->varBuffer[headers[i]->VAR_RENAME_POINTER] = newDeclaration; } } -void addParamToPortsModule(HeaderController *controller, char *param, int first) { - HeaderSmv* updated = accessHeader(controller,PORTS,0); // O PORTS MODULE É SEMPRE O PRIMEIRO - char* newName = addParams(updated->moduleName,param,"(",")"); - free(updated->moduleName); - updated->moduleName = newName; - // agora deve propagar as alterações para todos os demais módulos - // OU SEJA JÁ QUE ESTÁ CENTRALIZADO NO MAIN (posição 3 do buffer de VAR), deve-se substituir esse - - HeaderSmv* mainUpdate = accessHeader(controller,MAIN,-1); - - char* refOldPt; - refOldPt = mainUpdate->varBuffer[mainUpdate->VAR_RENAME_POINTER]; - char* newDeclaration = addParams(refOldPt,param,"(",")"); - free(refOldPt); - mainUpdate->varBuffer[mainUpdate->VAR_RENAME_POINTER] = newDeclaration; - -// if(!first){ -// propagParamDependence(controller->MAIN_RELATED,param,controller->H_MAIN_CURRENT_SIZE); -// } -// propagParamDependence(controller->AUTOMATA_RELATED,param,controller->H_AUTOMATA_CURRENT_SIZE); -} diff --git a/src/datastructures/Node.c b/src/datastructures/Node.c index bf953ab..e720a93 100644 --- a/src/datastructures/Node.c +++ b/src/datastructures/Node.c @@ -9,29 +9,34 @@ const char* mappingEnumNode[] = { "NUMBER", "L_BOOL", "STRING", "D_NULL", "IDVAR", "TIME_DIRECTIVE", - "DATA_V", "PARAMS_CALL", "DEFINE_INTERVAL", + "DATA_V", "PARAMS_CALL", "PARAMS", "DEFINE_INTERVAL", - "AC_V", "OTHER_ASSIGN", "V_PROP", "ADD_V", "ADD_V_PROP", "V_PROP_TDS", + "AC_V", "ASSIGN_TDIRECTIVE" ,"OTHER_ASSIGN", "V_PROP", "ADD_V", "ADD_V_PROP", "V_PROP_TDS", - "EXPR", "CMD_IF", "MATCH_IF", + "EXPR", "MINUS_EXPR", "PLUS_EXPR", "MULTI_EXPR", "DIV_EXPR", "LE_EXPR", "GE_EXPR", "LT_EXPR", "GT_EXPR", "EQUAL_EXPR", "NEQUAL_EXPR", + "NOT_EXPR", "AND_EXPR", "OR_EXPR", "IMP_EXPR", "BIMP_EXPR", "PRI_EXPR", - "ASSIGN_IDVAR", "ASSIGN_AC_V", "ASSIGN_TDIRECTIVE", + "CMD_IF", "TDS_DEF_COMPLETE", "TDS_DEF_DEPEN", "CMD_TDS_ANON", + + "LIST_ITERATOR", "TIME_COMP", "V_PROP_TDS_VALUE", "DOMAIN_FUNCTION", - "TDS_DEF_COMPLETE", "TD_DEF_DEPEN", + "MATCH_IF", - "DOMAIN_FUNCTION", "TIME_LIST", "TIME_COMP", + "ASSIGN_IDVAR", "ASSIGN_AC_V", "ASSIGN_TDIRECTIVE", - "DEF_EXTRAS_LINKED", "DEF_EXTRAS_DELAYED", + "DEF_EXTRAS_LINKED", "DEF_EXTRAS_DELAYED", "DEF_EXTRAS_FILTER", "HEADERS_E_PROG", "PROG", "FUNC_DEFS", "CMD", - "FUNC_DEF", "PROC_DEF", "OPT_RETURN", "PARAMS", "PARAM", + "FUNC_DEF", "PROC_DEF", "OPT_RETURN", "PARAM", + + "CMD_OTHER", - "CMD_OTHER", + "TDS_ANON_OP_PASS", "TDS_ANON_OP_DPASS", "TDS_ANON_OP_FPASS", - "CMD_TDS_ANON", "TDS_ANON_OP_PASS", "TDS_ANON_OP_DPASS", + "OTHER_LOOP", "FUNC_CALL", "PROC_CALL", - "OTHER_LOOP", "FUNC_CALL", "PROC_CALL" + "SHOW_PRINT" }; diff --git a/src/datastructures/STable.c b/src/datastructures/STable.c index cb9f00f..d328161 100644 --- a/src/datastructures/STable.c +++ b/src/datastructures/STable.c @@ -2,7 +2,6 @@ #include #include #include "../../headers/STable.h" -#include "../../headers/constants.h" const char* mappingEnumTable[] = { @@ -39,7 +38,7 @@ TableEntry* createEntry(char* name, Object* val, int methodParam, STable* parent } *dest = '\0'; - printf("[createEntry] novo nome: %s \n",newName); + //printf("[createEntry] novo nome: %s \n",newName); newEntry->name = newName; newEntry->val = val; // objects sempre vão ser alocados, string devemos ter tratativa! (a não ser que essa seja alocada pelo bison?) @@ -65,7 +64,7 @@ void printEntry(TableEntry* e) { printObject(e->val); if(e->val->type == TYPE_SET) { - printTable((STable*)e->val->values[2]); + //printTable((STable*)e->val->values[2]); } printf(")"); printf("\n"); @@ -104,6 +103,7 @@ STable *createTable(SCOPE_TYPE type, STable *parent, int level, int order, int i newtable->collision = 0; newtable->conditionBind = NULL; newtable->notEvaluated = 0; + newtable->notWrite = 0; newtable->children = NULL; newtable->parent = parent; @@ -116,13 +116,13 @@ STable *createTable(SCOPE_TYPE type, STable *parent, int level, int order, int i } */ - int selectSize = type == SIMPLE_HASH || type == SMV_PORTS ? MAX_SIMPLE : MAX_TABLE; - newtable->usedSize = selectSize; + + /* if(type == SIMPLE_HASH) { - printf("[createTable] criando simple hash \n\n"); + printf("[createTable] criando simple calculateHashPos \n\n"); } else { @@ -130,12 +130,12 @@ STable *createTable(SCOPE_TYPE type, STable *parent, int level, int order, int i } */ - newtable->tableData = (TableEntry**) malloc(selectSize*sizeof(TableEntry*)); + newtable->tableData = (TableEntry**) malloc(MAX_TABLE*sizeof(TableEntry*)); // garantia (tudo bem que eu NÃO VOU PRECISAR PERCORRER A TABELA DE SIMBOLOS, mas ele ta quebrando no print (por existir "qualquer coisa na tabela")) int i; - for (i = 0; i < selectSize; i++) + for (i = 0; i < MAX_TABLE; i++) { newtable->tableData[i] = NULL; } @@ -178,7 +178,7 @@ void printTable(STable* t){ } void letGoEntryByName(STable* table, char* name){ - int index = hash(name,table); + int index = calculateHashPos(name, table); letgoEntry(table->tableData[index]); table->tableData[index] = NULL; } @@ -193,9 +193,9 @@ void letgoEntry(TableEntry *e) { } if(e->val) { - if(e->val->type == TYPE_SET){ - letgoTable((STable *) e->val->values[2]); - } + //if(e->val->type == TYPE_SET){ + // letgoTable((STable *) e->val->values[2]); + //} letgoObject(e->val); } free(e); @@ -218,8 +218,8 @@ void letgoTable(STable *t) free(t->children); } if(t->tableData){ - int size = t->type == SIMPLE_HASH || t->type == SMV_PORTS? MAX_SIMPLE : MAX_TABLE; - for(i=0; i < size; i++) + //int size = t->type == SIMPLE_HASH || t->type == SMV_PORTS? MAX_SIMPLE : MAX_TABLE; + for(i=0; i < MAX_TABLE; i++) { if(t->tableData[i]) { letgoEntry(t->tableData[i]); @@ -238,22 +238,15 @@ void letgoTable(STable *t) -int hash(char * str, STable* t) { - int hash = 401; - int c; - int SIZE_FOR_HASH = t->collision ? t->collision : t->usedSize; - - if(t->collision) - { - printf("[hash] collision : (%d) \n",SIZE_FOR_HASH); - } - while (*str != '\0') { - hash = ((hash << 4) + (int)(*str)) % SIZE_FOR_HASH; - str++; - } +int calculateHashPos(char * str, STable* t) { - return hash % SIZE_FOR_HASH; + int SIZE_FOR_HASH = t && t->collision ? t->collision : MAX_TABLE; + if(t && t->collision) + { + printf("[calculateHashPos] collision : (%d) \n",SIZE_FOR_HASH); + } + return hash(str,SIZE_FOR_HASH); } @@ -279,7 +272,7 @@ void redistributeHashs(STable* t, TableEntry* e) { if(t->tableData[i]) { - int index = hash(t->tableData[i]->name,t); + int index = calculateHashPos(t->tableData[i]->name, t); printf("[redistributeHashs] new index (%s) %d \n",t->tableData[i]->name,index); newTableData[index] = t->tableData[i]; } @@ -298,8 +291,8 @@ void redistributeHashs(STable* t, TableEntry* e) void insert(STable* t, TableEntry* e) { - int index = hash(e->name,t); - printf("[insert] HASH CALCULADO para (%s) É: %d \n",e->name,index); + int index = calculateHashPos(e->name, t); + //printf("[insert] HASH CALCULADO para (%s) É: %d \n",e->name,index); if(lookup(t,e->name)) { @@ -319,15 +312,15 @@ void insert(STable* t, TableEntry* e) { TableEntry* lookup(STable* t, char* name) { - int index = hash(name,t); + int index = calculateHashPos(name, t); TableEntry* e = t->tableData[index]; if(e) { return e; } // não achou procura na hierarquia de escopos acima - printf("[lookup] WARNING %s not in scope : ",name); - printf("%s (%d,%d) \n",mappingEnumTable[t->type],t->level,t->order); + //printf("[lookup] WARNING %s not in scope : ",name); + //printf("%s (%d,%d) \n",mappingEnumTable[t->type],t->level,t->order); STable* parent = t->parent; while(!e && parent) { @@ -340,82 +333,9 @@ TableEntry* lookup(STable* t, char* name) { } -int checkTypeSet(STable* current, char* name, char* typeid) -{ - // procura a variável em questão na tabela do SMV - TableEntry* entry = lookup(current,name); - if(entry) - { - // procura o tipo - if(lookup(entry->val->values[2],typeid)) - { - printf("[checkTypeSet] %s encontrado no conjunto da variável %s \n",typeid,name); - return 0; - } - printf("[checkTypeSet] %s não existe no conjunto da variável %s \n",typeid,name); - // poderiamos chamar o método add aqui né ? (problemas: efeitos colaterais demais de uma só vez (atrapalha debug, lembre-se do print haha)) - return 1; - } -} - - -/* - Adiciona um tipo para o "conjunto de tipos das variáveis" - para otimizar a escrita no arquivo SMV. - -*/ -void addEntryToTypeSet(STable* current, char* name, char* typeid) -{ - TableEntry* entry = lookup(current,name); - if(entry) - { - int present = 1; - void* po = {&present}; - addValue(typeid, po, LOGICAL_ENTRY, 1, 0, entry->val->values[2], 0); - } -} - - - -// método especializado para adicionar valores que sejam SMV_POINTERS (indice no Header, tamanho da palavra, conjunto de tipos(hashmap ou outro objeto)) -/* - - Objeto: vetor dinamico[inteirosDoConjunto], nullable, vetor dinamico[labelsDoConjunto] - - Prós: Menos structs para alocar,não tem que alocar uma TABELA INTEIRA só para alguns valores, - a linguagem possui poucos tipos (atualmente: int, label, boolean(FALSE E TRUE são só enums no nuXmv), - e tds (que na verdade retorna qualquer um dos tipos anteriores)) - - Cons: Outro objeto (mais coisas para dar free), - "quebaria" o conceito de hashmap que é justamente não ter duplicata, ia ser um objeto só para checar algumas coisas - Toda vez que adicionar um tipo novo necessita alterar essa estrutura - - Hashmap: estrutura que já temos atualmente, teria pelo menos umas 5 entras (talvez mais ou menos) - - Pŕos: Não necessita criar mais nada, não precisa alocar vetores (indexa pela string em qualquer caso), - aberto para novos tipos (indexa pela string) - - Cons: Vai ficar uma estrutura "recursiva" tabela --x entradas--> entradaSmv(porta ou main) --> Objeto(iHeader,size, - tabela ---y entradas--->entradas --> Objeto(bool)) - Mais coisas para centralizar e dar free - - -*/ -void addTypeSetSmv(char *name, void **any, int object_size, STable *current) -{ - printf("[addTypeSetSmv] add var-name: %s to %s \n",name,mappingEnumTable[current->type]); - STable* hashset = createTable(SIMPLE_HASH, NULL, 0, 0, -1); - - void* po[] = {any[0], any[1], hashset}; - - printf("[addTypeSetSmv] (index: %d, size: %d) \n",*(int*)po[0],*(int*)po[1]); - - addValue(name, po, TYPE_SET, object_size + 1, 0, current, 0); -} - void addNumericalIntervalSmv(char* name, int pos, int tam, int pointIni, int pointEnd, int min , int max, int newValue, STable* current){ - printf("[addNumericalIntervalSmv] add var-name: %s to %s \n",name,mappingEnumTable[current->type]); + //printf("[addNumericalIntervalSmv] add var-name: %s to %s \n",name,mappingEnumTable[current->type]); max = newValue > max && newValue > min ? newValue : max; max = newValue < max && newValue < min ? newValue : min; @@ -438,37 +358,56 @@ void addWriteInfo(char* name, void** any, int any_type, int object_size, STable* } */ +void addSmvInfoDeclaration(char *name, void **any, int any_type, int object_size, STable *current, void* type_smv_info_dc){ + addValue(name,any,any_type,object_size,0,current,-1); + Object* VAR_DECLARATION_SMV_INFO = lookup(current,name)->val; + void* copy_type_smv_info_dc = NULL; + if(any_type == WRITE_SMV_INFO){ + copy_type_smv_info_dc = copyTypeMinMax(type_smv_info_dc); + } + else{ + copy_type_smv_info_dc = copyTypeSet(type_smv_info_dc); + } + VAR_DECLARATION_SMV_INFO->type_smv_info = copy_type_smv_info_dc; +} + // refatorar? os dois métodos, usar só um que recebe "qualquer coisa" e encapsula em um objeto void addValue(char *name, void **any, int any_type, int object_size, int methodParam, STable *current, int timeContext) { - // note que po é um ponteiro para objetos que o novo objeto irá encapsular, como criar ? - - // POR ENQUANTO: - + // note que po é um ponteiro para objetos que o novo objeto irá encapsular, como criar ? //void* pa[] = {&vali}; (pro :possibilita manipular arrays) (cons: tenho que tratar tudo como vetor até quando é um unico valor) - Object* o = createObject(any_type, object_size, any, timeContext, name); + Object* o = createObject(any_type, object_size, any, timeContext, name, NULL); addValueCurrentScope(name,o,methodParam,current); } void updateValue(char *name, void **any, int any_type, int object_size, int oIndex, int oProp, STable *current, int contextChange) { - TableEntry* e = lookup(current,name); if(e){ - printf("[updateValue] newValue %d \n",*(int*)any[0]); + //printf("[updateValue] newValue %d \n",*(int*)any[0]); updateObject(e->val, any, any_type, object_size, oIndex, oProp, contextChange); } else{ - // valor novo - addValue(name, any, any_type, object_size, 0, current, 0); + if(oIndex > 0){ + fprintf(stderr, "ASSIGN ERROR: %s is not defined for reference %s[%d] \n", name,name,oIndex); + exit(-1); + } + addValue(name, any, any_type, object_size, 0, current, 0); } } +void addReferenceCurrentScope(char* name, Object* DATA_STRUCT, int methodParam, STable* current){ + if(lookup(current,name)){ + fprintf(stderr,"%s already declared!\n",name); + exit(-1); + } + addValueCurrentScope(name,DATA_STRUCT,methodParam,current); +} void addValueCurrentScope(char* name, Object* val, int methodParam,STable* current) { @@ -497,7 +436,7 @@ STable* addSubScope(STable* parent, SCOPE_TYPE type) { STable* child = createTable(type, parent, parent->level + 1, parent->nchild, -1); - printf("[addSubScope] alocando filho: %d \n",parent->nchild); + //printf("[addSubScope] alocando filho: %d \n",parent->nchild); if(!parent->nchild) { parent->children = (STable**) malloc((parent->nchild+1)*sizeof(STable*)); @@ -506,7 +445,7 @@ STable* addSubScope(STable* parent, SCOPE_TYPE type) { { if(!parent->backup) { - printf("[addSubScope] realocando filhos: %d \n",parent->nchild); + //printf("[addSubScope] realocando filhos: %d \n",parent->nchild); STable** newbuffer = realloc(parent->children, (parent->nchild+1)*sizeof(STable*)); if(newbuffer == NULL) diff --git a/src/LEXEROUTPUT b/src/flex-bison/LEXEROUTPUT similarity index 100% rename from src/LEXEROUTPUT rename to src/flex-bison/LEXEROUTPUT diff --git a/src/PARSINGOUTPUT b/src/flex-bison/PARSINGOUTPUT similarity index 100% rename from src/PARSINGOUTPUT rename to src/flex-bison/PARSINGOUTPUT diff --git a/src/backupdebug.y b/src/flex-bison/backupdebug.y similarity index 100% rename from src/backupdebug.y rename to src/flex-bison/backupdebug.y diff --git a/src/tdsrpl.l b/src/flex-bison/tdsrpl.l similarity index 79% rename from src/tdsrpl.l rename to src/flex-bison/tdsrpl.l index 954a6a3..cff4251 100644 --- a/src/tdsrpl.l +++ b/src/flex-bison/tdsrpl.l @@ -1,7 +1,7 @@ %{ #include - #include - #include "../headers/Node.h" + #include + #include "../../headers/Node.h" #include "tdsrpl.tab.h" @@ -50,12 +50,13 @@ and {yylval.sval = strdup(yytext); return AND;} or {yylval.sval = strdup(yytext); return OR;} not {yylval.sval = strdup(yytext); return NOT;} -\|\|> {yylval.sval = strdup(yytext); return DPASS;} --> {yylval.sval = strdup(yytext); return PASS;} -xor {yylval.sval = strdup(yytext); return XOR;} -[<=] {yylval.sval = strdup(yytext); return LE;} -[>=] {yylval.sval = strdup(yytext); return GE;} -[<] {yylval.sval = strdup(yytext); return LT;} -[>] {yylval.sval = strdup(yytext); return GT;} +\<-\> {yylval.sval = strdup(yytext); return BIMP;} +-> {yylval.sval = strdup(yytext); return IMP;} +==> {yylval.sval = strdup(yytext); return PASS;} +"<=" {yylval.sval = strdup(yytext); return LE;} +">=" {yylval.sval = strdup(yytext); return GE;} +"<" {yylval.sval = strdup(yytext); return LT;} +">" {yylval.sval = strdup(yytext); return GT;} [+] {yylval.sval = strdup(yytext); return PLUS;} [-] {yylval.sval = strdup(yytext); return MINUS;} [*] {yylval.sval = strdup(yytext); return TIMES;} @@ -66,18 +67,22 @@ INTERVAL {yylval.sval = strdup(yytext); return INTERVAL;} I_TIME {yylval.sval = strdup(yytext); return INITTIME;} C_TIME {yylval.sval = strdup(yytext); return CURRENTTIME;} F_TIME {yylval.sval = strdup(yytext); return FINALTIME;} -'[A-Za-z_]*' {yylval.sval = strdup(yytext); return LABEL;} +TO {yylval.sval = strdup(yytext); return TO;} +' {yylval.sval = strdup(yytext); return PLICK;} linked {yylval.sval = strdup(yytext); return LINKED;} data-time {yylval.sval = strdup(yytext); return DATATIME;} delayed {yylval.sval = strdup(yytext); return DELAYED;} +filter {yylval.sval = strdup(yytext); return FILTER;} portname {yylval.sval = strdup(yytext); return PORTNAME;} +value {yylval.sval = strdup(yytext); return TDSVALUE;} [A-Za-z_]* {yylval.sval = strdup(yytext); return ID;} %% void yyerror(const char *s) { - printf("Erro de parsing! %s, perto da linha %d \n",s,yylineno); + printf("\n"); + printf("PARSING ERROR %s near line %d \n",s,yylineno); exit(-1); } diff --git a/src/tdsrpl.y b/src/flex-bison/tdsrpl.y similarity index 74% rename from src/tdsrpl.y rename to src/flex-bison/tdsrpl.y index 5da594f..bced854 100644 --- a/src/tdsrpl.y +++ b/src/flex-bison/tdsrpl.y @@ -7,7 +7,7 @@ #include #include #include - #include "../headers/Node.h" + #include "../../headers/Node.h" int yylex(void); int yyparse(); @@ -68,7 +68,8 @@ %token NOT %token ELSE %token Null -%token XOR +%token IMP +%token BIMP %token LE %token GE %token LT @@ -80,7 +81,7 @@ %token MOD %token FUNCTIONDOMAIN %token FUNCTION -%token LABEL +%token PLICK %token DATATIME %token DELAYED %token PORTNAME @@ -93,17 +94,21 @@ %token DPASS %token INTERVAL %token BETWEEN +%token TDSVALUE +%token FILTER %type prog %type cmds %type cmd %type functiondefs %type functiondef +%type param %type params %type data %type otherstmt %type assignable %type expr +%type subexp %type multiexp %type ineqexp %type logical @@ -114,7 +119,7 @@ %type matchornot %type extraaccesses %type extras -%type delayedoption +%type passoption %type dataflow %type tdsprop %type domain @@ -257,16 +262,16 @@ functiondef: FUNCTION ID LPAREN params RPAREN LBRACE cmds RBRACE { ; +param: ID { + Node* params = createNode(5,0,1,"VARIAVEL", IDVAR, $1); + $$ = params; +} -params: ID { - - Node* params = createNode(5,0,1,"parametro da definição de função", PARAM, $1); - $$ = params; - +params: param { + $$ = $1; } - | params COMMA ID { - - Node* params = createNode(7,1,2,"Paramslist - lista de parâmetros a mais de uma função ", PARAMS , $1, $2,$3); + | params COMMA param { + Node* params = createNode(7,2,1,"Paramslist - lista de parâmetros a mais de uma função ", LIST_ITERATOR , $1,$3, $2); $$ = params; } @@ -295,7 +300,15 @@ cmd: IF LPAREN expr RPAREN LBRACE cmds RBRACE matchornot { // jogar para nó mais abaixo a operação para avaliar antes de toda a expressão! | LPAREN params RPAREN anonimtdsop ID { - + if($2->type != IDVAR && ($4->type == TDS_ANON_OP_DPASS || $4->type == TDS_ANON_OP_FPASS) ){ + if($4->type == TDS_ANON_OP_DPASS){ + fprintf(stderr, "\n[PARSING ERROR] DELAYED-FIFO option for %s not valid for multiples inputs! \n",$5); + } + else{ + fprintf(stderr, "\n[PARSING ERROR] FILTER option for %s not valid for multiples inputs! \n",$5); + } + exit(-1); + } Node* cmd = createNode(9,2,3,"CMD - Comando (criação TDS-anonima)", CMD_TDS_ANON ,$2,$4, $1,$3,$5); //infoNode($$); //printf("(%s) (%s) (filhos: %d) \n \n",cmd->name,cmd->children[0]->name,cmd->nchild); @@ -312,7 +325,10 @@ anonimtdsop: PASS { Node* p = createNode(5,0,1,"CMD - DPASS", TDS_ANON_OP_DPASS ,$1); $$ = p; } - + | MINUS LBRACE expr RBRACE GT { + Node* p = createNode(9,1,4, "CMD - FPASS", TDS_ANON_OP_FPASS, $3, $1, $2, $4, $5); + $$ = p; + } paramsCall: expr { @@ -364,7 +380,7 @@ otherstmt: FOR ID IN expr LBRACE cmds RBRACE { //infoNode($$); } - | assignable ASSIGN expr { + | assignable ASSIGN variabledata { Node* assignment = createNode(7,2,1,"Assignment", OTHER_ASSIGN ,$1,$3, $2); $$ = assignment; @@ -373,10 +389,14 @@ otherstmt: FOR ID IN expr LBRACE cmds RBRACE { //infoNode($$); } - | RETURN expr { + | RETURN variabledata { Node* optionalreturn = createNode(6,1,1,"Optionalreturn - retorno opcional ", OPT_RETURN, $2, $1); $$ = optionalreturn; } + | CURRENTTIME TO expr { + Node* data = createNode(7,1,2,"CHANGE-CURRENTTIME-DIRECTIVE", ASSIGN_TDIRECTIVE , $3 ,$1,$2); + $$ = data; + } ; @@ -395,61 +415,50 @@ assignable : ID extraaccesses { $$ = assignment; } } - | CURRENTTIME { - - Node* data = createNode(5,0,1,"CHANGE-CURRENTTIME-DIRECTIVE", ASSIGN_TDIRECTIVE ,$1); - $$ = data; - - } - ; - - - -expr: MINUS expr { - - Node* expr = createNode(6,1,1,"Expressão Básica - negativo", EXPR, $2, $1); - $$ = expr; - - - } - | expr MINUS multiexp { - - Node* expr = createNode(7,2,1,"Expressão Básica - subtração ", EXPR ,$1,$3, $2); - $$ = expr; + ; - } - | expr PLUS multiexp { - Node* expr = createNode(7,2,1,"Expressão Básica - soma ", EXPR ,$1,$3, $2); - $$ = expr; - +expr: expr PLUS subexp { + Node* expr = createNode(7,2,1,"Expressão Básica - soma ", PLUS_EXPR ,$1,$3, $2); + $$ = expr; } - | multiexp { + | subexp { Node* expr = createNode(5,1,0,"Expressão Básica - Nível 2", EXPR ,$1); $$ = expr; } ; +subexp: subexp MINUS multiexp { + + Node* expr = createNode(7,2,1,"Expressão Básica - subtração ", MINUS_EXPR ,$1,$3, $2); + $$ = expr; + + } + | multiexp { + + Node* expr = createNode(5,1,0,"Expressão Básica - Nível 2", EXPR ,$1); + $$ = expr; + } multiexp: multiexp TIMES ineqexp { - Node* multiexp = createNode(7,2,1,"Expressão Básica - Multiplicação", EXPR ,$1,$3, $2); + Node* multiexp = createNode(7,2,1,"Expressão Básica - Multiplicação", MULTI_EXPR ,$1,$3, $2); $$ = multiexp; } |multiexp DIVIDE ineqexp { - Node* multiexp = createNode(7,2,1,"Expressão Básica - Divisão ", EXPR, $1,$3, $2); + Node* multiexp = createNode(7,2,1,"Expressão Básica - Divisão ", DIV_EXPR, $1,$3, $2); $$ = multiexp; } |multiexp MOD ineqexp { - Node* multiexp = createNode(7,2,1,"Expressão Básica - MOD ", EXPR ,$1,$3, $2); + Node* multiexp = createNode(7,2,1,"Expressão Básica - MOD ", DIV_EXPR ,$1,$3, $2); $$ = multiexp; } @@ -461,43 +470,30 @@ multiexp: multiexp TIMES ineqexp { ; ineqexp: ineqexp LE logical { - - - Node* ineqexp = createNode(7,2,1,"Inequação - Menor igual a ", EXPR, $1,$3, $2); - $$ = ineqexp; - - + Node* ineqexp = createNode(7,2,1,"Inequação - Menor igual a ", LE_EXPR, $1,$3, $2); + $$ = ineqexp; } | ineqexp GE logical { - - Node* ineqexp = createNode(7,2,1,"Inequação - Maior igual a ", EXPR ,$1,$3, $2); - $$ = ineqexp; - + Node* ineqexp = createNode(7,2,1,"Inequação - Maior igual a ", GE_EXPR ,$1,$3, $2); + $$ = ineqexp; } | ineqexp LT logical { - - Node* ineqexp = createNode(7,2,1,"Inequação - Menor que ", EXPR ,$1,$3, $2); + Node* ineqexp = createNode(7,2,1,"Inequação - Menor que ", LT_EXPR ,$1,$3, $2); $$ = ineqexp; - } | ineqexp GT logical { - - Node* ineqexp = createNode(7,2,1,"Inequação - Maior que ", EXPR, $1,$3, $2); - $$ = ineqexp; - - + Node* ineqexp = createNode(7,2,1,"Inequação - Maior que ", GT_EXPR, $1,$3, $2); + $$ = ineqexp; } | ineqexp EQUAL logical { - Node* ineqexp = createNode(7,2,1,"Inequação - Igual a ", EXPR ,$1,$3, $2); - $$ = ineqexp; - + Node* ineqexp = createNode(7,2,1,"Inequação - Igual a ", EQUAL_EXPR ,$1,$3, $2); + $$ = ineqexp; } | ineqexp NOTEQUAL logical { - Node* ineqexp = createNode(7,2,1,"Inequação - Diferente de ", EXPR ,$1,$3, $2); - $$ = ineqexp; - + Node* ineqexp = createNode(7,2,1,"Inequação - Diferente de ", NEQUAL_EXPR ,$1,$3, $2); + $$ = ineqexp; } | logical { Node* expr = createNode(5,1,0,"Expressão Básica - Nível 4", EXPR ,$1); @@ -506,32 +502,29 @@ ineqexp: ineqexp LE logical { ; -logical: NOT data { - - Node* logical = createNode(6,1,1,"Lógico - Negação ", EXPR ,$2, $1); - $$ = logical; - - } +logical: MINUS data { + Node* expr = createNode(6,1,1,"Expressão Básica - negativo", MINUS_EXPR, $2, $1); + $$ = expr; + } | logical AND data { - - Node* logical = createNode(7,2,1,"Lógico - AND ", EXPR ,$1,$3, $2); - $$ = logical; - + Node* logical = createNode(7,2,1,"Lógico - AND ", AND_EXPR ,$1,$3, $2); + $$ = logical; } | logical OR data { - - Node* logical = createNode(7,2,1,"Lógico - OR ", EXPR ,$1,$3, $2); - $$ = logical; - + Node* logical = createNode(7,2,1,"Lógico - OR ", OR_EXPR ,$1,$3, $2); + $$ = logical; + } + | logical IMP data { + Node* logical = createNode(7,2,1,"Lógico - OR ", IMP_EXPR ,$1,$3, $2); + $$ = logical; + } + | logical BIMP data { + Node* logical = createNode(7,2,1,"Lógico - OR ", BIMP_EXPR ,$1,$3, $2); + $$ = logical; } - | LPAREN expr RPAREN { - Node* expr = createNode(5,1,0,"Expressão Básica - encapsulada", EXPR ,$1); - $$ = expr; - } | data { - - $$ = $1; - + Node* expr = createNode(5,1,0,"Expressão Básica - Nível 5", EXPR ,$1); + $$ = expr; } ; @@ -541,6 +534,10 @@ data: RAWNUMBERDATA { $$ = data; } + | NOT data { + Node* logical = createNode(6,1,1,"Lógico - Negação ", NOT_EXPR ,$2, $1); + $$ = logical; + } | BOOLEAN { Node* data = createNode(5,0,1,"Booleano", L_BOOL ,$1); @@ -577,18 +574,36 @@ data: RAWNUMBERDATA { } - | LABEL { - - Node* data = createNode(5,0,1,"LABEL", STRING ,$1); + | PLICK ID PLICK { + Node* data = createNode(5,0,1,"LABEL", STRING ,$2); $$ = data; } - | variabledata { + | functioncall { $$ = $1; } + | ID extraaccesses { + + if($2){ + Node* assignment = createNode(6,1,1,"Acesso a variavel", AC_V, $2, $1); + $$ = assignment; + + //printf("(!!)atribuicao (%s) \n \n",assignment->leafs[0]); + //infoNode($$); + } + else { + Node* assignment = createNode(5,0,1,"VARIAVEL", IDVAR, $1); + $$ = assignment; + + } + } + | LPAREN expr RPAREN { + Node* expr = createNode(7,1,2,"Expressão Básica - encapsulada", PRI_EXPR, $2, $1, $3); + $$ = expr; + } ; @@ -649,9 +664,9 @@ tdsprop: functioncall { $$ = prop; } - | DATATIME { + | TDSVALUE { - Node* prop = createNode(5,0,1,"Props TDS - datatime", V_PROP_TDS , $1); + Node* prop = createNode(5,0,1,"Props TDS - value", V_PROP_TDS_VALUE , $1); $$ = prop; } @@ -670,49 +685,27 @@ tdsprop: functioncall { -variabledata: LBRACE PORTNAME COLON LABEL COMMA DATATIME COLON LBRACE dataflow RBRACE extras RBRACE { +variabledata: LBRACE PORTNAME COLON PLICK ID PLICK COMMA DATATIME COLON LBRACE dataflow RBRACE RBRACE { - Node* tdsformat = createNode(16,2,10,"Informações de TDS", TDS_DEF_COMPLETE , $9,$11, $1,$2,$3,$4,$5,$6,$7,$8,$10,$12); + Node* tdsformat = createNode(15,1,10,"Informações de TDS", TDS_DEF_COMPLETE , $11, $1,$2,$3,$5,$7,$8,$9,$10,$12,$13); $$ = tdsformat; } - | LBRACE PORTNAME COLON LABEL extras RBRACE { + | LBRACE PORTNAME COLON PLICK ID PLICK extras RBRACE { - Node* tdsformat = createNode(10,1,5,"Informações de TDS - LINKED", TD_DEF_DEPEN ,$5, $1,$2,$3,$4,$6); + Node* tdsformat = createNode(10,1,5,"Informações de TDS - LINKED", TDS_DEF_DEPEN ,$7, $1,$2,$3,$5,$8); $$ = tdsformat; } - - | ID extraaccesses { - - if($2){ - Node* assignment = createNode(6,1,1,"Acesso a variavel", AC_V, $2, $1); - $$ = assignment; - - //printf("(!!)atribuicao (%s) \n \n",assignment->leafs[0]); - //infoNode($$); - } - else { - Node* assignment = createNode(5,0,1,"VARIAVEL", IDVAR, $1); - $$ = assignment; - - } - } - // VETOR | LBRACE paramsCall RBRACE { Node* data = createNode(7,1,2,"VETOR", DATA_V ,$2, $1,$3); $$ = data; } - - // causa possível da redundancia? (podemos separar em procedure call e function call?) - | functioncall { - - Node* variabledata = createNode(5,1,0,"Dados de chamada de função", FUNC_CALL, $1); - $$ = variabledata; - - } + | expr { + $$ = $1; + } ; @@ -759,13 +752,13 @@ timecomponent: RAWNUMBERDATA COLON expr { timelist: timecomponent { - //Node* timelist = createNode(5,1,0,"TIME-LIST-TDS-one", TIME_LIST ,$1); + //Node* timelist = createNode(5,1,0,"TIME-LIST-TDS-one", LIST_ITERATOR ,$1); $$ = $1; } |timelist COMMA timecomponent { - Node* timelist = createNode(7,2,1,"TIME-LIST-TDS-loop", TIME_LIST ,$1,$3, $2 ); + Node* timelist = createNode(7,2,1,"TIME-LIST-TDS-loop", LIST_ITERATOR, $1,$3, $2 ); $$ = timelist; } @@ -773,29 +766,44 @@ timelist: timecomponent { -extras: COMMA LINKED COLON LBRACE params RBRACE delayedoption { +extras: COMMA LINKED COLON LBRACE params RBRACE passoption { Node* extra; if($7){ - extra = createNode(11,2,5,"LINKED-EXTRA-ARGS-TDS" , DEF_EXTRAS_LINKED ,$5,$7, $1,$2,$3,$4,$6); + // NOVA VALIDAÇÃO DE PARSING: + Node* synth_params = $5; + if(synth_params->nchild > 1){ + if($7->type == DEF_EXTRAS_DELAYED){ + fprintf(stderr, "\n[PARSING ERROR] DELAYED-FIFO option not valid for multiples inputs! \n"); + } + else{ + fprintf(stderr, "\n[PARSING ERROR] FILTER option not valid for multiples inputs! \n"); + } + exit(-1); + } + extra = createNode(11,2,5,"LINKED-EXTRA-ARGS-TDS" , DEF_EXTRAS_LINKED ,$5, $7, $1,$2,$3,$4,$6); } else { extra = createNode(10,1,5,"LINKED-EXTRA-ARGS-TDS" , DEF_EXTRAS_LINKED , $5, $1,$2,$3,$4,$6); } $$ = extra; } - | delayedoption { + | passoption { //Node* extra = createNode(4,1,0,"DELAYED-EXTRA-ARGS-TDS",$1); $$ = $1; } -delayedoption: COMMA DELAYED COLON BOOLEAN { +passoption: COMMA DELAYED { - Node* extra = createNode(8,0,4,"DELAYED-EXTRA-ARGS-TDS", DEF_EXTRAS_DELAYED ,$1,$2,$3,$4); + Node* extra = createNode(6,0,2,"DELAYED-EXTRA-ARGS-TDS", DEF_EXTRAS_DELAYED , $1,$2); $$ = extra; } + | COMMA FILTER COLON expr { + Node* extra = createNode(8,1,3,"FILTER-EXTRA-ARGS-TDS", DEF_EXTRAS_FILTER, $4, $1,$2,$3); + $$ = extra; + } | /* empty */ { $$ = NULL;} ; diff --git a/src/langmodules/LangCore.c b/src/langmodules/LangCore.c new file mode 100644 index 0000000..c1cb0a2 --- /dev/null +++ b/src/langmodules/LangCore.c @@ -0,0 +1,310 @@ +// +// Created by mateus on 20/04/2021. +// +#include +#include +#include +#include "../../headers/LangCore.h" + + +/* + * Funções Auxiliares Internas da linguagem + */ + +STable* selectSMV_SCOPE(STable* scope, EnvController* controllerSmv){ + if(scope->type == FUNC || scope->childOfFunction){ + return accessSmvInfo(controllerSmv,FUNCTION_SMV,scope->indexRef); +// return controllerSmv->functionsInfo[scope->indexRef]; + } + else{ + return controllerSmv->mainInfo; // só vai retornar ports em casos de declarações de tds + } +} + +HeaderSmv * selectSMV_INFO(STable* scope, Object* functionPointer, EnvController* controllerSmv){ + if(!functionPointer){ + return controllerSmv->MAIN; + } + else{ +// objeto função (parametros vão ser adicionados a STABLE, e vamos ter o número esperado de parâmetros) + // (vamos ter o index de referência do controller (header) e também o smvinfo + int ALL_FUNCTION = *(int*) functionPointer->values[3]; +// int TDS_FUNCTION = *(int*) functionPointer->values[4]; + if(ALL_FUNCTION){ + return accessHeader(controllerSmv,MAIN,ALL_FUNCTION); + } +// if(TDS_FUNCTION){ +// return accessHeader(controllerSmv,PORTS,TDS_FUNCTION); +// } + fprintf(stderr, "FUNCTION SMV INFO NOT FOUND"); + exit(-1); + } +} + +// avaliar a importancia dos métodos acima, e se possível movimentar eles para o HeaderSmv.c ou para um Novo Controller.h + + +void checkTdsEvalReview(EnvController* controller){ + if(controller->interactiveMode){ + char awns[50]; + printf("\n\n"); + printf("Continue(y/n)?"); + scanf("%s", awns); + if((awns[0] == 'n' || awns[0] == 'N') && awns[1] == '\0'){ + printf("Interpretation interrupted by user.\n"); + exit(0); + } + if(awns[0] == 'S' && !strcmp(awns,"SKIP")){ + printf("Skipped next interactions.\n"); + controller->interactiveMode = 0; + } + printf("\n\n\n"); + printf("---------------------------------------------------------\n\n\n"); + } +} + +void resolveDependencies(TDS* currentTDS, STable* scope, EnvController* controllerSmv, int I_TIME, int C_TIME){ + + Object* resolvedCondFilter = NULL; + if(currentTDS->limitCondition){ + controllerSmv->filterContext = 1; + controllerSmv->currentTDScontext = NULL; + resolvedCondFilter = eval(currentTDS->limitCondition,scope,controllerSmv); + if(C_TIME > I_TIME){ + updateAllAutomataFilter(resolvedCondFilter,controllerSmv); + } + updateLimitCondition(currentTDS, resolvedCondFilter); + addDataToTds(currentTDS,C_TIME,currentTDS->linkedDependency[0]->DATA_TIME[C_TIME]); + } + else{ + if(currentTDS->delayed){ + resolveDelayedTdsDependencies(currentTDS,C_TIME); + } + else{ + resolveMergerTdsDependencies(currentTDS, C_TIME); + } + } + int i; + // sempre deve resolver as dependencias de uma TDS já que a embora a dependente possa não ter recebido valores diretamente esse instante + // o "tipo" do type-set da outra pode ter mudado (nuXmv é bem rigido a respeito disso) + for (i = 0; i < currentTDS->TOTAL_DEPENDENCIES_PT; i++) { + propagateValueToTypeSet(currentTDS, currentTDS->linkedDependency[i],controllerSmv); + } + if(currentTDS->limitCondition){ + specTDS(currentTDS,NULL,C_TIME,I_TIME,controllerSmv,scope); + letgoObject(resolvedCondFilter); + controllerSmv->filterContext = 0; + } +} + +void resolveLazyTdsSpec(STable *currentScope, EnvController *controllerSmv, int C_TIME, int I_TIME, Node *PROGRAM_PATH, TDS *currentTDS) { + + Object* lazyValue = eval(PROGRAM_PATH, currentScope, controllerSmv); + if(lazyValue->aList || lazyValue->type == LOGICAL_ENTRY){ + fprintf(stderr, "TDS VALIDATION ERROR: INCOMPATIBLE SPECIFICATION FOR TDS %s. DATA STRUCTURES ARE NOT ACCEPTED AS VALUES, ONLY SYMBOLIC VALUES.", currentTDS->name); + exit(-1); + } + specTDS(currentTDS,lazyValue,C_TIME,I_TIME,controllerSmv,currentScope); + addDataToTds(currentTDS,C_TIME,lazyValue); +} + +void resolveTimeComponentSpec(STable *currentScope, EnvController *controllerSmv, int C_TIME, int I_TIME, + TDS *currentTDS, Object *timeComponent) { + + resolveLazyTdsSpec(currentScope, controllerSmv, C_TIME, I_TIME, timeComponent->values[1], currentTDS); +} + +void resolveTdsLazyEvaluation(STable *currentScope, EnvController *controllerSmv, int C_TIME) { + int I_TIME = *(int*) lookup(currentScope, "I_TIME")->val->values[0]; + int i; + for (i = 0; i < controllerSmv->declaredPortsNumber; i++) { + // resolve call-by-need cada expressão ativa da TDS. + TDS* currentTDS = controllerSmv->declaredPorts[i]; + controllerSmv->currentTDScontext = currentTDS; + if(C_TIME >= currentTDS->I_INTERVAL){ + if(currentTDS->type == DATA_LIST){ + // eval de forma que ele deve saber qual componente temporal ele deve pegar + if(currentTDS->COMPONENT_TIMES[C_TIME] != -1){ + Object* tdsDataSpec = currentTDS->DATA_SPEC; + Object* timeComponent = (Object*) tdsDataSpec->values[currentTDS->COMPONENT_TIMES[C_TIME]]; + resolveTimeComponentSpec(currentScope,controllerSmv,C_TIME,I_TIME,currentTDS,timeComponent); + } + }else{ + // tds_dependentes já são resolvidas sempre (tds desse tipo deveria ser adicionada aos lazy?) + if(currentTDS->type != TDS_DEPEN){ + resolveLazyTdsSpec(currentScope, controllerSmv, C_TIME, I_TIME, currentTDS->DATA_SPEC, currentTDS); + } + else{ + // senão deve verificar a dependência dessa TDS para atribuir o DATA_TIME também e resolver seu type-set + resolveDependencies(currentTDS,currentScope,controllerSmv,I_TIME,C_TIME); + } + + } + } + if(controllerSmv->interactiveMode){ + prepareToPrintTDS(currentTDS,C_TIME); + printf("\n\n"); + } + else{ + resetLimitConditionEval(currentTDS); + } + if(currentTDS->limitCondition && controllerSmv->relationRef){ + controllerSmv->relationRef = 0; + } + } + checkTdsEvalReview(controllerSmv); + controllerSmv->currentTDScontext = NULL; +} + +// CASO FORA DE FLUXO 1: e se ele "pular", ex: commitar c_time = 2 (quando era 0 antes), ele pulou o 1! A gente deve ver a "diferença" +// CHAMAR ESSA FUNÇÃO DIFERENÇA VEZES. +// CASO FORA DE FLUXO 2: deve chamar isso também ao FIM DO PROGRAMA (para cada CHAMADA RESTANTE, ex: C_TIME terminou em 4, deve chamar até F_TIME (5, ... , F_TIME). +// DIFERENÇA VEZES DE NOVO! +void commitCurrentTime(STable* currentScope, EnvController* controllerSmv, int changedTo){ + // deve resolver a avaliação para cada TDS "n" vezes. Antes do proximo intervalo ou fim do programa. + int i; + int C_TIME = *(int*) lookup(currentScope,"C_TIME")->val->values[0]; + for (i = C_TIME; i < changedTo; i++) { + if(controllerSmv->interactiveMode){ + printf("--------------TDS EVALUATION (time = %d)------------------\n\n\n",i); + } + resolveTdsLazyEvaluation(currentScope, controllerSmv, i); + int next = i+1; + if(next != changedTo){ + void* vp[] = {&next}; + updateValue("C_TIME", vp, T_DIRECTIVE_ENTRY, 1, -1, -1, currentScope, 0); + } + } +} + + +Object * notObjectOperation(Object* o){ + if(o->aList || (o->type != LOGICAL_ENTRY)) + { + fprintf(stderr, "INCOMPATIBLE OPERAND %s FOR THE (not) OPERATION!",o->SINTH_BIND); + exit(-1); + } + int r; + r = !(*(int*) o->values[0]); + void* rp[] = {&r}; + char resultingBind[strlen(o->SINTH_BIND)+2]; + createExprBind(resultingBind, o, NULL, "!"); + letgoObject(o); + return createObject(LOGICAL_ENTRY, 1, rp, -1, resultingBind, NULL); +} + +int comparator(Object* o1, Object* o2, char* op){ + + if(!o1->aList && !o2->aList && o1->type == NUMBER_ENTRY && o2->type == NUMBER_ENTRY) + { + return (*(int*)o1->values[0]) == (*(int*)o2->values[0]); + } + if(!o1->aList && !o2->aList && o1->type == LABEL_ENTRY && o2->type == LABEL_ENTRY) + { + char* str1 = (char*) o1->values[0]; + char* str2 = (char*) o2->values[0]; + return strcmp(str1,str2); + } + fprintf(stderr, "INCOMPATIBLE OPERANDS %s and %s FOR THE (%s) OPERATION!",o1->SINTH_BIND,o2->SINTH_BIND,op); + exit(-1); +} + +_Bool IMP(_Bool a, _Bool b){ return !a || b; } + + +_Bool BIMP(_Bool a, _Bool b){ return (a && b) || (!a && !b); } + +void updateVariable(char* varName, Object *var, Object *expr, STable* scope, int index, int C_TIME) { + + int prevTimeContext = var->timeContext; + if(prevTimeContext == C_TIME){ + fprintf(stderr, "ASSIGN ERROR: redefinition of %s in same time interval \n", varName); + exit(-1); + } + /* + * Caso var não seja NULL (isto é "placeholder") + * Realiza operação normal, senão trata o null + */ + if(var->type == NULL_ENTRY){ + if(expr->type != NULL_ENTRY) { + updateNullRef(var,expr); + updateValue(varName, expr->values, expr->type, expr->OBJECT_SIZE, index, -1, scope, C_TIME); + } + // senao nao faz nada x = NULL , atribuir novamente a null não muda nada + } + else{ + // VALIDAÇÃO DE TIPOS + if(var->type != expr->type){ + fprintf(stderr, "ASSIGN ERROR: incompatible type for %s \n", varName); + exit(-1); + } + updateValue(varName, expr->values, expr->type, expr->OBJECT_SIZE, index, -1, scope, C_TIME); + } +} + +void computeTDSDependentOperations(Node*n, char* portName, STable* scope, TDS* newTDS, EnvController* controller, int I_TIME, int C_TIME){ + Object * dependenceList = eval(n->children[0],scope,controller); + Object * DEP_HEAD = dependenceList->OBJECT_SIZE > 1 ? dependenceList->values[0] : NULL; + if(DEP_HEAD && DEP_HEAD->type == TDS_ENTRY || dependenceList->type == TDS_ENTRY) { + if (dependenceList->OBJECT_SIZE > 2) { + fprintf(stderr, + "[WARNING] %s definition uses more than 2 inputs.\nIt is recommended to check the input model, for instance, reo2nuXmv only generates merge-like connections with at most 2 inputs\n", + portName); + exit(-1); // enquanto o modelo do daniel não é estendido para mais de 2 portas para o merger + } + if(( newTDS->delayed || dependenceList->OBJECT_SIZE > 1) && C_TIME > I_TIME){ + fprintf(stderr, "[WARNING] %s uses a temporal condition to initialization. It is recommended to review your specification.\nThis behaviour is usually acceptable in case the modeled port is lossy (eg: LossySync)\n", + portName); + } + + } + else{ + fprintf(stderr, "ERROR: BAD USE OF TDS DEFINITION, %s is not receiving input from another TDS! \n",portName); + exit(-1); + } + + if(dependenceList->OBJECT_SIZE > 1){ + int i; + for (i = 0; i < dependenceList->OBJECT_SIZE; i++) { + Object* ENCAPSULATED_DEPENDENCY = (Object*) dependenceList->values[i]; + TDS* DEPENDENCY = (TDS*) ENCAPSULATED_DEPENDENCY->values[0]; + if(DEPENDENCY){ + addTdsDependency(DEPENDENCY,newTDS); + } + } + } + else{ + addTdsDependency(dependenceList->values[0], newTDS); + } + controller->IO_RELATION = 1; +} + +Object *computeTDSBasicOperations(Node *pathForDepen, char *portName, TDS_TYPE type, Object *tdsSpec, int delayed, + STable *scope, Node *pathForCond, EnvController *controller) { + int C_TIME = *(int*) lookup(scope,"C_TIME")->val->values[0]; + int I_TIME = *(int*)lookup(scope,"I_TIME")->val->values[0]; + int F_TIME = *(int*) lookup(scope,"F_TIME")->val->values[0]; + + TDS* newTDS = createTDS(portName, type, tdsSpec, delayed, C_TIME, F_TIME, pathForCond); + if(newTDS->limitCondition){ + controller->filterUsed = 1; + } + if(type == TDS_DEPEN){ + computeTDSDependentOperations(pathForDepen,portName,scope,newTDS,controller,I_TIME,C_TIME); + } + + void* vp[] = {newTDS}; + char* TDS_BIND = createReferenceTDS(portName); + Object* encapsulatedTDS = createObjectDS(TDS_ENTRY,1,vp,C_TIME,TDS_BIND,0); + free(TDS_BIND); // pode parecer "irrelevante" mas é uma garantia, o createObject não cuida do free dos binds. Em especial por causa da cópia de variáveis. + preProcessTDS(encapsulatedTDS,controller,C_TIME,I_TIME,F_TIME); + return encapsulatedTDS; +} + +void validateOpsTdsValue(Object* o1, Object* o2){ + if(o1->fromTdsValue || ( o2 && o2->fromTdsValue)){ + fprintf(stderr, "ERROR: Non comparison operator used with tds.value expression.\nOnly == and != are supported with symbolic comparisons in nuXmv\nThe operation will be available in future language and model extensions\n"); + exit(-1); + } +} + diff --git a/src/langmodules/Object.c b/src/langmodules/Object.c index a056a9f..2effe35 100644 --- a/src/langmodules/Object.c +++ b/src/langmodules/Object.c @@ -6,10 +6,11 @@ const char* mappingEnumObjectType[] = { "NUMBER", "BOOLEAN", - "STRING", + "LABEL", "T_DIRECTIVE", "TDS", "null*", + "TIME_COMPONENT", "FUNCTION", "WRITE_SMV_INFO", "TYPE_SET", @@ -21,27 +22,31 @@ const char* mappingEnumObjectType[] = { // MANTER ESSA FUNÇÃO: E sempre criar objetos para valores sintetizados (caso seja necessário, dar free em valores intermediarios que não venham a ser usados... void* allocatePtObjects(int type, void* value, Object* newOb,int index) { - if(type == NUMBER_ENTRY || type == T_DIRECTIVE_ENTRY || type == LOGICAL_ENTRY || type == WRITE_SMV_INFO) + if(type == NUMBER_ENTRY || type == T_DIRECTIVE_ENTRY || type == LOGICAL_ENTRY || type == WRITE_SMV_INFO ) { int* pt = malloc(sizeof(int)); *pt = *(int*) value; - printf("[allocatePtObjects - numVariants] valor: %d \n",*(int*) pt); - printf("[allocatePtObjects - numVariants] success \n"); + //printf("[allocatePtObjects - numVariants] valor: %d \n",*(int*) pt); + //printf("[allocatePtObjects - numVariants] success \n"); return pt; } - // precisa alocar para strings ? (pode ser que já tenha sido alocado pelo parser) Necessita alocar: Pode gerar efeito colateral em alguns casos (string pode ser re-usada) if(type == LABEL_ENTRY || type == NULL_ENTRY) { char* deref = (char*) value; - newOb->STR[index] = strlen(value); - char* pt = malloc(sizeof(char)*newOb->STR[index]+1); + newOb->STR = strlen(value); + char* pt = malloc(sizeof(char)*newOb->STR+1); strcpy(pt, deref); - printf("[allocatePtObjects - labelVariants] valor: %s (%d)\n",pt,type); + //printf("[allocatePtObjects - labelVariants] valor: %s (%d)\n",pt,type); return pt; } - - + if(newOb->SINTH_BIND){ + fprintf(stderr, "FAIL IN ALLOCATE VALUES FOR %s ! \n",newOb->SINTH_BIND); + } + else{ + fprintf(stderr, "FAIL IN ALLOCATE VALUES FOR CURRENT OBJECT! \n"); + } + exit(-1); } @@ -52,84 +57,93 @@ void* allocateTypeSetObjects(int index, void* value) { int* pt = malloc(sizeof(int)); *pt = *(int*) value; - printf("[allocateTypeSetObjects] [i=%d] valor: %d \n",index,*(int*) pt); + // printf("[allocateTypeSetObjects] [i=%d] valor: %d \n",index,*(int*) pt); return pt; } - - printf("[allocateTypeSetObjects] [i=%d] Hashmap já alocada \n",index); + //printf("[allocateTypeSetObjects] [i=%d] Hashmap já alocada \n",index); return value; } +Object* setUpForNewObject(object_type type, int OBJECT_SIZE, int timeContext, char* BIND){ + Object* newOb = (Object*) malloc(sizeof(Object)); -Object *createObject(int type, int OBJECT_SIZE, void **values, int timeContext, char *BIND) -{ - - Object* newOb = (Object*) malloc(sizeof(Object)); - - newOb->type = type; - newOb->OBJECT_SIZE = OBJECT_SIZE; - newOb->redef = 0; - newOb->timeContext = timeContext; + newOb->type = type; + newOb->OBJECT_SIZE = OBJECT_SIZE; + newOb->redef = 0; + newOb->timeContext = timeContext; if(BIND){ newOb->SINTH_BIND = malloc(sizeof(char)*strlen(BIND) + 1); strcpy(newOb->SINTH_BIND, BIND); } else{ -// newOb->ORIGINAL_BIND = NULL; newOb->SINTH_BIND = NULL; } + if(OBJECT_SIZE) { + // malloc para garantir que o objeto utilizado não "seja perdido" em chamadas + void **vo = (void **) malloc(sizeof(void *) * OBJECT_SIZE); + newOb->values = vo; + } + else{ + if(newOb->type != NULL_ENTRY){ + fprintf(stderr, "[createObject] Error during values allocation. Zero Sized object \n"); + exit(-1); + } + } + return newOb; +} + +Object *createObject(object_type type, int OBJECT_SIZE, void **values, int timeContext, char *BIND, void *TYPE_SMV_INFO) +{ + Object* newOb = setUpForNewObject(type,OBJECT_SIZE,timeContext,BIND); + newOb->type_smv_info = TYPE_SMV_INFO; + /* if(type == LABEL_ENTRY) - { - newOb->STR = malloc(sizeof(int)*OBJECT_SIZE); - } + { + newOb->STR = malloc(sizeof(int)*OBJECT_SIZE); + } else{ newOb->STR = NULL; } - - if(OBJECT_SIZE) - { - // malloc para garantir que o objeto utilizado não "seja perdido" em chamadas - void** vo = (void**) malloc(sizeof(void*)*OBJECT_SIZE); - int i; - for(i = 0; i< OBJECT_SIZE; i++) - { +*/ + newOb->aList = 0; + int i; + for(i = 0; i< OBJECT_SIZE; i++) + { //vo[i] = values[i]; - // caso do int e tipos mais basicos: ele chega aqui como um ponteiro para um variavel local (essa região de memoria é perdida depois!) // por ser um ponteiro para void que estamos guardando temos duas opções, alocar o ponteiro associado e passar para vo[i] // ou alocar antes e passar para esse já alocado! (acho melhor a primeira opção, para centralizar) - // casos como por exemplo do conjunto de tipos: não precisa de malloc (já é um ponteiro de um objeto alocado a muito tempo ) // -> tupla ponteiro smv (indiceHeader, tamanhoPalavra, Hashmap) - if(type == TYPE_SET) { - vo[i] = allocateTypeSetObjects(i,values[i]); + newOb->values[i] = allocateTypeSetObjects(i,values[i]); } else { - vo[i] = allocatePtObjects(type,values[i],newOb,i); + newOb->values[i] = allocatePtObjects(type,values[i],newOb,i); } - - } - newOb->values = vo; - } - - - int info = newOb == NULL ? 1 : 0; - - printf("[DEBUG - createObject] info: %d \n", info); - + } + //printf("[DEBUG - createObject] info: %d \n", info); //printObject(newOb); - - + newOb->fromTdsValue = 0; return newOb; - } +Object* createObjectDS(object_type type, int OBJECT_SIZE, void ** values, int timeContext, char *BIND, int aList) { + Object* newOb = setUpForNewObject(type,OBJECT_SIZE,timeContext,BIND); + newOb->aList = aList; + newOb->type_smv_info = NULL; + int i; + for (i = 0; i < OBJECT_SIZE; i++) { + newOb->values[i] = values[i]; + } + newOb->fromTdsValue = 0; + return newOb; +} void printObject(Object* o) { @@ -171,89 +185,173 @@ void printObject(Object* o) int derefboolean = *(int*) o->values[i]; if(derefboolean) { - printf(" (%s, %s) \n",mappingEnumObjectType[o->type],"true"); + printf(" (%s :: %s) \n",mappingEnumObjectType[o->type],"true"); } else { - printf(" (%s, %s) \n",mappingEnumObjectType[o->type],"false"); + printf(" (%s :: %s) \n",mappingEnumObjectType[o->type],"false"); } } } - if(o->type == LABEL_ENTRY || o->type == NULL_ENTRY) + if(o->type == LABEL_ENTRY) { for(i = 0; i < o->OBJECT_SIZE; i++) { const char* valor = (char*) o->values[i]; - printf(" (%s, '%s' ) \n",mappingEnumObjectType[o->type],valor); + printf(" (%s :: '%s' ) \n",mappingEnumObjectType[o->type],valor); } } + if(o->type == NULL_ENTRY){ + printf(" (%s :: '%s' ) \n",mappingEnumObjectType[LABEL_ENTRY],"NULL"); + } if(o->type == TDS_ENTRY){ // TODO (struct TDS) } - } - else + } else { printf("null \n"); } } +/** + * Desaloca a lista de objetos auxiliares time-component. Sendo esses da forma: + * Object --HEAD-> { {int,PATH} , ..., {int,PATH} } + * @param o + */ +void letGoTimeComponent(Object* o){ + if(o->OBJECT_SIZE < 2 && !o->aList){ + fprintf(stderr, "\n[letGoTimeComponent] Possible error while freeing memory \n"); + //exit(-1); + } + int i; + for(i = 0; i < o->OBJECT_SIZE; i++) { + Object* currentComponent = o->values[i]; + free(currentComponent->values[0]); + currentComponent->values[1] = NULL; + free(currentComponent->values); + currentComponent->values = NULL; + if(currentComponent->SINTH_BIND){ + free(currentComponent->SINTH_BIND); + } + currentComponent->SINTH_BIND = NULL; + free(currentComponent); + } +} + + void letgoObject(Object *o) { if(o) { - int i; - for (i = 0; i < o->OBJECT_SIZE; i++) - { - if(o->type != TYPE_SET || i < 2) - { - free(o->values[i]); // usar o free da tabela de simbolos para i == 3 (em outra localidade anteriormente) - // na chamada anterior - } - else if(o->type == TDS_ENTRY) - { - // TODO PARA TDS - } - o->values[i] = NULL; - } + // OBJETOS atômicos da linguagem e listas dos tipos padrões + if(o->type != TDS_ENTRY && o->type != TIME_COMPONENT){ + int i; + for (i = 0; i < o->OBJECT_SIZE; i++) + { + if(o->OBJECT_SIZE == 1 || o->type == WRITE_SMV_INFO || o->type == TYPE_SET) { + free(o->values[i]); // não precisa mais do mapeamento para type-sets (vai ser só um pos x size agora que tem type_smv_info um type-set) + } + // listas padrões + else{ + if(o->OBJECT_SIZE > 1){ + letgoObject(o->values[i]); + } + } + o->values[i] = NULL; + } + } + else{ + if(o->type == TDS_ENTRY){ + // let go tds + } + if(o->type == TIME_COMPONENT){ + // let go time component + letGoTimeComponent(o); + } + } } free(o->values); o->values = NULL; - if(o->STR){ - free(o->STR); - } - o->STR = NULL; if(o->SINTH_BIND){ free(o->SINTH_BIND); } o->SINTH_BIND = NULL; + //letgo min max verificando se o type_smv_info não é null + if(o->type_smv_info && (o->type == NUMBER_ENTRY || o->type == WRITE_SMV_INFO)){ + letGoTypeMinMax(o->type_smv_info); + o->type_smv_info = NULL; + } + //let go type-set + if(o->type_smv_info && (o->type == LABEL_ENTRY || o->type == TYPE_SET)){ + letGoTypeSet(o->type_smv_info); + o->type_smv_info = NULL; + } free(o); } +Object* copyObjectProperty(Object* o, char* path){ + if(o){ + Object* newOb = createObject(o->type, o->OBJECT_SIZE, o->values, o->timeContext, path, NULL); + newOb->fromTdsValue = 1; + return newOb; + } + else{ + return NULL; + } +} Object* copyObject(Object* o) { - Object* newOb = createObject(o->type, o->OBJECT_SIZE, o->values, o->timeContext, o->SINTH_BIND); - return newOb; + if(o){ + Object* newOb = createObject(o->type, o->OBJECT_SIZE, o->values, o->timeContext, o->SINTH_BIND, NULL); + return newOb; + } + return NULL; +} + +void updateNullRef(Object *var, Object *expr){ + var->type = expr->type; + // responsabilidade do metodo de atualizaçao de variavel logo depois + if(!expr->aList){ + var->values = (void **) malloc(sizeof(void *) * 1); + } + if(expr->SINTH_BIND){ + char* newBind = realloc(var->SINTH_BIND,strlen(expr->SINTH_BIND)+1); + if(!newBind){ + fprintf(stderr, "[updateNullRef] Error while allocating bind \n"); + exit(-1); + } + strcpy(newBind,expr->SINTH_BIND); + var->SINTH_BIND = newBind; + } } void updateObjectCell(Object* o, void** any, int any_type ,int object_size, int index, int prop) { //printf("[updateObject] indexUpdate: %d \n",index); + free(o->values[index]); // libera o indice atual, sobrescrevendo o valor + o->values[index] = NULL; + void* newPt; + if(object_size == 1) { - o->values[index] = NULL; - void* newPt = allocatePtObjects(any_type,any[0],o,index); + newPt = allocatePtObjects(any_type,any[0],o,index); o->values[index] = newPt; } - } +/** + * prototipo para listas + */ +void updateObjectReference(){ + +} @@ -263,36 +361,89 @@ void updateObject(Object *o, void **any, int any_type, int object_size, int inde if(index == -1 && prop == -1) { // vale para ambos os casos (mesmo que o seja um vetor sendo sobrescrito ou variavel comum) + // se um vetor é sobrescrito, devemos ou não limpar seus valores? (LIMPAR PODERIA TER EFEITOS COLATERAIS EM QUEM REFERENCIA ELE) + // não limpar poderia acarretar em objetos com memória solta (apesar que no final de cada escopo eles iam ser inevitavelmente liberados) + // PORÉM, e se nenhum objeto referenciar essa memória perdida? Vai ter que ser liberada em algum momento (final do programa?) + // mover a limpeza para object o método de object cell e deixar mais simples +/* int i; for (i = 0; i < o->OBJECT_SIZE; i++) { free(o->values[i]); o->values[i] = NULL; } +*/ if(object_size > 1) { - // passa referencia - o->values = any; - o->OBJECT_SIZE = object_size; + // passa referencia (é para arrays) + updateObjectReference(); +// o->values = any; +// o->OBJECT_SIZE = object_size; + } + else{ + updateObjectCell(o,any,any_type,object_size,0,-1); } - updateObjectCell(o,any,any_type,object_size,0,-1); } // caso x[i] = y else if(index != -1 ){ - free(o->values[index]); - o->values[index] = NULL; updateObjectCell(o,any,any_type,object_size,index,-1); } - int typeChanged = 0; - if(o->type != any_type && o->type != any_type) +// int typeChanged = 0; + if(o->type != any_type) { - printf("[updateObject] -------type-change----> %s \n",mappingEnumObjectType[any_type]); - o->type = any_type; - typeChanged = 1; + //printf("[updateObject] -------type-change----> %s \n",mappingEnumObjectType[any_type]); + exit(-1); + //typeChanged = 1; } - int oldRedef = o->redef; - o->redef = typeChanged || (contextChange != o->timeContext)? o->redef : o->redef+1; + //int oldRedef = o->redef; + //o->redef = typeChanged || (contextChange != o->timeContext)? o->redef : o->redef+1; o->timeContext = contextChange == o->timeContext? o->timeContext : contextChange; } +/** + * Adiciona um membro novo a uma lista, de maneira que seu novo limite de tamanho seja redefinido. + * @param original a lista original ou objeto único + * @param newMember o objeto de mesmo tipo que deve ser adicionado + * @SideEffects: Realoca o values de original. + */ +void updateListObjectBound(Object* original, Object* newMember) { + int mergedSize = original->OBJECT_SIZE +1; // lista + novo ou novo + novo (n ou 2) + void** mergedValues = realloc(original->values,mergedSize); + if(!mergedValues) { + fprintf(stderr, "[updateListObjectBound] ERROR IN ALLOCATION \n"); + exit(-1); + } + original->values = mergedValues; + original->values[original->OBJECT_SIZE] = newMember; // [n-1] ou [1] + original->OBJECT_SIZE++; +} + +Object * mergeGenericList(Object* LEFT_COMPONENT, Object* RIGHT_COMPONENT){ + + object_type selectedType; + // permite juntar tipos diferentes nesse caso + if(LEFT_COMPONENT->type == RIGHT_COMPONENT->type){ + selectedType = LEFT_COMPONENT->type; + } + else{ + //Object* MEMBER_OF_LIST = (Object*) LEFT_COMPONENT->values[0]; + //if(LEFT_COMPONENT->OBJECT_SIZE > 1 && MEMBER_OF_LIST->type != RIGHT_COMPONENT->type) { + fprintf(stderr, "ERROR: Array structure with different data types."); + exit(-1); + //} + //else{ + // selectedType = GEN_LIST; + //} + } + Object* newList = LEFT_COMPONENT; + if(!LEFT_COMPONENT->aList){ + void* vp[] = {LEFT_COMPONENT,RIGHT_COMPONENT}; + newList = createObjectDS(selectedType,2,vp,LEFT_COMPONENT->timeContext,LEFT_COMPONENT->SINTH_BIND,1); + } + else{ + updateListObjectBound(newList,RIGHT_COMPONENT); + } + return newList; +} + diff --git a/src/langmodules/TDS.c b/src/langmodules/TDS.c new file mode 100644 index 0000000..95cd37e --- /dev/null +++ b/src/langmodules/TDS.c @@ -0,0 +1,245 @@ +#include +#include +#include "../../headers/TDS.h" + + +TDS* createTDS(char *name, TDS_TYPE type, void *valueList, int delayed, int I_INTERVAL, int F_INTERVAL, void *limitCondition) { + + TDS* newTDS = (TDS*) malloc(sizeof(TDS)); + + newTDS->name = name; // nome sintetizado diretamente do código. + newTDS->type = type; + newTDS->DATA_SPEC = valueList; + + newTDS->DATA_TIME = malloc(sizeof(Object*)*F_INTERVAL+1); + int i; + // Por padrão, ainda não sabemos qual valor por tempo de cada parte dessa tds (vai ser avaliado no código via lazy) + for (i = 0; i < F_INTERVAL; i++) { + newTDS->DATA_TIME[i] = NULL; + } + + newTDS->TOTAL_DEPENDENCIES_PT = type == TDS_DEPEN? 0 : -1; + newTDS->linkedDependency = NULL; + newTDS->LAST_DELAYED_ACCEPT_TIME = type == TDS_DEPEN && delayed? I_INTERVAL+1 : -1; + + newTDS->delayed = delayed; + newTDS->I_INTERVAL = I_INTERVAL; + newTDS->F_INTERVAL = F_INTERVAL; + newTDS->SMV_REF = -1; + + newTDS->COMPONENT_TIMES = type == DATA_LIST? malloc(sizeof(int)*F_INTERVAL+1) : NULL; + if(newTDS->COMPONENT_TIMES){ + for (i = 0; i <= F_INTERVAL; i++) { + newTDS->COMPONENT_TIMES[i] = -1; + } + } + newTDS->noValue = 1; + newTDS->limitCondition = limitCondition; + newTDS->currentCondEval = limitCondition? 0 : 1; + + return newTDS; +} + +void addTdsDependency(TDS* dependency, TDS* tds){ + if(!tds->linkedDependency && !tds->TOTAL_DEPENDENCIES_PT){ + // alocação inicial de primeiro no maximo 150 dependencias + tds->linkedDependency = malloc(sizeof(TDS*) * MAX_DEPEND); + } + else{ + // DEVE REALIZAR REALLOC + if(tds->TOTAL_DEPENDENCIES_PT + 1 > MAX_DEPEND ){ + TDS** newRef = realloc(tds->linkedDependency, (tds->TOTAL_DEPENDENCIES_PT + 1) * 2); + if(!newRef) { + fprintf(stderr, "[addTdsDependency] ERROR IN ALLOCATION \n"); + exit(-1); + } + tds->linkedDependency = newRef; + } + } + tds->linkedDependency[tds->TOTAL_DEPENDENCIES_PT] = dependency; + tds->TOTAL_DEPENDENCIES_PT++; +} + +Object* getTdsValue(TDS* tds, int C_TIME, char* valuePath){ + if(tds->delayed){ + return copyObjectProperty(tds->DATA_TIME[tds->LAST_DELAYED_ACCEPT_TIME],valuePath); + } + return copyObjectProperty(tds->DATA_TIME[C_TIME],valuePath); +} + +void resolveDelayedTdsDependencies(TDS* tds, int C_TIME){ + // c_time não é o valor o qual a TDS começou a valer (só vale no próximo porque é delayed) + if(C_TIME >= tds->LAST_DELAYED_ACCEPT_TIME){ + Object* dependency = tds->linkedDependency[0]->DATA_TIME[C_TIME-1]; // aceita o anterior com atraso + if(!tds->DATA_TIME[tds->LAST_DELAYED_ACCEPT_TIME]){ + addDataToTds(tds,C_TIME,dependency); + tds->LAST_DELAYED_ACCEPT_TIME = C_TIME; + } + else{ + // o input parou (podemos liberar a porta) + if(!dependency){ + tds->LAST_DELAYED_ACCEPT_TIME = C_TIME; // vai referenciar um valor atual que é NULL + } + // SENÃO, ele mantem a referência anterior de ACCEPT ai ele indexa a partir desse (a ideia é tentar nao "copiar varios valores" + // pode dar problema na hora de liberar memoria (ou gerar efeitos colaterais)? + } + } +} + + +void resolveMergerTdsDependencies(TDS *tds, int C_TIME){ + int i; + Object* resolved = NULL; + for (i = 0; i < tds->TOTAL_DEPENDENCIES_PT; i++) { + TDS* dependency = tds->linkedDependency[i]; + // caso exista dado nesse instante (se não tiver não é necessário verificar pois não existe conflito de merge) + if(dependency->DATA_TIME[C_TIME]){ + // se a dependencia já não foi resolvida anteriormente e não foi resolvida nessa passada atual + if(!tds->DATA_TIME[C_TIME] && resolved == NULL){ + resolved = dependency->DATA_TIME[C_TIME]; + } + else{ + // vale ressaltar que isso aqui é só preocaução (já que a atualização da tds dependente está agora na responsabilidade dela mesma) + // elas que se "inscreveram" nas dependencias e ficam observando elas + // deve anular para esse instante de tempo + tds->DATA_TIME[C_TIME] = NULL; + return; + } + } + } + // sempre pode ocorrer a possibilidade da TDS de input em questão também não possuir DADOS! e então nada deve ser feito + if(resolved){ + addDataToTds(tds,C_TIME,resolved); + } +} + +int addDataToTds(TDS* currentTDS, int C_TIME, Object* value){ + int currentLimitCond = currentTDS->limitCondition? currentTDS->currentCondEval : 1; + if(value && C_TIME >= currentTDS->I_INTERVAL && currentTDS->DATA_TIME[C_TIME] == NULL && currentLimitCond) { + currentTDS->DATA_TIME[C_TIME] = value; + if(currentTDS->noValue){ + currentTDS->noValue = 0; + } + return 1; + } + return 0; +} + +void updateLimitCondition(TDS* tds, Object* condExpr){ + if(condExpr){ + if(condExpr->type != LOGICAL_ENTRY){ + fprintf(stderr,"Invalid filter expression used on %s. Specified condition was not a boolean type",tds->name); + exit(-1); + } + else{ + int eval = *(int*)condExpr->values[0]; + tds->currentCondEval = eval; + tds->currenCondBindRef = condExpr->SINTH_BIND; + } + } +} + +void resetLimitConditionEval(TDS* tds){ + tds->currentCondEval = 0; +} + +void letGoTDS(TDS* tds){ + +} + +void printTdsValues(TDS* tds, int C_TIME){ + if(!tds){ + return; + } + + if (!tds->delayed){ + if(tds->noValue || !tds->DATA_TIME[C_TIME] || tds->DATA_TIME[C_TIME]->type == NULL_ENTRY){ + printf("TDS(%s,%d) o----- NULL --------",tds->name,C_TIME); + } + else{ + Object* valueEncap = tds->DATA_TIME[C_TIME]; + if(valueEncap->type == NUMBER_ENTRY){ + printf("TDS(%s,%d) o----> value: %d --->---",tds->name,C_TIME,*(int*)valueEncap->values[0]); + } + else{ + printf("TDS(%s,%d) o----> value: %s --->---",tds->name,C_TIME,(char*)valueEncap->values[0]); + } + } + } + else{ + Object* valueEncap = tds->DATA_TIME[tds->LAST_DELAYED_ACCEPT_TIME]; + printf("-"); + if(tds->noValue || !valueEncap || valueEncap->type == NULL_ENTRY){ + printf("||-o TDS(%s,%d)",tds->name,C_TIME); + } + else{ + if(valueEncap->type == NUMBER_ENTRY){ + printf("| %d |-o TDS(%s,%d)",*(int*)valueEncap->values[0],tds->name,C_TIME); + } + else{ + printf("| %s |-o TDS(%s,%d)",(char*)valueEncap->values[0],tds->name,C_TIME); + } + } + } +} + +void prepareToPrintTDS(TDS* tds, int C_TIME){ + printTDS(tds,NULL,C_TIME); + if(tds->limitCondition && tds->type == TDS_DEPEN){ + resetLimitConditionEval(tds); + } +} + +void printTDS(TDS* tds, TDS* dependent, int C_TIME){ + if (!tds){ + return; + } + if(tds->type == TDS_DEPEN){ + int i; + for (i = 0; i < tds->TOTAL_DEPENDENCIES_PT; i++) { + TDS* depRefFifo = NULL; + if(tds->delayed){ + depRefFifo = tds; + } + printTDS(tds->linkedDependency[i],depRefFifo,C_TIME); + if(!depRefFifo){ + printf("->"); + } + if(tds->TOTAL_DEPENDENCIES_PT > 1){ + if(i == (tds->TOTAL_DEPENDENCIES_PT/2)-1){ + printf("\n"); + printf("\t\t\t\t\t"); + printf("o TDS(%s,%d)",tds->name,C_TIME); + if(dependent){ + printTdsValues(dependent,C_TIME); + } + printf("\n"); + } + else { + printf("\n"); + } + } + else{ + if(tds->limitCondition){ + if(tds->currentCondEval){ + printf("o TDS(%s,%d)",tds->name,C_TIME); + } + else{ + printf("|filter block|-o TDS (%s,%d)",tds->name,C_TIME); + } + } + else if (!tds->delayed){ + printf("o TDS(%s,%d)",tds->name,C_TIME); + } + else{ + if(tds->TOTAL_DEPENDENCIES_PT == 1 && (tds->linkedDependency[0]->TOTAL_DEPENDENCIES_PT == -1 || tds->linkedDependency[0]->TOTAL_DEPENDENCIES_PT == 1)){ + printTdsValues(tds,C_TIME); + } + } + } + } + } + else{ + printTdsValues(tds,C_TIME); + } +} \ No newline at end of file diff --git a/src/langmodules/TDSvar.c b/src/langmodules/TDSvar.c deleted file mode 100644 index 0f71201..0000000 --- a/src/langmodules/TDSvar.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include "../../headers/TDSvar.h" -#include "../../headers/constants.h" - - -TDSvar* createTDS(char* name, int type, int I_TIME, int F_TIME, int C_TIME, int linked, int delayed) { - - TDSvar* newTDS = (TDSvar*) malloc(sizeof(TDSvar)); - - newTDS->name = name; - newTDS->type = type; - newTDS->I_TIME = I_TIME; - newTDS->F_TIME = F_TIME; - newTDS->C_TIME = C_TIME; - newTDS->linked = linked; - newTDS->delayed = delayed; - - return newTDS; -} \ No newline at end of file diff --git a/src/langmodules/TypeMinMax.c b/src/langmodules/TypeMinMax.c new file mode 100644 index 0000000..a06b83d --- /dev/null +++ b/src/langmodules/TypeMinMax.c @@ -0,0 +1,217 @@ +// +// Created by mateus on 02/04/2021. +// + +#include +#include "../../headers/TypeMinMax.h" + + +TypeMinMax* createMinMaxByOneValue(int valSin){ + int min = 0; // init default + int max = 1; + if(valSin <= 0){ + min = valSin; + } + else{ + max = valSin; + } + return createMinMax(min,max); +} + +TypeMinMax* createMinMax(int min, int max){ + TypeMinMax* newMinMax = malloc(sizeof(TypeMinMax)); + newMinMax->min = min; + newMinMax->max = max; + return newMinMax; +} + +TypeMinMax* computeMinMaxSum(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2){ + int min = typeRefMinMax1->min + typeRefMinMax2->min; + int max = typeRefMinMax1->max + typeRefMinMax2->max; + return createMinMax(min,max); +} + +TypeMinMax* computeMinMaxSub(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2){ + int min = typeRefMinMax1->min - typeRefMinMax2->max; + int max = typeRefMinMax1->max - typeRefMinMax2->min; + return createMinMax(min,max); +} + +TypeMinMax* computeMinMaxNeg(TypeMinMax* typeRefMinMax1){ + int eNegativo = typeRefMinMax1->max < 0; + int min; + int max; + // maior positivo + if(eNegativo){ + min = (-1)*typeRefMinMax1->min; + max = (-1)*typeRefMinMax1->max; + } + // maior negativo + else{ + min = (-1)*typeRefMinMax1->max; + max = (-1)*typeRefMinMax1->min; + } + return createMinMax(min,max); +} + +TypeMinMax* computeMinMaxMul(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2){ + int min; + int max; + if(typeRefMinMax1->min >= 0 && typeRefMinMax2->min >= 0){ + min = typeRefMinMax1->min*typeRefMinMax2->min; + } + else{ + int cond = typeRefMinMax1->min >= 0; + // min1 >= 0 escolhe min2 senao escolhe min1 + int negativo = cond? typeRefMinMax2->min : typeRefMinMax1->min; + // faz o contrário + int positivo = cond? typeRefMinMax1->max : typeRefMinMax2->max; + min = negativo*positivo; + } + //if(typeRefMinMax1->max > 0 && typeRefMinMax2->max > 0){ + max = typeRefMinMax1->max *typeRefMinMax2->max; + //} + return createMinMax(min,max); +} + +TypeMinMax* computeMinMaxDiv(TypeMinMax* typeRefMinMax1, TypeMinMax* typeRefMinMax2){ + int min; + int max; + if(typeRefMinMax1->min >= 0 && typeRefMinMax2->max > 0){ + min = typeRefMinMax1->min / typeRefMinMax2->max; + } + // ou o min1 é negativo ou max2 é zero/negativo (tornando minmax2 negativo) + else{ + // min1 é negativo + if(typeRefMinMax1->min < 0){ + if(typeRefMinMax2->min > 0){ + min = typeRefMinMax1->min / typeRefMinMax2->min; // tenta gerar o negativo com maior distancia a 0 + } + else{ + // min2 negativo + // o segundo é negativo (mas é o mais próximo de zero) + if(typeRefMinMax2->max < 0){ + min = typeRefMinMax1->min / typeRefMinMax2->max; // deve gerar o menor positivo o possível + } + else{ + // o max do segundo é perto de zero e positivo (gerando valores muito grandes) ou seja o valor minimo deve ser ele mesmo + min = typeRefMinMax1->min; + } + } + } + // max2 é negativo e é o mais próximo de zero (um valor de módulo pequeno) (e o min2 também é negativo só que de modulo grande) + else{ + // o min 1 é positivo ou zero (senão teriamos caido no código de antes) ou seja devemos criar um negativo mais longe de zero (ou seja de módulo alto) + if(typeRefMinMax1->min > 0 && typeRefMinMax2->max != 0){ + min = typeRefMinMax1->min / typeRefMinMax2->max; // deve gerar o negativo de maior módulo, considerando que min2 é um negativo "grande" + // código replicado porém "separado" + } + // max2 é zero ou seja o menor valor de divisão é algum número entre min2 ~ -1. + // Como min1 é positivo, a menor divisão que ele vai assumir é ele mesmo negativo, qualquer outra daria um número mais perto de zero. + else{ + min = typeRefMinMax1->min/(-1); + } + } + } + + if(typeRefMinMax2->min > 0){ + max = typeRefMinMax1->max / typeRefMinMax2->min; // vai gerar o número de maior módulo independente do sinal + // no caso mesmo que max1 seja negativo ainda quer dizer que ele é o mais próximo de zero comparado aos demais e seu minimo + } + else{ + // min2 é negativo + if(typeRefMinMax2->min < 0){ + if(typeRefMinMax2->max > 0 ){ + // o valor máximo assumido pelo resultado é ele mesmo porque o menor positivo nesse caso é o 1 + max = typeRefMinMax1->max; // seja positivo ou negativo + } + // o max2 é um número menor que zero porém de módulo pequeno (comparado ao seu minimo) + else{ + if(typeRefMinMax2->max != 0){ + max = typeRefMinMax1->max/typeRefMinMax2->max; // max1/max2 (max2 é um número bem perto de zero e negativo, tirando o menos possivel de max1) + } + else{ + // max2 é zero ou seja o número até pode ser zero, mas não vai realizar a divisão por zero. + // Ou seja o valor do segundo operando que menos vai tirar de max2 é -1 + max = typeRefMinMax1->max /(-1); + } + } + } + // min2 é zero + else{ + // ou seja max2 é positivo + // então o que iria tirar menos é o 1 (já que max2 não pode ser zero tmb) + max = typeRefMinMax1->max; + } + } + return createMinMax(min,max); +} + + +TypeMinMax* computeMinMaxMod(TypeMinMax* typeRefMinMax1, int by2){ + + int min; + int max; + // nuXmv é muito rigido quanto aos valores possíveis... + /* + if(by2){ + min = 0; + max = 1; + } + else{ + */ + min = typeRefMinMax1->min < 0? typeRefMinMax1->min : 0; // o mínimo é o resto da divisão ser zero ou ser o menor número possível + max = typeRefMinMax1->max; // o máximo é ser o próprio número em seu valor máximo + //} + return createMinMax(min,max); +} + +TypeMinMax* copyTypeMinMax(TypeMinMax* original){ + if (original){ + return createMinMax(original->min,original->max); + } + return NULL; +} + +int mergeTypeMinMax(TypeMinMax* original, TypeMinMax* newInfo){ + int min = original->min; + int max = original->max; + int newMax = newInfo->max; + int newMin = newInfo->min; + + int changeMin = newMin < min? 0 : -1; + int changeMax = newMax > max? 1 : -1; + + if(changeMax != -1 && changeMin != -1){ + original->max = newMax; + original->min = newMin; + return 2; + } + if(changeMin != -1){ + original->min = newMin; + return changeMin; + } + if(changeMax != -1){ + original->max = newMax; + return changeMax; + } + return -1; +} + +int changeMinMax(TypeMinMax* tmm, int value){ + int min = tmm->min; + int max = tmm->max; + if(value < min){ + tmm->min = value; + return 0; + } + if(value > max){ + tmm->max = value; + return 1; + } + return -1; +} + +void letGoTypeMinMax(TypeMinMax* tmm){ + free(tmm); +} \ No newline at end of file diff --git a/src/langmodules/TypeSet.c b/src/langmodules/TypeSet.c new file mode 100644 index 0000000..7433ea8 --- /dev/null +++ b/src/langmodules/TypeSet.c @@ -0,0 +1,89 @@ +// +// Created by mateus on 31/03/2021. +// + +#include +#include +#include +#include "../../headers/TypeSet.h" + +//int MULTIPLIER_SIMPLE_HASH = 1; + + +TypeSet* createTypeSet(char* defaultWord){ + TypeSet* ts = malloc(sizeof(TypeSet)); + ts->usedSize = MAX_SIMPLE; + ts->hash_set = malloc(sizeof(char*)*ts->usedSize); + int i; + for (i = 0; i < ts->usedSize; i++) { + ts->hash_set[i] = NULL; + } + if(defaultWord){ + int hashDefaultWord = hash(defaultWord,ts->usedSize); + ts->hash_set[hashDefaultWord] = defaultWord; + ts->lastIndex = hashDefaultWord; + } + else{ + ts->lastIndex = 0; + } + return ts; +} + +TypeSet* copyTypeSet(TypeSet* original){ + if(original){ + TypeSet* newCopy = createTypeSet(NULL); + int i; + int tempIndex = 0; + for (i = 0; i <= original->lastIndex; i++) { + if(original->hash_set[i]){ + addElementToTypeSet(newCopy,original->hash_set[i]); + tempIndex = i; + } + } + newCopy->lastIndex = tempIndex; + return newCopy; + } + return NULL; +} + +int addElementToTypeSet(TypeSet* ts, char* newElement){ + int pos = hash(newElement,ts->usedSize); + if(!ts->hash_set[pos]){ + //char* aloc = malloc(sizeof(char)*(strlen(newElement)+1)); // vai pegar do dicionário! lembre-se disso + //strcpy(aloc,newElement); + //ts->hash_set[pos] = aloc; + ts->hash_set[pos] = newElement; + ts->lastIndex = pos > ts->lastIndex? pos : ts->lastIndex; + return 1; + } + if(strcmp(newElement,ts->hash_set[pos]) != 0){ + // politica de redistribuição (podemos tentar implementar de novo) + fprintf(stderr,"[addElementToTypeSet] Collision !\n"); + exit(-1); + } + return 0; +} + +/*Será atualizado após descobrir o memory leak*/ +/** + * Dado uma variável de interesse de um módulo (ex: value (tds) return (funções de tds). Atualiza + * o type-set dessa variável baseado no tipo SMV de uma outra variável de dependência (min max ou outro type-set). + * @param var o nome da variável de interesse + * @param headerModule o header do módulo em que a alteração será feita + * @param auxTableModule a tabela de simbolos auxiliar desse módulo + * @param varD o nome (referência) da variável dependência + * @param auxTableDependency a tabela auxiliar que tem as inforamções do tipo da dependência + * @SideEffects: Realoca a string da declaração de var para comportar cada valor possível do tipo da dependência + */ +//void createUnionAtSmvType(char* var, HeaderSmv* headerModule, STable* auxTableModule, char* varD, STable* auxTableDependency); + +void letGoTypeSet(TypeSet* ts){ + if(ts){ + int i; + for (i = 0; i < ts->usedSize; i++) { + ts->hash_set[i] = NULL; + } + free(ts->hash_set); + free(ts); + } +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index 11d09db..1aefef6 100644 --- a/src/main.c +++ b/src/main.c @@ -3,10 +3,9 @@ #include #include "../headers/STable.h" #include "../headers/Node.h" - #include "../headers/HeaderSmv.h" #include "../headers/PreProcess.h" #include "../headers/Interpreter.h" - #include "../headers/PostProcess.h" + extern int yylex(void); extern int yyparse(); @@ -16,100 +15,129 @@ extern void yyerror(const char *s); int main(int argc, char* argv[]) { - - - FILE *fp; // .tds file - FILE *smvP; // .smv file; - fp = fopen(argv[1], "r"); - astout = fopen("results/astOutput", "w"); - smvP = fopen(argv[2], "r+"); - - //printf("%s \n",argv[1]); - //printf("%s \n",argv[2]); - - if(!fp){ - printf("CADE MEU CODIGO!?"); - return -1; - } + + int interactive = 0; + int interactiveParamPassed = 0; + FILE *fp = NULL; // .tds file + int sizeFpName; + FILE *smvP = NULL; // .smv file + int sizeSmvName; + if(argv[1]){ + int size = strlen(argv[1]); + if(size == 4){ + interactive = 1; + interactiveParamPassed = 1; + } + else{ + fp = fopen(argv[1], "r"); + sizeFpName = size; + if(argv[1][sizeFpName-1] != 's' || argv[1][sizeFpName-2] != 'd' || argv[1][sizeFpName-3] != 't'){ + fprintf(stderr,"Expected .tds input file \n"); + exit(-1); + } + } + } + else{ + // não tem input tds nem -int + fprintf(stderr,"No .tds input file found!\n"); + exit(-1); + } + + if(argv[2]){ + if(interactiveParamPassed){ + fp = fopen(argv[2], "r"); + sizeFpName = strlen(argv[2]); + if(argv[2][sizeFpName-1] != 's' || argv[2][sizeFpName-2] != 'd' || argv[2][sizeFpName-3] != 't'){ + fprintf(stderr,"Expected .tds input file \n"); + exit(-1); + } + } + else{ + smvP = fopen(argv[2], "r+"); + sizeSmvName = strlen(argv[2]); + if(argv[2][sizeSmvName-1] != 'v' || argv[2][sizeSmvName-2] != 'm' || argv[2][sizeSmvName-3] != 's'){ + fprintf(stderr,"Expected .smv input file \n"); + exit(-1); + } + } + } + else{ + if(interactiveParamPassed){ + fprintf(stderr,"No .tds input file found!\n"); + exit(-1); + } + } + if(interactiveParamPassed){ + if(argv[3]){ + smvP = fopen(argv[3], "r+"); + sizeSmvName = strlen(argv[3]); + if(argv[3][sizeSmvName-1] != 'v' || argv[3][sizeSmvName-2] != 'm' || argv[3][sizeSmvName-3] != 's'){ + fprintf(stderr,"Expected .smv input file \n"); + exit(-1); + } + } + } + + + if(!fp){ + fprintf(stderr,".tds input file path not found!\n"); + return -1; + } + astout = fopen("results/astOutput", "w"); yyin = fp; yyparse(); - fprintf(astout,"--------------TREE--------------------\n"); filePrintNode(root,astout); fclose(astout); fclose(fp); // tabelas e componentes globais - HeaderController* controller = createController(); + EnvController* controller = createController(interactive); STable* global = createTable(GLOBAL, NULL, 0, 0, -1); //pré processamento - preProcessSmv(smvP,controller); + printf("\n\n"); + if(smvP){ + printf("Start PreProcess\n\n"); + preProcessSmv(smvP,controller); + } + else{ + printf("No .smv file detected. Using default model\n\n"); + setDefaultSmv(controller); + } setUpMainSmvTable(controller,global); - - printf("--------------------------------- EVAL ---------------------------------------------\n"); + + //printf("--------------------------------- EVAL ---------------------------------------------\n"); printf("\n"); printf("\n"); - - //pos processamento - eval(root, global, controller); + + //interpretação e pos processamento + startInterpreter(root,global,controller); printf("\n"); printf("------------------------------------------------------------------------------\n"); - printf("\n"); - printf("\n"); - printf("\n"); - printf("\n"); + //printf("\n\n\n\n"); - printf("--------------------------------- PROGRAM TABLES ---------------------------------------------\n"); +// printf("--------------------------------- PROGRAM TABLES ---------------------------------------------\n"); - printTable(global); - printf("\n"); +// printTable(global); +// printf("\n"); - printf("--------------------------------- smv-INFO TABLES ---------------------------------------------\n"); - - printTable(controller->mainInfo); - printf("\n"); - printf("\n"); - printf("\n"); - printTable(controller->originalPorts); - printf("\n"); - printf("\n"); - printf("\n"); +// printf("--------------------------------- smv-INFO TABLES ---------------------------------------------\n"); +// printTable(controller->mainInfo); + printf("\n\n\n\n"); +// printTable(controller->originalPorts); + printf("\n\n\n"); letgoTable(global); - printf("--------------------------------- HEADERS ---------------------------------------------\n"); - - - printAllHeaders(controller); - - if(controller->declaredPorts != controller->expectedPorts){ - printf("\n"); - if(!controller->declaredPorts){ - fprintf(stderr, "[WARNING] THE MODEL GENERATION WAS SUCCESSFUL, HOWEVER NO TDS DEFINITION WAS FOUND \n IT IS RECOMMENDED THAT YOU REVIEW YOUR .tds FILE \n"); - } - else{ - fprintf(stderr,"[WARNING] THE MODEL GENERATION WAS SUCCESSFUL, HOWEVER ONLY %d PORTS WERE DECLARED. %d PORTS WERE EXPECTED \n", - controller->declaredPorts,controller->expectedPorts); - } - } + //printf("--------------------------------- HEADERS ---------------------------------------------\n"); + //printAllHeaders(controller); + validateAfterInterPost(controller); writeResultantHeaders(controller,"results/newSmvfile.smv"); - fclose(smvP); - letgoNode(root); - - - -// char* temp = controller->PORTS_RELATED[0]->varBuffer[1]; -// char* result = addParams(temp,"BATATA","{","}"); -// printf("%s\n",result); -// char* testAgain = addParams(result,"JUDGEMENT AHS COME TO YOU","{","}"); -// printf("%s\n",testAgain); - + if(smvP) { + fclose(smvP); + } letGoHeaderControl(controller); - - - -} - +} \ No newline at end of file diff --git a/src/util/Hash.c b/src/util/Hash.c new file mode 100644 index 0000000..1075b76 --- /dev/null +++ b/src/util/Hash.c @@ -0,0 +1,29 @@ +// +// Created by mateus on 27/03/2021. +// + +#include "../../headers/Hash.h" +#include +#include + +/** + * + * djb2 * This algorithm was first reported by Dan Bernstein + */ +int hash(char *str, int SIZE_ED) +{ + int hash = 5381; + int c; + char* strpt = str; + + while (c = *strpt++){ + hash = (( ( (hash << 5) + hash) + c ) % SIZE_ED); /* hash * 33 + c */ + } + int final = hash % SIZE_ED; + if(final > SIZE_ED-1){ + fprintf(stderr,"[hash] Error in generating HASH\n"); + exit(-1); + } + return final; +} + diff --git a/src/textManager.c b/src/util/textManager.c similarity index 60% rename from src/textManager.c rename to src/util/textManager.c index a36c2c6..2afaf24 100644 --- a/src/textManager.c +++ b/src/util/textManager.c @@ -1,8 +1,9 @@ #include #include #include -#include "../headers/textManager.h" +#include "../../headers/textManager.h" +int multiFactor = 1; char * customCat(char* dest, char* src, char toIgnore, int ignoreMode) { @@ -36,6 +37,16 @@ char * customCat(char* dest, char* src, char toIgnore, int ignoreMode) { } +void removeAfter(char* dest, char* src, char stop){ + customCat(dest,src,stop,0); +} + +char* formatNumeric(int ctime){ + char* directiveValueBind = malloc(sizeof(char)*ALOC_SIZE_LINE/10); + sprintf(directiveValueBind, "%d", ctime); + return directiveValueBind; +} + void clearOldPortsRefs(char* oldConstraint, char* toCopyResult) { int removedCharacters = 0; @@ -74,8 +85,39 @@ void clearOldPortsRefs(char* oldConstraint, char* toCopyResult) { //printf("[clearOldPortsRefs] copiando e filtrando... %c \n",*oldConstraintRef); } } +// ports. +char* removeAllSubStrings(char* string, char* toRemove){ + int originalSize = strlen(string); + int toRemoveSize = strlen(toRemove); + char* result = malloc(sizeof(char)*originalSize); + char* resultRef = result; + char* oldRef = string; + int copy = 1; + int c = 0; + while(*oldRef){ + if(copy && *oldRef != toRemove[0]){ + *resultRef = *oldRef; + resultRef++; + } + else{ + if(c > (originalSize - toRemoveSize) ){ + *resultRef = *oldRef; + resultRef++; + } + else{ + copy = 0; + } + } + if (*oldRef == toRemove[toRemoveSize-1]){ + copy = 1; + } + c++; + oldRef++; + } + return result; +} -char *addParams(char *original, char *param, char* delim1, char* delim2) { +char *addParams(char *original, char *param, char *delim1, char *delim2, int useRealloc) { char *newString; char *auxNewAdd; @@ -93,9 +135,19 @@ char *addParams(char *original, char *param, char* delim1, char* delim2) { // qualquer string passada (original) são das seguintes formas: xxxxxxxxx , xxxxxxxxx; , xxxxxxxxx(...)\n , xxxxxxxxx(...);\n // caso possua o delmitador de fechamento ) ou qualquer outro... if(original[tamOriginal-3] == delim2[0] || original[tamOriginal-2] == delim2[0]){ - newString = (char*) calloc(strlen(original) + strlen(param) + 2 + 1, sizeof(char)); // original + param + ',' + ' ' + '\0' + int newSize = strlen(original) + strlen(param) + 2 + 1; // original + param + ',' + ' ' + '\0' + newString = useRealloc ? (char*) realloc(original,newSize) : (char*) calloc(newSize, sizeof(char)); + if(!newString){ + fprintf(stderr,"[addParams] Fail in realloc\n"); + exit(-1); + } auxNewAdd = newString; - auxNewAdd = customCat(auxNewAdd,original,delim2[0],0); + if(!useRealloc){ + auxNewAdd = customCat(auxNewAdd,original,delim2[0],0); + } + else{ + auxNewAdd[tamOriginal-3] = '\0'; + } //printf("caso 1... %s \n",newString); auxNewAdd = customCat(auxNewAdd,", ",0,0); //printf("caso 1... %s \n",newString); @@ -105,14 +157,23 @@ char *addParams(char *original, char *param, char* delim1, char* delim2) { //printf("caso 1... %s \n",newString); } else { - newString = (char*) calloc(strlen(original) + 1 + strlen(param) + 1 + 1, sizeof(char)); -// newString = (char*) malloc(sizeof(char)*(strlen(original) + 1 + strlen(param) + 1 + 1)); // ( ) e \0 + int newSize = strlen(original) + 1 + strlen(param) + 1 + 1; + newString = useRealloc ? (char*) realloc(original,newSize) : (char*) calloc(newSize, sizeof(char)); + if(!newString){ + fprintf(stderr,"[addParams] Fail in realloc\n"); + exit(-1); + } auxNewAdd = newString; - if(statementEnd){ - auxNewAdd = customCat(auxNewAdd,original,';',0); + if(!useRealloc){ + if(statementEnd){ + auxNewAdd = customCat(auxNewAdd,original,';',0); + } + else{ + auxNewAdd = customCat(auxNewAdd,original,'\n',0); + } } else{ - auxNewAdd = customCat(auxNewAdd,original,'\n',0); + auxNewAdd[tamOriginal-1] = '\0'; } auxNewAdd = customCat(auxNewAdd,delim1,0,0); auxNewAdd = customCat(auxNewAdd,param,0,0); @@ -129,9 +190,22 @@ char *addParams(char *original, char *param, char* delim1, char* delim2) { return newString; } -void updateSubStringInterval(const char *newValue, char *updated, int sizeNew, int pointIni, int pointEnd, int size, +char* updateSubStringInterval(const char *newValue, char *updated, int sizeNew, int pointIni, int pointEnd, int size, int *newPointInit, int *newPointEnd, int variantPointIni) { + + if(size + sizeNew >= ALOC_SIZE_LINE*multiFactor) + { + multiFactor = multiFactor*2; + char* newStrSize = realloc(updated,ALOC_SIZE_LINE*multiFactor); + if(newStrSize == NULL) + { + fprintf(stderr, "[updateSubStringInterval] FAIL IN REALLOCATE STRING SIZE FOR %s !",updated); + exit(-1); + } + updated = newStrSize; + } + char aux[size - (pointEnd+1)]; // pointEnd+1 (é o indice(tamanho) sem ser 0-index) (+1 é para estarmos fora da zona da sobrescrita) int i; // deve-se copiar os caracteres que vem após a zona de sobrescrita @@ -174,16 +248,31 @@ void updateSubStringInterval(const char *newValue, char *updated, int sizeNew, i } updated[size] = '\0'; (*newPointInit) = variantPointIni? (*newPointEnd) : pointIni; - + return updated; } char* overwriteParam(char* moduleName, char* param){ - char* refOldPt; - refOldPt = strstr(moduleName,"("); - memset(refOldPt, '\n', 1); - refOldPt++; - memset(refOldPt, '\0', strlen(refOldPt)); - return addParams(moduleName,param,"(",")"); + char* refOldPt = moduleName; + char moduleNameNoParam[strlen(moduleName)]; + char* refModuleNameNoParam = moduleNameNoParam; + //refOldPt = strstr(moduleName,"("); + while(*refOldPt != '('){ + *refModuleNameNoParam = *refOldPt; + refOldPt++; + refModuleNameNoParam++; + } + if(moduleName[strlen(moduleName)-2] == ';'){ + *refModuleNameNoParam = ';'; + refModuleNameNoParam++; + } + *refModuleNameNoParam = '\n'; + refModuleNameNoParam++; + *refModuleNameNoParam = '\0'; + + //memset(refOldPt, '\n', 1); + //refOldPt++; + //memset(refOldPt, '\0', strlen(refOldPt)); + return addParams(moduleNameNoParam, param, "(", ")", 0); } diff --git a/teste2.c b/tests/teste2.c similarity index 100% rename from teste2.c rename to tests/teste2.c