Example #1
0
 def popContext(self):
     if (len(self.stack) <= 0):
         errPrint('\nBehram Error.  Empty type context stack.  Cannot pop\n');
         assert(False);
     self.stack.pop();
     self.funcStack.pop();
     self.currentFunctionNode = None;
Example #2
0
 def checkValid(self):
     '''
     Should only call when trying to use (not set) internal data of
     object.  Just ensures that actual data for different types of
     errors has actually been set before being used.
     '''
     if (not self.valid):
         errPrint('\nValidity check for FuncCallArgMatchError object failed.\n');
         assert(False);
Example #3
0
    def getOtherEndpointName(self):
        if (self.currentEndpointName == None) or (self.endpoint1 == None) or (self.endpoint2 == None):
            errMsg = '\nBehram error: should not call getOtherEndpointName in ';
            errMsg += 'astTypeCheckStack.py unless we are currently in an endpoint ';
            errMsg += 'and all endpoints are defined.\n';
            errPrint(errMsg);
            assert(False);

        if (self.currentEndpointName != self.endpoint1):
            return self.endpoint1;
        return self.endpoint2;
Example #4
0
    def addFuncIdentifier(self,functionName,functionType,functionArgTypes,astNode,lineNum=None):
        '''
        @param {string} functionName: name of function

        @param{list of type dicts} functionType --- The return type of
        this function.  We're using a list to support returning
        tuples.  Each element of the list is the return type of that
        element of the tuple.
        

        @param {list} functionArgTypes: ordered (from left to right)
        list of types for function arguments.
        
        @param {int} lineNum: line number that function was declared on.

        @returns {None or TyepCheckError} -- None if nothing is wrong
        with trace, TypeCheckError otherwise.
        
        '''
        if len(self.funcStack) <= 1:
            errMsg = '\nBehram Error.  Cannot insert into type ';
            errMsg += 'check stack because stack is empty.\n';
            errPrint(errMsg);
            assert(False);


        #if it's a msgSend function or msgReceive function, then
        #notify the traceLineManager that a msgSend or msgreceive
        #function has been defined;
        currentEndpointName = self.currentEndpointName;
        if (currentEndpointName == None):
            errMsg = '\nBehram error: should ony be adding a ';
            errMsg += 'func identifier in the body of an endpoint section.\n';
            errPrint(errMsg);
            assert(False);

        traceError = None;

        

        if astNode.label == AST_MESSAGE_SEND_SEQUENCE_FUNCTION:
            traceError = self.traceManager.addMsgSendFunction(astNode,currentEndpointName);
        elif astNode.label == AST_MESSAGE_RECEIVE_SEQUENCE_FUNCTION:
            traceError = self.traceManager.addMsgRecvFunction(astNode, currentEndpointName);

        if (traceError != None):
            return traceError;

        #add the function identifier itself to function context.
        traceError = self.funcStack[-1].addFuncIdentifier(
            functionName,functionType,functionArgTypes,astNode,lineNum);
        
        return traceError;
Example #5
0
 def addIdentifier(self,identifierName,identifierType,controlledBy,astNode,lineNum = None):
     '''
     @param {String} controlledBy --- name of the endpoint that is
     authoritative for this variable if it's a shared variable.
     None if it's not a shared variable or if no one is
     authoritative for it.
     '''
     
     if(len(self.stack) <= 1):
         errPrint('\nBehram Error.  Cannot insert into type check stack because stack is empty.\n');
         assert(False);
     self.stack[-1].addIdentifier(identifierName,identifierType,controlledBy,astNode,lineNum);
Example #6
0
    def addCurrentFunctionNode(self,node):
        '''
        Sets the current function we're in so that can check return
        types when we get to them.
        '''
        if ((node.label != AST_PUBLIC_FUNCTION) and (node.label != AST_PRIVATE_FUNCTION) and
            (node.label != AST_ONCREATE_FUNCTION) and
            (node.label != AST_MESSAGE_SEND_SEQUENCE_FUNCTION ) and
            (node.label != AST_MESSAGE_RECEIVE_SEQUENCE_FUNCTION) and
            (node.label != AST_ONCOMPLETE_FUNCTION)):
            
            errMsg = '\nBehram error: adding internal or public node with incorrect ';
            errMsg += 'type.\n';
            errPrint(errMsg);
            assert(False);

        self.currentFunctionNode = node;
Example #7
0
 def setArgLengthMismatchError(self,numArgsExpected,numArgsProvided):
     '''
     @param {int} numArgsExpected
     @param {int} numArgsProvided
     
     Called to set the number of arguments expected vs the number
     provided when have an argument length mismatch error.
     '''
     if (self.errorType != FUNC_CALL_ARG_MATCH_ERROR_NUM_ARGS_MISMATCH):
         errMsg = '\nBehram error: should not be setting a num arguments '
         errMsg += 'mismatch error if have declared the error type as a ';
         errMsg += 'type mismatch error.';
         errMsg += '\n';
         errPrint(errMsg);
         assert(False);
         
     self.expected = numArgsExpected;
     self.provided = numArgsProvided;
     self.valid = True;
Example #8
0
    def addIdentifier(self,identifierName,identifierType,controlledBy,astNode,lineNum):
        '''
        @param {String} identifierName
        @param {String} identifierType
        
        If identifier already exists in this context, throw an error.
        Cannot have re-definition of existing type.
        '''
        exists,ctrldBy  = self.getIdentifierType(identifierName);
        if (exists != None):
            #FIXME: this should turn into a more formal error-reporting system.
            errPrint('\nError, overwriting existing type with name ' + identifierName + '\n');
            assert(False);

        prevDecl,ctrldBy = self.getIdentifierType(identifierName);
        if (prevDecl != None):
            errMsg =  '\nError.  You already declared a variable named ';
            errMsg += '"' + identifierName + '".  You cannot declare another.\n';
            nodes = [astNode,prevDecl.astNode];
            return TypeCheckError(nodes,errMsg);

        self.dict[identifierName] = ContextElement(identifierType,controlledBy,astNode,lineNum);
Example #9
0
    def checkMsgSendFunction(self,msgSendFuncAstNode,endpointName):
        '''
        @returns {None or TypeCheckError} -- Returns TypeCheckError if
        any non-first part of the trace line uses the msgSend
        function.  Returns None to indicate no error.
        '''
        funcName = msgSendFuncAstNode.children[1].value;

        if (len(self.stringifiedTraceItems) == 0):
            errMsg = '\nBehram error: you should never have a case where ';
            errMsg += 'self.stringifiedTraceItems is empty.\n';
            errPrint(errMsg);
            assert(False);

        stringifiedFuncName = endpointFuncNameToString(endpointName,funcName);
            
        if (self.stringifiedTraceItems[0] == stringifiedFuncName):
            self.definedUndefinedList[0] += 1;
            self.usedNodes[0] = msgSendFuncAstNode;


        #start at 1 so that skip over msgSendFunction that initiates trace.
        for s in range(1,len(self.stringifiedTraceItems)):
            if (self.stringifiedTraceItems[s] == stringifiedFuncName):
                errMsg = '\nMessage send error: You are using a message send ';
                errMsg += 'function named "' + funcName + '", in the middle ';
                errMsg += 'of a sequence of messages.  You cannot use a message ';
                errMsg += 'send function in the middle of a sequence of messages.  '
                errMsg += 'This is because message send functions do not take any ';
                errMsg += 'input messages.  ';
                errMsg += 'You should use a message receive function instead or ';
                errMsg += 'change "' + funcName + '" to a message receive function.\n';

                nodes = [self.traceLineAst,msgSendFuncAstNode];
                return TypeCheckError(nodes,errMsg);

            
        return None;
Example #10
0
    def addMatchError(self,argNo,expectedType,providedType):
        '''
        @param {int} argNo
        @param {String} expectedType
        @param {String} providedType
        '''
        
        if (self.errorType != FUNC_CALL_ARG_MATCH_ERROR_TYPE_MISMATCH):
            errMsg = '\nBehram error: should not add a specific argument ';
            errMsg += 'type mismatch error when already specified that ';
            errMsg += 'error was a length mismatch.\n';
            errPrint(errMsg);
            assert(False);

        #first error added
        if (self.argNos == None):
            self.argNos = [];
            self.expected = [];
            self.provided = [];

        self.argNos.append(argNo);
        self.expected.append(expectedType);
        self.provided.append(providedType);
        self.valid = True;
Example #11
0
    def checkReturnStatement(self,returnNode,check_type_mismatch_func):
        '''
        @param {function} check_type_mismatch_func ... should just be
        typeCheck.checkTypeMismatch.
        '''
        if (returnNode.label != AST_RETURN_STATEMENT):
            errMsg = '\nBehram error: trying to check a ';
            errMsg += 'return statement without a return statement node.\n';
            errPrint(errMsg);
            assert(False);

            
        if self.currentFunctionNode == None:
            errMsg = '\nBehram error: any return statement should have a ';
            errMsg += 'currentFunctionNode to compare to.\n';
            print(errMsg);
            assert(False);


        return_tuple_node = returnNode.children[0]
        # list of the types that we're actually returning
        return_type_list = []
        for single_node in return_tuple_node.children:

            # takes care of case where we are returning a function
            # call
            if ((single_node.label == AST_FUNCTION_CALL) and
                (not is_wildcard_type(single_node.type))):
                func_returned_type_array = get_type_array_from_func_call_returned_tuple_type(
                    single_node.type)
                for ind_tuple_return_type in func_returned_type_array:
                    return_type_list.append(ind_tuple_return_type)
            else:
                return_type_list.append(single_node.type)
            
        returnStatementType = returnNode.children[0].type;
        if ((self.currentFunctionNode.label == AST_MESSAGE_SEND_SEQUENCE_FUNCTION) or
            (self.currentFunctionNode.label == AST_MESSAGE_RECEIVE_SEQUENCE_FUNCTION)):

            if len(return_type) > 0:
                err_msg = 'Error.  Cannot return a value from a sequence function.'
                nodes= [returnNode];
                return TypeCheckError(nodes,err_msg);

            # no error because message sequences are not declared to
            # return anything and this return statement does not.
            return None

        # check public and privates for return statement...
        function_returns_type_node = self.currentFunctionNode.children[1];
        # the declared return type of this function
        function_returns_type_list = []
        for single_type in function_returns_type_node.children:
            function_returns_type_list.append(single_type.type)

        funcName = self.currentFunctionNode.children[0].value;

        if len(function_returns_type_list) != len(return_type_list):
            err_msg = 'Error.  ' + funcName + ' expects to return '
            err_msg += str(len(function_returns_type_list)) + ' arguments.  '
            err_msg += 'Instead, you returned ' + str(len(return_type_list))
            err_msg += ' arguments.'
            err_nodes = [returnNode, function_returns_type_node]
            return TypeCheckError(err_nodes,err_msg)

        
        for return_index in range(0,len(return_type_list)):
            
            declared_return_type = function_returns_type_list[return_index]
            actual_return_type = return_type_list[return_index]

            if check_type_mismatch_func(
                returnNode,declared_return_type,actual_return_type,self,''):

                err_msg = 'Incorrect return type in ' + funcName + '.  '
                if len(return_type_list) == 1:
                    err_msg += 'Expected type '
                    err_msg += dict_type_to_str(declared_return_type)
                    err_msg += ', but actually returned type '
                    err_msg += dict_type_to_str(actual_return_type)
                    err_msg += '.'
                else:
                    err_msg += 'The ' + str(return_index + 1) + ' tuple return '
                    err_msg += 'element expected a type of '
                    err_msg += dict_type_to_str(declared_return_type)
                    err_msg += ', but actually returned type of '
                    err_msg += dict_type_to_str(actual_return_type)
                    err_msg += '.'

                err_nodes = [returnNode, function_returns_type_node]
                return TypeCheckError(err_nodes, err_msg)

        return None;