1*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2014 The Android Open Source Project 2*795d594fSAndroid Build Coastguard Worker# 3*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*795d594fSAndroid Build Coastguard Worker# 7*795d594fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*795d594fSAndroid Build Coastguard Worker# 9*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*795d594fSAndroid Build Coastguard Worker# limitations under the License. 14*795d594fSAndroid Build Coastguard Worker 15*795d594fSAndroid Build Coastguard Workerfrom common.logger import Logger 16*795d594fSAndroid Build Coastguard Workerfrom file_format.checker.struct import TestExpression, TestStatement 17*795d594fSAndroid Build Coastguard Worker 18*795d594fSAndroid Build Coastguard Worker# Required for eval. 19*795d594fSAndroid Build Coastguard Workerimport os 20*795d594fSAndroid Build Coastguard Workerimport re 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Workerdef head_and_tail(list): 24*795d594fSAndroid Build Coastguard Worker return list[0], list[1:] 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Workerdef split_at_separators(expressions): 28*795d594fSAndroid Build Coastguard Worker """ Splits a list of TestExpressions at separators. """ 29*795d594fSAndroid Build Coastguard Worker split_expressions = [] 30*795d594fSAndroid Build Coastguard Worker word_start = 0 31*795d594fSAndroid Build Coastguard Worker for index, expression in enumerate(expressions): 32*795d594fSAndroid Build Coastguard Worker if expression.variant == TestExpression.Variant.SEPARATOR: 33*795d594fSAndroid Build Coastguard Worker split_expressions.append(expressions[word_start:index]) 34*795d594fSAndroid Build Coastguard Worker word_start = index + 1 35*795d594fSAndroid Build Coastguard Worker split_expressions.append(expressions[word_start:]) 36*795d594fSAndroid Build Coastguard Worker return split_expressions 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker 39*795d594fSAndroid Build Coastguard Workerdef get_variable(name, variables, pos): 40*795d594fSAndroid Build Coastguard Worker if name in variables: 41*795d594fSAndroid Build Coastguard Worker return variables[name] 42*795d594fSAndroid Build Coastguard Worker else: 43*795d594fSAndroid Build Coastguard Worker Logger.test_failed('Missing definition of variable "{}"'.format(name), pos, variables) 44*795d594fSAndroid Build Coastguard Worker 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Workerdef set_variable(name, value, variables, pos): 47*795d594fSAndroid Build Coastguard Worker if name not in variables: 48*795d594fSAndroid Build Coastguard Worker return variables.copy_with(name, value) 49*795d594fSAndroid Build Coastguard Worker else: 50*795d594fSAndroid Build Coastguard Worker Logger.test_failed('Multiple definitions of variable "{}"'.format(name), pos, variables) 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Worker 53*795d594fSAndroid Build Coastguard Workerdef match_words(checker_word, string_word, variables, pos): 54*795d594fSAndroid Build Coastguard Worker """ Attempts to match a list of TestExpressions against a string. 55*795d594fSAndroid Build Coastguard Worker Returns updated variable dictionary if successful and None otherwise. 56*795d594fSAndroid Build Coastguard Worker """ 57*795d594fSAndroid Build Coastguard Worker for expression in checker_word: 58*795d594fSAndroid Build Coastguard Worker # If `expression` is a variable reference, replace it with the value. 59*795d594fSAndroid Build Coastguard Worker if expression.variant == TestExpression.Variant.VAR_REF: 60*795d594fSAndroid Build Coastguard Worker pattern = re.escape(get_variable(expression.name, variables, pos)) 61*795d594fSAndroid Build Coastguard Worker else: 62*795d594fSAndroid Build Coastguard Worker pattern = expression.text 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker try: 65*795d594fSAndroid Build Coastguard Worker pattern = re.compile(pattern) 66*795d594fSAndroid Build Coastguard Worker except re.error as e: 67*795d594fSAndroid Build Coastguard Worker message = ('Invalid regex "{}" at {}:{},' 68*795d594fSAndroid Build Coastguard Worker ' compiling fails with error: {}'.format(pattern, pos.filename, pos.line_no, e)) 69*795d594fSAndroid Build Coastguard Worker raise RuntimeError(message) 70*795d594fSAndroid Build Coastguard Worker 71*795d594fSAndroid Build Coastguard Worker # Match the expression's regex pattern against the remainder of the word. 72*795d594fSAndroid Build Coastguard Worker # Note: re.match will succeed only if matched from the beginning. 73*795d594fSAndroid Build Coastguard Worker match = re.match(pattern, string_word) 74*795d594fSAndroid Build Coastguard Worker if not match: 75*795d594fSAndroid Build Coastguard Worker return None 76*795d594fSAndroid Build Coastguard Worker 77*795d594fSAndroid Build Coastguard Worker # If `expression` was a variable definition, set the variable's value. 78*795d594fSAndroid Build Coastguard Worker if expression.variant == TestExpression.Variant.VAR_DEF: 79*795d594fSAndroid Build Coastguard Worker variables = set_variable(expression.name, string_word[:match.end()], variables, pos) 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker # Move cursor by deleting the matched characters. 82*795d594fSAndroid Build Coastguard Worker string_word = string_word[match.end():] 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker # Make sure the entire word matched, i.e. `stringWord` is empty. 85*795d594fSAndroid Build Coastguard Worker if string_word: 86*795d594fSAndroid Build Coastguard Worker return None 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker return variables 89*795d594fSAndroid Build Coastguard Worker 90*795d594fSAndroid Build Coastguard Worker 91*795d594fSAndroid Build Coastguard Workerdef match_lines(checker_line, string_line, variables): 92*795d594fSAndroid Build Coastguard Worker """ Attempts to match a CHECK line against a string. Returns variable state 93*795d594fSAndroid Build Coastguard Worker after the match if successful and None otherwise. 94*795d594fSAndroid Build Coastguard Worker """ 95*795d594fSAndroid Build Coastguard Worker assert checker_line.variant != TestStatement.Variant.EVAL 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker checker_words = split_at_separators(checker_line.expressions) 98*795d594fSAndroid Build Coastguard Worker string_words = string_line.split() 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker while checker_words: 101*795d594fSAndroid Build Coastguard Worker # Get the next run of TestExpressions which must match one string word. 102*795d594fSAndroid Build Coastguard Worker checker_word, checker_words = head_and_tail(checker_words) 103*795d594fSAndroid Build Coastguard Worker 104*795d594fSAndroid Build Coastguard Worker # Keep reading words until a match is found. 105*795d594fSAndroid Build Coastguard Worker word_matched = False 106*795d594fSAndroid Build Coastguard Worker while string_words: 107*795d594fSAndroid Build Coastguard Worker string_word, string_words = head_and_tail(string_words) 108*795d594fSAndroid Build Coastguard Worker new_variables = match_words(checker_word, string_word, variables, checker_line) 109*795d594fSAndroid Build Coastguard Worker if new_variables is not None: 110*795d594fSAndroid Build Coastguard Worker word_matched = True 111*795d594fSAndroid Build Coastguard Worker variables = new_variables 112*795d594fSAndroid Build Coastguard Worker break 113*795d594fSAndroid Build Coastguard Worker if not word_matched: 114*795d594fSAndroid Build Coastguard Worker return None 115*795d594fSAndroid Build Coastguard Worker 116*795d594fSAndroid Build Coastguard Worker # All TestExpressions matched. Return new variable state. 117*795d594fSAndroid Build Coastguard Worker return variables 118*795d594fSAndroid Build Coastguard Worker 119*795d594fSAndroid Build Coastguard Worker 120*795d594fSAndroid Build Coastguard Workerdef get_eval_text(expression, variables, pos): 121*795d594fSAndroid Build Coastguard Worker if expression.variant == TestExpression.Variant.PLAIN_TEXT: 122*795d594fSAndroid Build Coastguard Worker return expression.text 123*795d594fSAndroid Build Coastguard Worker else: 124*795d594fSAndroid Build Coastguard Worker assert expression.variant == TestExpression.Variant.VAR_REF 125*795d594fSAndroid Build Coastguard Worker return get_variable(expression.name, variables, pos) 126*795d594fSAndroid Build Coastguard Worker 127*795d594fSAndroid Build Coastguard Worker 128*795d594fSAndroid Build Coastguard Workerdef evaluate_line(checker_line, variables): 129*795d594fSAndroid Build Coastguard Worker assert checker_line.is_eval_content_statement() 130*795d594fSAndroid Build Coastguard Worker # Required for eval. 131*795d594fSAndroid Build Coastguard Worker hasIsaFeature = lambda feature: variables["ISA_FEATURES"].get(feature, False) 132*795d594fSAndroid Build Coastguard Worker readBarrierType = lambda barrier_type: variables["READ_BARRIER_TYPE"] == barrier_type 133*795d594fSAndroid Build Coastguard Worker eval_string = "".join(get_eval_text(expr, 134*795d594fSAndroid Build Coastguard Worker variables, 135*795d594fSAndroid Build Coastguard Worker checker_line) for expr in checker_line.expressions) 136*795d594fSAndroid Build Coastguard Worker return eval(eval_string) 137