# Copyright 2016 by Raytheon BBN Technologies Corp.  All Rights Reserved.

from pyqgl2.ast_util import NodeError
from pyqgl2.inline import QubitPlaceholder

import QGL.Channels

def QGL2check(value, required_type, fp_name, fun_name, fname, lineno, colno):
    """
    Runtime check of an actual parameter

    Check that the given value is of the required type, and
    if it is not then print out an error message mentioning the
    name of the formal parameter to which that value was intended
    to be assigned, the name of the function being called, and the
    file name, line number, and column number of the call in the
    source code.
    """

    # TODO: should be able to tolerate actual Qubit values,
    # not just references to QubitPlaceholder instances

    assert isinstance(required_type, str), 'required_type must be a str'
    assert isinstance(fp_name, str), 'fp_name must be a str'
    assert isinstance(fun_name, str), 'fun_name must be a str'
    assert isinstance(fname, str), 'fname must be a str'
    assert isinstance(lineno, int), 'lineno must be an int'
    assert isinstance(colno, int), 'colno must be a int'

    if required_type == 'qbit':
        if ((not isinstance(value, QubitPlaceholder)) and
                (not isinstance(value, QGL.Channels.Qubit))):
            print(('%s:%d:%d: error: ' +
                'param [%s] of func [%s] must be qbit') %
                    (fname, lineno, colno, fp_name, fun_name))
            NodeError.MAX_ERR_LEVEL = NodeError.NODE_ERROR_ERROR
            return False

    elif required_type == 'qbit_list':
        if ((not isinstance(value, list)) and
                (not isinstance(value, set)) and
                (not isinstance(value, tuple))):
            print(('%s:%d:%d: error: ' +
                'param [%s] of func [%s] must be qbit_list') %
                    (fname, lineno, colno, fp_name, fun_name))
            NodeError.MAX_ERR_LEVEL = NodeError.NODE_ERROR_ERROR
            return False

        for element in value:
            # this might be too persnickety, but right now
            # we must have a QubitPlaceholder because we will
            # require the use_name() method be present.
            #
            if not isinstance(element, QubitPlaceholder):
                print(('%s:%d:%d: error: ' +
                    'each elem of param [%s] of func [%s] must be a qbit') %
                        (fname, lineno, colno, fp_name, fun_name))
                NodeError.MAX_ERR_LEVEL = NodeError.NODE_ERROR_ERROR
                return False

    elif required_type == 'classical':
        if isinstance(value, QubitPlaceholder):
            print(('%s:%d:%d: error: ' +
                'param [%s] of func [%s] must be classical') %
                    (fname, lineno, colno, fp_name, fun_name))
            NodeError.MAX_ERR_LEVEL = NodeError.NODE_ERROR_ERROR
            return False

    return True

@@ -1171,34 +1171,32 @@
 it':%0A        if 
-((
 not isinstance(v
@@ -1222,74 +1222,8 @@
 der)
-) and%0A                (not isinstance(value, QGL.Channels.Qubit)))
 :%0A  

insist that qbits are QubitPlaceholder instances