/**CFile****************************************************************

  FileName    [ltl_parser.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Liveness property checking.]

  Synopsis    [LTL checker.]

  Author      [Sayak Ray]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - January 1, 2009.]

  Revision    [$Id: ltl_parser.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]

***********************************************************************/

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "aig/aig/aig.h"
#include "base/abc/abc.h"
#include "base/main/mainInt.h"

ABC_NAMESPACE_IMPL_START


enum ltlToken { AND, OR, NOT, IMPLY, GLOBALLY, EVENTUALLY, NEXT, UNTIL, BOOL };
enum ltlGrammerToken { OPERAND, LTL, BINOP, UOP };
typedef enum ltlToken tokenType;
typedef enum ltlGrammerToken ltlGrammerTokenType;

struct ltlNode_t
{
    tokenType type;
    char *name;
    Aig_Obj_t *pObj;
    struct ltlNode_t *left;
    struct ltlNode_t *right;
};

typedef struct ltlNode_t ltlNode;

ltlNode *generateTypedNode( tokenType new_type )
//void generateTypedNode( ltlNode *new_node, tokenType new_type )
{
    ltlNode *new_node;

    new_node = (ltlNode *)malloc( sizeof(ltlNode) );
    if( new_node )
    {
        new_node->type = new_type;
        new_node->pObj = NULL;
        new_node->name = NULL;
        new_node->left = NULL;
        new_node->right = NULL;
    }

    return new_node;
}

Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAig, ltlNode *pLtlNode );

static inline int isNotVarNameSymbol( char c )
{
    return ( c == ' ' || c == '\t' || c == '\n' || c == ':' || c == '\0' );
}

void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk )
{
    char *pLtlFormula, *tempFormula;
    int i;

    if( pAbc->vLTLProperties_global != NULL )
    {
//        printf("Deleting exisitng LTL database from the frame\n");
        Vec_PtrFree( pAbc->vLTLProperties_global );
        pAbc->vLTLProperties_global = NULL;
    }
    pAbc->vLTLProperties_global = Vec_PtrAlloc(Vec_PtrSize(pNtk->vLtlProperties));
    Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pLtlFormula, i )
    {
        tempFormula = (char *)malloc( sizeof(char)*(strlen(pLtlFormula)+1) );
        sprintf( tempFormula, "%s", pLtlFormula );
        Vec_PtrPush( pAbc->vLTLProperties_global, tempFormula );
    }
}

char *getVarName( char *suffixFormula, int startLoc, int *endLocation )
{
    int i = startLoc, length;
    char *name;

    if( isNotVarNameSymbol( suffixFormula[startLoc] ) )
        return NULL;

    while( !isNotVarNameSymbol( suffixFormula[i] ) )
        i++;
    *endLocation = i;
    length = i - startLoc;
    name = (char *)malloc( sizeof(char) * (length + 1));
    for( i=0; i<length; i++ )
        name[i] = suffixFormula[i+startLoc];
    name[i] = '\0';

    return name;
}


int startOfSuffixString = 0;

int isUnexpectedEOS( char *formula, int index )
{
    assert( formula );
    if( index >= (int)strlen( formula ) )
    {
        printf("\nInvalid LTL formula: unexpected end of string..." );
        return 1;
    }
    return 0;
}

int isTemporalOperator( char *formula, int index )
{
    if( !(isUnexpectedEOS( formula, index ) || formula[ index ] == 'G' || formula[ index ] == 'F' || formula[ index ] == 'U' || formula[ index ] == 'X') )
    {
        printf("\nInvalid LTL formula: expecting temporal operator at the position %d....\n", index);
        return 0;
    }
    return 1;
}

ltlNode *readLtlFormula( char *formula )
{
    char ch;
    char *varName;
    int formulaLength, rememberEnd;
    int i = startOfSuffixString;
    ltlNode *curr_node, *temp_node_left, *temp_node_right;
    char prevChar;
    
    formulaLength = strlen( formula );
    if( isUnexpectedEOS( formula, startOfSuffixString ) )
    {
        printf("\nFAULTING POINT: formula = %s\nstartOfSuffixString = %d, formula[%d] = %c\n\n", formula, startOfSuffixString, startOfSuffixString - 1, formula[startOfSuffixString-1]);
        return NULL;
    }
            
    while( i < formulaLength )
    {
        ch = formula[i];

        switch(ch){
            case ' ':
            case '\n':
            case '\r':
            case '\t':
            case '\v':
            case '\f':
                        i++;
                        startOfSuffixString = i;
                        break;
            case ':':
                        i++;
                        if( !isTemporalOperator( formula, i ) )
                            return NULL;
                        startOfSuffixString = i;
                        break;
            case 'G':
                        prevChar = formula[i-1];
                        if( prevChar == ':' ) //i.e. 'G' is a temporal operator
                        {
                            i++;
                            startOfSuffixString = i;
                            temp_node_left = readLtlFormula( formula );
                            if( temp_node_left == NULL )
                                return NULL;
                            else
                            {
                                curr_node = generateTypedNode(GLOBALLY);
                                curr_node->left = temp_node_left;
                                return curr_node;
                            }
                        }
                        else    //i.e. 'G' must be starting a variable name
                        {
                            varName = getVarName( formula, i, &rememberEnd );
                            if( !varName )
                            {
                                printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
                                return NULL;
                            }
                            curr_node = generateTypedNode(BOOL);
                            curr_node->name = varName;
                            i = rememberEnd;
                            startOfSuffixString = i;
                            return curr_node;
                        }
            case 'F':
                        prevChar = formula[i-1];
                        if( prevChar == ':' ) //i.e. 'F' is a temporal operator
                        {
                            i++;
                            startOfSuffixString = i;
                            temp_node_left = readLtlFormula( formula );
                            if( temp_node_left == NULL )
                                return NULL;
                            else
                            {
                                curr_node = generateTypedNode(EVENTUALLY);
                                curr_node->left = temp_node_left;
                                return curr_node;
                            }
                        }
                        else //i.e. 'F' must be starting a variable name
                        {
                            varName = getVarName( formula, i, &rememberEnd );
                            if( !varName )
                            {
                                printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
                                return NULL;
                            }
                            curr_node = generateTypedNode(BOOL);
                            curr_node->name = varName;
                            i = rememberEnd;
                            startOfSuffixString = i;
                            return curr_node;
                        }    
            case 'X':
                        prevChar = formula[i-1];
                        if( prevChar == ':' ) //i.e. 'X' is a temporal operator
                        {
                            i++;
                            startOfSuffixString = i;
                            temp_node_left = readLtlFormula( formula );
                            if( temp_node_left == NULL )
                                return NULL;
                            else
                            {
                                curr_node = generateTypedNode(NEXT);
                                curr_node->left = temp_node_left;
                                return curr_node;
                            }
                        }
                        else //i.e. 'X' must be starting a variable name
                        {
                            varName = getVarName( formula, i, &rememberEnd );
                            if( !varName )
                            {
                                printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
                                return NULL;
                            }
                            curr_node = generateTypedNode(BOOL);
                            curr_node->name = varName;
                            i = rememberEnd;
                            startOfSuffixString = i;
                            return curr_node;
                        }    
            case 'U':
                        prevChar = formula[i-1];
                        if( prevChar == ':' ) //i.e. 'X' is a temporal operator
                        {
                            i++;
                            startOfSuffixString = i;
                            temp_node_left = readLtlFormula( formula );
                            if( temp_node_left == NULL )
                                return NULL;
                            temp_node_right = readLtlFormula( formula );
                            if( temp_node_right == NULL )
                            {
                                //need to do memory management: if right subtree is NULL then left
                                //subtree must be freed.
                                return NULL;
                            }
                            curr_node = generateTypedNode(UNTIL);
                            curr_node->left = temp_node_left;
                            curr_node->right = temp_node_right;
                            return curr_node;
                        }
                        else //i.e. 'U' must be starting a variable name
                        {
                            varName = getVarName( formula, i, &rememberEnd );
                            if( !varName )
                            {
                                printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
                                return NULL;
                            }
                            curr_node = generateTypedNode(BOOL);
                            curr_node->name = varName;
                            i = rememberEnd;
                            startOfSuffixString = i;
                            return curr_node;
                        }    
            case '+':
                        i++;
                        startOfSuffixString = i;
                        temp_node_left = readLtlFormula( formula );
                        if( temp_node_left == NULL )
                            return NULL;
                        temp_node_right = readLtlFormula( formula );
                        if( temp_node_right == NULL )
                        {
                            //need to do memory management: if right subtree is NULL then left
                            //subtree must be freed.
                            return NULL;
                        }
                        curr_node = generateTypedNode(OR);
                        curr_node->left = temp_node_left;
                        curr_node->right = temp_node_right;
                        return curr_node;
            case '&':
                        i++;
                        startOfSuffixString = i;
                        temp_node_left = readLtlFormula( formula );
                        if( temp_node_left == NULL )
                            return NULL;
                        temp_node_right = readLtlFormula( formula );
                        if( temp_node_right == NULL )
                        {
                            //need to do memory management: if right subtree is NULL then left
                            //subtree must be freed.
                            return NULL;
                        }
                        curr_node = generateTypedNode(AND);
                        curr_node->left = temp_node_left;
                        curr_node->right = temp_node_right;
                        return curr_node;
            case '!':
                        i++;
                        startOfSuffixString = i;
                        temp_node_left = readLtlFormula( formula );
                        if( temp_node_left == NULL )
                            return NULL;
                        else
                        {
                            curr_node = generateTypedNode(NOT);
                            curr_node->left = temp_node_left;
                            return curr_node;
                        }
            default:
                varName = getVarName( formula, i, &rememberEnd );
                if( !varName )
                {
                    printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
                    return NULL;
                }
                curr_node = generateTypedNode(BOOL);
                curr_node->name = varName;
                i = rememberEnd;
                startOfSuffixString = i;
                return curr_node;
        }
    }
    return NULL;
}

void resetGlobalVar()
{
    startOfSuffixString = 0;
}

ltlNode *parseFormulaCreateAST( char *inputFormula )
{
    ltlNode *temp;

    temp = readLtlFormula( inputFormula );
    //if( temp == NULL )
    //    printf("\nAST creation failed for formula %s", inputFormula );
    resetGlobalVar();
    return temp;
}

void traverseAbstractSyntaxTree( ltlNode *node )
{
    switch(node->type){
        case( AND ):
            printf("& ");
            assert( node->left != NULL );
            assert( node->right != NULL );
            traverseAbstractSyntaxTree( node->left );
            traverseAbstractSyntaxTree( node->right );
            return;
        case( OR ):
            printf("+ ");
            assert( node->left != NULL );
            assert( node->right != NULL );
            traverseAbstractSyntaxTree( node->left );
            traverseAbstractSyntaxTree( node->right );
            return;
        case( NOT ):
            printf("~ ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree( node->left );
            assert( node->right == NULL );
            return;
        case( GLOBALLY ):
            printf("G ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree( node->left );
            assert( node->right == NULL );
            return;
        case( EVENTUALLY ):
            printf("F ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree( node->left );
            assert( node->right == NULL );
            return;
        case( NEXT ):
            printf("X ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree( node->left );
            assert( node->right == NULL );
            return;
        case( UNTIL ):
            printf("U ");
            assert( node->left != NULL );
            assert( node->right != NULL );
            traverseAbstractSyntaxTree( node->left );
            traverseAbstractSyntaxTree( node->right );
            return;
        case( BOOL ):
            printf("%s ", node->name);
            assert( node->left == NULL );
            assert( node->right == NULL );
            return;
        default:
            printf("\nUnsupported token type: Exiting execution\n");
            exit(0);
    }
}

void traverseAbstractSyntaxTree_postFix( ltlNode *node )
{
    switch(node->type){
        case( AND ):
            printf("( ");
            assert( node->left != NULL );
            assert( node->right != NULL );
            traverseAbstractSyntaxTree_postFix( node->left );
            printf("& ");
            traverseAbstractSyntaxTree_postFix( node->right );
            printf(") ");
            return;
        case( OR ):
            printf("( ");
            assert( node->left != NULL );
            assert( node->right != NULL );
            traverseAbstractSyntaxTree_postFix( node->left );
            printf("+ ");
            traverseAbstractSyntaxTree_postFix( node->right );
            printf(") ");
            return;
        case( NOT ):
            printf("~ ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree_postFix( node->left );
            assert( node->right == NULL );
            return;
        case( GLOBALLY ):
            printf("G ");
            //printf("( ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree_postFix( node->left );
            assert( node->right == NULL );
            //printf(") ");
            return;
        case( EVENTUALLY ):
            printf("F ");
            //printf("( ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree_postFix( node->left );
            assert( node->right == NULL );
            //printf(") ");
            return;
        case( NEXT ):
            printf("X ");
            assert( node->left != NULL );
            traverseAbstractSyntaxTree_postFix( node->left );
            assert( node->right == NULL );
            return;
        case( UNTIL ):
            printf("( ");
            assert( node->left != NULL );
            assert( node->right != NULL );
            traverseAbstractSyntaxTree_postFix( node->left );
            printf("U ");
            traverseAbstractSyntaxTree_postFix( node->right );
            printf(") ");
            return;
        case( BOOL ):
            printf("%s ", node->name);
            assert( node->left == NULL );
            assert( node->right == NULL );
            return;
        default:
            printf("\nUnsupported token type: Exiting execution\n");
            exit(0);
    }
}

void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap )
{
    ltlNode *nextNode, *nextToNextNode;
    int serialNumSignal;

    switch( topASTNode->type ){
        case AND:
        case OR:
        case IMPLY:
            populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap );
            populateAigPointerUnitGF( pAigNew, topASTNode->right, vSignal, vAigGFMap );
            return;
        case NOT:
            populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap );
            return;
        case GLOBALLY:
            nextNode = topASTNode->left;
            assert( nextNode->type == EVENTUALLY );
            nextToNextNode = nextNode->left;
            if( nextToNextNode->type == BOOL )
            {
                assert( nextToNextNode->pObj );
                serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
                if( serialNumSignal == -1 )
                {                    
                    Vec_PtrPush( vSignal, nextToNextNode->pObj );
                    serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
                }
                //Vec_PtrPush( vGLOBALLY, topASTNode );
                Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode );
            }
            else
            {
                assert( nextToNextNode->pObj == NULL );
                buildLogicFromLTLNode_combinationalOnly( pAigNew, nextToNextNode );
                serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
                if( serialNumSignal == -1 )
                {
                    Vec_PtrPush( vSignal, nextToNextNode->pObj );
                    serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
                }
                //Vec_PtrPush( vGLOBALLY, topASTNode );
                Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode );
            }
            return;
        case BOOL:
            return;
        default:
            printf("\nINVALID situation: aborting...\n");
            exit(0);
    }
}

Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAigNew, ltlNode *pLtlNode )
{
    Aig_Obj_t *leftAigObj, *rightAigObj;

    if( pLtlNode->pObj != NULL )
        return pLtlNode->pObj;
    else
    {
        assert( pLtlNode->type != BOOL );
        switch( pLtlNode->type ){
            case AND:
                assert( pLtlNode->left ); assert( pLtlNode->right );
                leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
                rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right );
                assert( leftAigObj ); assert( rightAigObj );
                pLtlNode->pObj = Aig_And( pAigNew, leftAigObj, rightAigObj );
                return pLtlNode->pObj;
            case OR:
                assert( pLtlNode->left ); assert( pLtlNode->right );
                leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
                rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right );
                assert( leftAigObj ); assert( rightAigObj );
                pLtlNode->pObj = Aig_Or( pAigNew, leftAigObj, rightAigObj );
                return pLtlNode->pObj;
            case NOT:
                assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); 
                leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
                assert( leftAigObj );
                pLtlNode->pObj = Aig_Not( leftAigObj );
                return pLtlNode->pObj;
            case GLOBALLY:
            case EVENTUALLY:
            case NEXT:
            case UNTIL:
                printf("FORBIDDEN node: ABORTING!!\n");
                exit(0);
            default:
                printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n");
                exit(0);
        }
    }
}

Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode )
{
    Aig_Obj_t *leftAigObj, *rightAigObj;

    if( pLtlNode->pObj != NULL )
        return pLtlNode->pObj;
    else
    {
        assert( pLtlNode->type != BOOL );
        switch( pLtlNode->type ){
            case AND:
                assert( pLtlNode->left ); assert( pLtlNode->right );
                leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
                rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right );
                assert( leftAigObj ); assert( rightAigObj );
                pLtlNode->pObj = Aig_And( pAig, leftAigObj, rightAigObj );
                return pLtlNode->pObj;
            case OR:
                assert( pLtlNode->left ); assert( pLtlNode->right );
                leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
                rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right );
                assert( leftAigObj ); assert( rightAigObj );
                pLtlNode->pObj = Aig_Or( pAig, leftAigObj, rightAigObj );
                return pLtlNode->pObj;
            case NOT:
                assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); 
                leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
                assert( leftAigObj );
                pLtlNode->pObj = Aig_Not( leftAigObj );
                return pLtlNode->pObj;
            case GLOBALLY:
            case EVENTUALLY:
            case NEXT:
            case UNTIL:
                printf("\nAttempting to create circuit with missing AIG pointer in a TEMPORAL node: ABORTING!!\n");
                exit(0);
            default:
                printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n");
                exit(0);
        }
    }
}

int isNonTemporalSubformula( ltlNode *topNode )
{
    switch( topNode->type ){
        case AND:
        case OR:
        case IMPLY:
            return isNonTemporalSubformula( topNode->left) && isNonTemporalSubformula( topNode->right ) ;
        case NOT:
            assert( topNode->right == NULL );
            return isNonTemporalSubformula( topNode->left );
        case BOOL:
            return 1;
        default:
            return 0;
    }
}

int isWellFormed( ltlNode *topNode )
{
    ltlNode *nextNode;

    switch( topNode->type ){
        case AND:
        case OR:
        case IMPLY:
            return isWellFormed( topNode->left) && isWellFormed( topNode->right ) ;
        case NOT:
            assert( topNode->right == NULL );
            return isWellFormed( topNode->left );
        case BOOL:
            return 1;
        case GLOBALLY:
            nextNode = topNode->left;
            assert( topNode->right == NULL );
            if( nextNode->type != EVENTUALLY )
                return 0;
            else
            {
                assert( nextNode->right == NULL );
                return isNonTemporalSubformula( nextNode->left );
            }
        default:
            return 0;
    }
}

int checkBooleanConstant( char *targetName )
{
    if( strcmp( targetName, "true" ) == 0 ) 
        return 1;
    if( strcmp( targetName, "false" ) == 0 )
        return 0;
    return -1;
}

int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode )
{
    char *targetName;
    Abc_Obj_t * pNode;
    int i;
        
    switch( topASTNode->type ){
        case BOOL:
            targetName = topASTNode->name;
            //printf("\nTrying to match name %s\n", targetName);
            if( checkBooleanConstant( targetName ) != -1 )
                return 1;
            Abc_NtkForEachPo( pNtk, pNode, i )
            {
                if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 )
                {
                    //printf("\nVariable name \"%s\" MATCHED\n", targetName);
                    return 1;
                }
            }
            printf("\nVariable name \"%s\" not found in the PO name list\n", targetName);
            return 0;
        case AND:
        case OR:
        case IMPLY:
        case UNTIL:
            assert( topASTNode->left != NULL );
            assert( topASTNode->right != NULL );
            return checkSignalNameExistence( pNtk, topASTNode->left ) && checkSignalNameExistence( pNtk, topASTNode->right );
            
        case NOT:
        case NEXT:
        case GLOBALLY:
        case EVENTUALLY:
            assert( topASTNode->left != NULL );
            assert( topASTNode->right == NULL );
            return checkSignalNameExistence( pNtk, topASTNode->left );
        default:
            printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
            exit(0);
    }
}

void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode )
{
    char *targetName;
    Abc_Obj_t * pNode;
    int i;
    Aig_Obj_t *pObj, *pDriverImage;
    
    switch( topASTNode->type ){
        case BOOL:
            targetName = topASTNode->name;
            if( checkBooleanConstant( targetName ) == 1 )
            {
                topASTNode->pObj = Aig_ManConst1( pAigNew );
                return;
            }
            if( checkBooleanConstant( targetName ) == 0 )
            {
                topASTNode->pObj = Aig_Not(topASTNode->pObj = Aig_ManConst1( pAigNew ));
                return;
            }
            Abc_NtkForEachPo( pNtk, pNode, i )
                if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 )
                {
                    pObj = Aig_ManCo( pAigOld, i );
                    assert( Aig_ObjIsCo( pObj ));
                    pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
                    topASTNode->pObj = pDriverImage;
                    return;
                }
            assert(0);
        case AND:
        case OR:
        case IMPLY:
        case UNTIL:
            assert( topASTNode->left != NULL );
            assert( topASTNode->right != NULL );
            populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left );
            populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->right );
            return;
        case NOT:
        case NEXT:
        case GLOBALLY:
        case EVENTUALLY:
            assert( topASTNode->left != NULL );
            assert( topASTNode->right == NULL );
            populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left );
            return;
        default:
            printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
            exit(0);
    }
}

int checkAllBoolHaveAIGPointer( ltlNode *topASTNode )
{
    
    switch( topASTNode->type ){
        case BOOL:
            if( topASTNode->pObj != NULL )
                return 1;
            else
            {
                printf("\nfaulting PODMANDYO topASTNode->name = %s\n", topASTNode->name);
                return 0;
            }
        case AND:
        case OR:
        case IMPLY:
        case UNTIL:
            assert( topASTNode->left != NULL );
            assert( topASTNode->right != NULL );
            return checkAllBoolHaveAIGPointer( topASTNode->left ) && checkAllBoolHaveAIGPointer( topASTNode->right );
            
        case NOT:
        case NEXT:
        case GLOBALLY:
        case EVENTUALLY:
            assert( topASTNode->left != NULL );
            assert( topASTNode->right == NULL );
            return checkAllBoolHaveAIGPointer( topASTNode->left );
        default:
            printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
            exit(0);
    }
}

void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo )
{
    astNode->pObj = pObjLo;
}
            
Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode )
{
    return astNode->pObj;
}


ABC_NAMESPACE_IMPL_END
