All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opalj.ai.ConsoleEvaluationTracer.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License:
 * Copyright (c) 2009 - 2017
 * Software Technology Group
 * Department of Computer Science
 * Technische Universität Darmstadt
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package org.opalj
package ai

import org.opalj.collection.immutable.{Chain ⇒ List}
import org.opalj.br.Code
import org.opalj.br.instructions.Instruction

/**
 * A tracer that primarily prints out the evaluation order of the instructions on the
 * console. This tracer is particularly useful to understand the handling of JSR/RET
 * instructions.
 *
 * If you want to reuse this tracer to trace evaluations of different methods
 * you should call the `reset` method between two calls.
 *
 * ==Thread Safety==
 * This tracer has internal state that is dependent on the state of the evaluation.
 * Hence, '''this class is not thread safe and a new `AI` instance should be used per
 * method that is analyzed'''.
 *
 * @author Michael Eichberg
 */
trait ConsoleEvaluationTracer extends AITracer {

    import Console._

    private[this] var indent = 0
    private[this] def printIndent(): Unit = { (0 until indent) foreach (i ⇒ print("\t")) }

    def reset(): Unit = { indent = 0 }

    override def instructionEvalution(
        domain: Domain
    )(
        pc:          PC,
        instruction: Instruction,
        operands:    domain.Operands,
        locals:      domain.Locals
    ): Unit = {
        print(pc+" ")
    }

    override def continuingInterpretation(
        code:   Code,
        domain: Domain
    )(
        initialWorkList:                  List[PC],
        alreadyEvaluated:                 List[PC],
        operandsArray:                    domain.OperandsArray,
        localsArray:                      domain.LocalsArray,
        memoryLayoutBeforeSubroutineCall: List[(PC, domain.OperandsArray, domain.LocalsArray)]
    ): Unit = {
        /*EMPTY*/
    }

    override def rescheduled(
        domain: Domain
    )(
        sourcePC:                 PC,
        targetPC:                 PC,
        isExceptionalControlFlow: Boolean,
        worklist:                 List[PC]
    ): Unit = { /*EMPTY*/ }

    override def flow(
        domain: Domain
    )(
        currentPC:                PC,
        targetPC:                 PC,
        isExceptionalControlFlow: Boolean
    ): Unit = { /*EMPTY*/ }

    override def noFlow(domain: Domain)(currentPC: PC, targetPC: PC): Unit = { /*EMPTY*/ }

    override def join(
        domain: Domain
    )(
        pc:            PC,
        thisOperands:  domain.Operands,
        thisLocals:    domain.Locals,
        otherOperands: domain.Operands,
        otherLocals:   domain.Locals,
        result:        Update[(domain.Operands, domain.Locals)]
    ): Unit = { /*EMPTY*/ }

    override def abruptMethodExecution(
        domain: Domain
    )(
        pc:        Int,
        exception: domain.ExceptionValue
    ): Unit = { /*EMPTY*/ }

    override def jumpToSubroutine(
        domain: Domain
    )(
        pc: PC, target: PC, nestingLevel: Int
    ): Unit = {
        println
        printIndent
        print(BOLD+"↳\t︎"+RESET)
        indent += 1
    }

    override def returnFromSubroutine(
        domain: Domain
    )(
        pc:                     PC,
        returnAddress:          PC,
        subroutineInstructions: List[PC]
    ): Unit = {
        indent -= 1

        println(BOLD+"✓"+"(Resetting: "+subroutineInstructions.mkString(", ")+")"+RESET)
        printIndent
    }

    def abruptSubroutineTermination(
        domain: Domain
    )(
        sourcePC: PC, targetPC: PC, jumpToSubroutineId: Int,
        terminatedSubroutinesCount: Int,
        oldWorklist:                List[PC],
        newWorklist:                List[PC]
    ): Unit = { /* EMPTY */ }

    override def ret(
        domain: Domain
    )(
        pc:            PC,
        returnAddress: PC,
        oldWorklist:   List[PC],
        newWorklist:   List[PC]
    ): Unit = { /*EMPTY*/ }

    override def establishedConstraint(
        domain: Domain
    )(
        pc:          PC,
        effectivePC: PC,
        operands:    domain.Operands,
        locals:      domain.Locals,
        newOperands: domain.Operands,
        newLocals:   domain.Locals
    ): Unit = { /*EMPTY*/ }

    override def result(result: AIResult): Unit = { /*EMPTY*/ }

    override def domainMessage(
        domain: Domain,
        source: Class[_], typeID: String,
        pc: Option[PC], message: ⇒ String
    ): Unit = { /*EMPTY*/ }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy