1e5c31af7Sopenharmony_ci#!/usr/bin/python3 2e5c31af7Sopenharmony_ci 3e5c31af7Sopenharmony_ci# Copyright 2022-2024 The Khronos Group Inc. 4e5c31af7Sopenharmony_ci# Copyright 2003-2019 Paul McGuire 5e5c31af7Sopenharmony_ci# SPDX-License-Identifier: MIT 6e5c31af7Sopenharmony_ci 7e5c31af7Sopenharmony_ci# apirequirements.py - parse 'depends' expressions in API XML 8e5c31af7Sopenharmony_ci# Supported methods: 9e5c31af7Sopenharmony_ci# dependency - the expression string 10e5c31af7Sopenharmony_ci# 11e5c31af7Sopenharmony_ci# evaluateDependency(dependency, isSupported) evaluates the expression, 12e5c31af7Sopenharmony_ci# returning a boolean result. isSupported takes an extension or version name 13e5c31af7Sopenharmony_ci# string and returns a boolean. 14e5c31af7Sopenharmony_ci# 15e5c31af7Sopenharmony_ci# dependencyLanguage(dependency) returns an English string equivalent 16e5c31af7Sopenharmony_ci# to the expression, suitable for header file comments. 17e5c31af7Sopenharmony_ci# 18e5c31af7Sopenharmony_ci# dependencyNames(dependency) returns a set of the extension and 19e5c31af7Sopenharmony_ci# version names in the expression. 20e5c31af7Sopenharmony_ci# 21e5c31af7Sopenharmony_ci# dependencyMarkup(dependency) returns a string containing asciidoctor 22e5c31af7Sopenharmony_ci# markup for English equivalent to the expression, suitable for extension 23e5c31af7Sopenharmony_ci# appendices. 24e5c31af7Sopenharmony_ci# 25e5c31af7Sopenharmony_ci# All may throw a ParseException if the expression cannot be parsed or is 26e5c31af7Sopenharmony_ci# not completely consumed by parsing. 27e5c31af7Sopenharmony_ci 28e5c31af7Sopenharmony_ci# Supported expressions at present: 29e5c31af7Sopenharmony_ci# - extension names 30e5c31af7Sopenharmony_ci# - '+' as AND connector 31e5c31af7Sopenharmony_ci# - ',' as OR connector 32e5c31af7Sopenharmony_ci# - parenthesization for grouping 33e5c31af7Sopenharmony_ci 34e5c31af7Sopenharmony_ci# Based on https://github.com/pyparsing/pyparsing/blob/master/examples/fourFn.py 35e5c31af7Sopenharmony_ci 36e5c31af7Sopenharmony_cifrom pyparsing import ( 37e5c31af7Sopenharmony_ci Literal, 38e5c31af7Sopenharmony_ci Word, 39e5c31af7Sopenharmony_ci Group, 40e5c31af7Sopenharmony_ci Forward, 41e5c31af7Sopenharmony_ci alphas, 42e5c31af7Sopenharmony_ci alphanums, 43e5c31af7Sopenharmony_ci Regex, 44e5c31af7Sopenharmony_ci ParseException, 45e5c31af7Sopenharmony_ci CaselessKeyword, 46e5c31af7Sopenharmony_ci Suppress, 47e5c31af7Sopenharmony_ci delimitedList, 48e5c31af7Sopenharmony_ci infixNotation, 49e5c31af7Sopenharmony_ci) 50e5c31af7Sopenharmony_ciimport math 51e5c31af7Sopenharmony_ciimport operator 52e5c31af7Sopenharmony_ciimport pyparsing as pp 53e5c31af7Sopenharmony_ciimport re 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_cifrom apiconventions import APIConventions as APIConventions 56e5c31af7Sopenharmony_ciconventions = APIConventions() 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_cidef markupPassthrough(name): 59e5c31af7Sopenharmony_ci """Pass a name (leaf or operator) through without applying markup""" 60e5c31af7Sopenharmony_ci return name 61e5c31af7Sopenharmony_ci 62e5c31af7Sopenharmony_cidef leafMarkupAsciidoc(name): 63e5c31af7Sopenharmony_ci """Markup a leaf name as an asciidoc link to an API version or extension 64e5c31af7Sopenharmony_ci anchor. 65e5c31af7Sopenharmony_ci 66e5c31af7Sopenharmony_ci - name - version or extension name""" 67e5c31af7Sopenharmony_ci 68e5c31af7Sopenharmony_ci return conventions.formatVersionOrExtension(name) 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_cidef leafMarkupC(name): 71e5c31af7Sopenharmony_ci """Markup a leaf name as a C expression, using conventions of the 72e5c31af7Sopenharmony_ci Vulkan Validation Layers 73e5c31af7Sopenharmony_ci 74e5c31af7Sopenharmony_ci - name - version or extension name""" 75e5c31af7Sopenharmony_ci 76e5c31af7Sopenharmony_ci (apivariant, major, minor) = apiVersionNameMatch(name) 77e5c31af7Sopenharmony_ci 78e5c31af7Sopenharmony_ci if apivariant is not None: 79e5c31af7Sopenharmony_ci return name 80e5c31af7Sopenharmony_ci else: 81e5c31af7Sopenharmony_ci return f'ext.{name}' 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ciopMarkupAsciidocMap = { '+' : 'and', ',' : 'or' } 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_cidef opMarkupAsciidoc(op): 86e5c31af7Sopenharmony_ci """Markup a operator as an asciidoc spec markup equivalent 87e5c31af7Sopenharmony_ci 88e5c31af7Sopenharmony_ci - op - operator ('+' or ',')""" 89e5c31af7Sopenharmony_ci 90e5c31af7Sopenharmony_ci return opMarkupAsciidocMap[op] 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ciopMarkupCMap = { '+' : '&&', ',' : '||' } 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_cidef opMarkupC(op): 95e5c31af7Sopenharmony_ci """Markup a operator as an C language equivalent 96e5c31af7Sopenharmony_ci 97e5c31af7Sopenharmony_ci - op - operator ('+' or ',')""" 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_ci return opMarkupCMap[op] 100e5c31af7Sopenharmony_ci 101e5c31af7Sopenharmony_ci 102e5c31af7Sopenharmony_ci# Unfortunately global to be used in pyparsing 103e5c31af7Sopenharmony_ciexprStack = [] 104e5c31af7Sopenharmony_ci 105e5c31af7Sopenharmony_cidef push_first(toks): 106e5c31af7Sopenharmony_ci """Push a token on the global stack 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci - toks - first element is the token to push""" 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ci exprStack.append(toks[0]) 111e5c31af7Sopenharmony_ci 112e5c31af7Sopenharmony_ci# An identifier (version or extension name) 113e5c31af7Sopenharmony_cidependencyIdent = Word(alphanums + '_') 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci# Infix expression for depends expressions 116e5c31af7Sopenharmony_cidependencyExpr = pp.infixNotation(dependencyIdent, 117e5c31af7Sopenharmony_ci [ (pp.oneOf(', +'), 2, pp.opAssoc.LEFT), ]) 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci# BNF grammar for depends expressions 120e5c31af7Sopenharmony_ci_bnf = None 121e5c31af7Sopenharmony_cidef dependencyBNF(): 122e5c31af7Sopenharmony_ci """ 123e5c31af7Sopenharmony_ci boolop :: '+' | ',' 124e5c31af7Sopenharmony_ci extname :: Char(alphas) 125e5c31af7Sopenharmony_ci atom :: extname | '(' expr ')' 126e5c31af7Sopenharmony_ci expr :: atom [ boolop atom ]* 127e5c31af7Sopenharmony_ci """ 128e5c31af7Sopenharmony_ci global _bnf 129e5c31af7Sopenharmony_ci if _bnf is None: 130e5c31af7Sopenharmony_ci and_, or_ = map(Literal, '+,') 131e5c31af7Sopenharmony_ci lpar, rpar = map(Suppress, '()') 132e5c31af7Sopenharmony_ci boolop = and_ | or_ 133e5c31af7Sopenharmony_ci 134e5c31af7Sopenharmony_ci expr = Forward() 135e5c31af7Sopenharmony_ci expr_list = delimitedList(Group(expr)) 136e5c31af7Sopenharmony_ci atom = ( 137e5c31af7Sopenharmony_ci boolop[...] 138e5c31af7Sopenharmony_ci + ( 139e5c31af7Sopenharmony_ci (dependencyIdent).setParseAction(push_first) 140e5c31af7Sopenharmony_ci | Group(lpar + expr + rpar) 141e5c31af7Sopenharmony_ci ) 142e5c31af7Sopenharmony_ci ) 143e5c31af7Sopenharmony_ci 144e5c31af7Sopenharmony_ci expr <<= atom + (boolop + atom).setParseAction(push_first)[...] 145e5c31af7Sopenharmony_ci _bnf = expr 146e5c31af7Sopenharmony_ci return _bnf 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci# map operator symbols to corresponding arithmetic operations 150e5c31af7Sopenharmony_ci_opn = { 151e5c31af7Sopenharmony_ci '+': operator.and_, 152e5c31af7Sopenharmony_ci ',': operator.or_, 153e5c31af7Sopenharmony_ci} 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_cidef evaluateStack(stack, isSupported): 156e5c31af7Sopenharmony_ci """Evaluate an expression stack, returning a boolean result. 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci - stack - the stack 159e5c31af7Sopenharmony_ci - isSupported - function taking a version or extension name string and 160e5c31af7Sopenharmony_ci returning True or False if that name is supported or not.""" 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci op, num_args = stack.pop(), 0 163e5c31af7Sopenharmony_ci if isinstance(op, tuple): 164e5c31af7Sopenharmony_ci op, num_args = op 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci if op in '+,': 167e5c31af7Sopenharmony_ci # Note: operands are pushed onto the stack in reverse order 168e5c31af7Sopenharmony_ci op2 = evaluateStack(stack, isSupported) 169e5c31af7Sopenharmony_ci op1 = evaluateStack(stack, isSupported) 170e5c31af7Sopenharmony_ci return _opn[op](op1, op2) 171e5c31af7Sopenharmony_ci elif op[0].isalpha(): 172e5c31af7Sopenharmony_ci return isSupported(op) 173e5c31af7Sopenharmony_ci else: 174e5c31af7Sopenharmony_ci raise Exception(f'invalid op: {op}') 175e5c31af7Sopenharmony_ci 176e5c31af7Sopenharmony_cidef evaluateDependency(dependency, isSupported): 177e5c31af7Sopenharmony_ci """Evaluate a dependency expression, returning a boolean result. 178e5c31af7Sopenharmony_ci 179e5c31af7Sopenharmony_ci - dependency - the expression 180e5c31af7Sopenharmony_ci - isSupported - function taking a version or extension name string and 181e5c31af7Sopenharmony_ci returning True or False if that name is supported or not.""" 182e5c31af7Sopenharmony_ci 183e5c31af7Sopenharmony_ci global exprStack 184e5c31af7Sopenharmony_ci exprStack = [] 185e5c31af7Sopenharmony_ci results = dependencyBNF().parseString(dependency, parseAll=True) 186e5c31af7Sopenharmony_ci val = evaluateStack(exprStack[:], isSupported) 187e5c31af7Sopenharmony_ci return val 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_cidef evalDependencyLanguage(stack, leafMarkup, opMarkup, parenthesize, root): 190e5c31af7Sopenharmony_ci """Evaluate an expression stack, returning an English equivalent 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci - stack - the stack 193e5c31af7Sopenharmony_ci - leafMarkup, opMarkup, parenthesize - same as dependencyLanguage 194e5c31af7Sopenharmony_ci - root - True only if this is the outer (root) expression level""" 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_ci op, num_args = stack.pop(), 0 197e5c31af7Sopenharmony_ci if isinstance(op, tuple): 198e5c31af7Sopenharmony_ci op, num_args = op 199e5c31af7Sopenharmony_ci if op in '+,': 200e5c31af7Sopenharmony_ci # Could parenthesize, not needed yet 201e5c31af7Sopenharmony_ci rhs = evalDependencyLanguage(stack, leafMarkup, opMarkup, parenthesize, root = False) 202e5c31af7Sopenharmony_ci opname = opMarkup(op) 203e5c31af7Sopenharmony_ci lhs = evalDependencyLanguage(stack, leafMarkup, opMarkup, parenthesize, root = False) 204e5c31af7Sopenharmony_ci if parenthesize and not root: 205e5c31af7Sopenharmony_ci return f'({lhs} {opname} {rhs})' 206e5c31af7Sopenharmony_ci else: 207e5c31af7Sopenharmony_ci return f'{lhs} {opname} {rhs}' 208e5c31af7Sopenharmony_ci elif op[0].isalpha(): 209e5c31af7Sopenharmony_ci # This is an extension or feature name 210e5c31af7Sopenharmony_ci return leafMarkup(op) 211e5c31af7Sopenharmony_ci else: 212e5c31af7Sopenharmony_ci raise Exception(f'invalid op: {op}') 213e5c31af7Sopenharmony_ci 214e5c31af7Sopenharmony_cidef dependencyLanguage(dependency, leafMarkup, opMarkup, parenthesize): 215e5c31af7Sopenharmony_ci """Return an API dependency expression translated to a form suitable for 216e5c31af7Sopenharmony_ci asciidoctor conditionals or header file comments. 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ci - dependency - the expression 219e5c31af7Sopenharmony_ci - leafMarkup - function taking an extension / version name and 220e5c31af7Sopenharmony_ci returning an equivalent marked up version 221e5c31af7Sopenharmony_ci - opMarkup - function taking an operator ('+' / ',') name name and 222e5c31af7Sopenharmony_ci returning an equivalent marked up version 223e5c31af7Sopenharmony_ci - parenthesize - True if parentheses should be used in the resulting 224e5c31af7Sopenharmony_ci expression, False otherwise""" 225e5c31af7Sopenharmony_ci 226e5c31af7Sopenharmony_ci global exprStack 227e5c31af7Sopenharmony_ci exprStack = [] 228e5c31af7Sopenharmony_ci results = dependencyBNF().parseString(dependency, parseAll=True) 229e5c31af7Sopenharmony_ci return evalDependencyLanguage(exprStack, leafMarkup, opMarkup, parenthesize, root = True) 230e5c31af7Sopenharmony_ci 231e5c31af7Sopenharmony_ci# aka specmacros = False 232e5c31af7Sopenharmony_cidef dependencyLanguageComment(dependency): 233e5c31af7Sopenharmony_ci """Return dependency expression translated to a form suitable for 234e5c31af7Sopenharmony_ci comments in headers of emitted C code, as used by the 235e5c31af7Sopenharmony_ci docgenerator.""" 236e5c31af7Sopenharmony_ci return dependencyLanguage(dependency, leafMarkup = markupPassthrough, opMarkup = opMarkupAsciidoc, parenthesize = True) 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ci# aka specmacros = True 239e5c31af7Sopenharmony_cidef dependencyLanguageSpecMacros(dependency): 240e5c31af7Sopenharmony_ci """Return dependency expression translated to a form suitable for 241e5c31af7Sopenharmony_ci comments in headers of emitted C code, as used by the 242e5c31af7Sopenharmony_ci interfacegenerator.""" 243e5c31af7Sopenharmony_ci return dependencyLanguage(dependency, leafMarkup = leafMarkupAsciidoc, opMarkup = opMarkupAsciidoc, parenthesize = False) 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_cidef dependencyLanguageC(dependency): 246e5c31af7Sopenharmony_ci """Return dependency expression translated to a form suitable for 247e5c31af7Sopenharmony_ci use in C expressions""" 248e5c31af7Sopenharmony_ci return dependencyLanguage(dependency, leafMarkup = leafMarkupC, opMarkup = opMarkupC, parenthesize = True) 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_cidef evalDependencyNames(stack): 251e5c31af7Sopenharmony_ci """Evaluate an expression stack, returning the set of extension and 252e5c31af7Sopenharmony_ci feature names used in the expression. 253e5c31af7Sopenharmony_ci 254e5c31af7Sopenharmony_ci - stack - the stack""" 255e5c31af7Sopenharmony_ci 256e5c31af7Sopenharmony_ci op, num_args = stack.pop(), 0 257e5c31af7Sopenharmony_ci if isinstance(op, tuple): 258e5c31af7Sopenharmony_ci op, num_args = op 259e5c31af7Sopenharmony_ci if op in '+,': 260e5c31af7Sopenharmony_ci # Do not evaluate the operation. We only care about the names. 261e5c31af7Sopenharmony_ci return evalDependencyNames(stack) | evalDependencyNames(stack) 262e5c31af7Sopenharmony_ci elif op[0].isalpha(): 263e5c31af7Sopenharmony_ci return { op } 264e5c31af7Sopenharmony_ci else: 265e5c31af7Sopenharmony_ci raise Exception(f'invalid op: {op}') 266e5c31af7Sopenharmony_ci 267e5c31af7Sopenharmony_cidef dependencyNames(dependency): 268e5c31af7Sopenharmony_ci """Return a set of the extension and version names in an API dependency 269e5c31af7Sopenharmony_ci expression. Used when determining transitive dependencies for spec 270e5c31af7Sopenharmony_ci generation with specific extensions included. 271e5c31af7Sopenharmony_ci 272e5c31af7Sopenharmony_ci - dependency - the expression""" 273e5c31af7Sopenharmony_ci 274e5c31af7Sopenharmony_ci global exprStack 275e5c31af7Sopenharmony_ci exprStack = [] 276e5c31af7Sopenharmony_ci results = dependencyBNF().parseString(dependency, parseAll=True) 277e5c31af7Sopenharmony_ci # print(f'names(): stack = {exprStack}') 278e5c31af7Sopenharmony_ci return evalDependencyNames(exprStack) 279e5c31af7Sopenharmony_ci 280e5c31af7Sopenharmony_cidef markupTraverse(expr, level = 0, root = True): 281e5c31af7Sopenharmony_ci """Recursively process a dependency in infix form, transforming it into 282e5c31af7Sopenharmony_ci asciidoctor markup with expression nesting indicated by indentation 283e5c31af7Sopenharmony_ci level. 284e5c31af7Sopenharmony_ci 285e5c31af7Sopenharmony_ci - expr - expression to process 286e5c31af7Sopenharmony_ci - level - indentation level to render expression at 287e5c31af7Sopenharmony_ci - root - True only on initial call""" 288e5c31af7Sopenharmony_ci 289e5c31af7Sopenharmony_ci if level > 0: 290e5c31af7Sopenharmony_ci prefix = '{nbsp}{nbsp}' * level * 2 + ' ' 291e5c31af7Sopenharmony_ci else: 292e5c31af7Sopenharmony_ci prefix = '' 293e5c31af7Sopenharmony_ci str = '' 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_ci for elem in expr: 296e5c31af7Sopenharmony_ci if isinstance(elem, pp.ParseResults): 297e5c31af7Sopenharmony_ci if not root: 298e5c31af7Sopenharmony_ci nextlevel = level + 1 299e5c31af7Sopenharmony_ci else: 300e5c31af7Sopenharmony_ci # Do not indent the outer expression 301e5c31af7Sopenharmony_ci nextlevel = level 302e5c31af7Sopenharmony_ci 303e5c31af7Sopenharmony_ci str = str + markupTraverse(elem, level = nextlevel, root = False) 304e5c31af7Sopenharmony_ci elif elem in ('+', ','): 305e5c31af7Sopenharmony_ci str = str + f'{prefix}{opMarkupAsciidoc(elem)} +\n' 306e5c31af7Sopenharmony_ci else: 307e5c31af7Sopenharmony_ci str = str + f'{prefix}{leafMarkupAsciidoc(elem)} +\n' 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci return str 310e5c31af7Sopenharmony_ci 311e5c31af7Sopenharmony_cidef dependencyMarkup(dependency): 312e5c31af7Sopenharmony_ci """Return asciidoctor markup for a human-readable equivalent of an API 313e5c31af7Sopenharmony_ci dependency expression, suitable for use in extension appendix 314e5c31af7Sopenharmony_ci metadata. 315e5c31af7Sopenharmony_ci 316e5c31af7Sopenharmony_ci - dependency - the expression""" 317e5c31af7Sopenharmony_ci 318e5c31af7Sopenharmony_ci parsed = dependencyExpr.parseString(dependency) 319e5c31af7Sopenharmony_ci return markupTraverse(parsed) 320e5c31af7Sopenharmony_ci 321e5c31af7Sopenharmony_ciif __name__ == "__main__": 322e5c31af7Sopenharmony_ci for str in [ 'VK_VERSION_1_0', 'cl_khr_extension_name', 'XR_VERSION_3_2', 'CL_VERSION_1_0' ]: 323e5c31af7Sopenharmony_ci print(f'{str} -> {conventions.formatVersionOrExtension(str)}') 324e5c31af7Sopenharmony_ci import sys 325e5c31af7Sopenharmony_ci sys.exit(0) 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ci termdict = { 328e5c31af7Sopenharmony_ci 'VK_VERSION_1_1' : True, 329e5c31af7Sopenharmony_ci 'false' : False, 330e5c31af7Sopenharmony_ci 'true' : True, 331e5c31af7Sopenharmony_ci } 332e5c31af7Sopenharmony_ci termSupported = lambda name: name in termdict and termdict[name] 333e5c31af7Sopenharmony_ci 334e5c31af7Sopenharmony_ci def test(dependency, expected): 335e5c31af7Sopenharmony_ci val = False 336e5c31af7Sopenharmony_ci try: 337e5c31af7Sopenharmony_ci val = evaluateDependency(dependency, termSupported) 338e5c31af7Sopenharmony_ci except ParseException as pe: 339e5c31af7Sopenharmony_ci print(dependency, f'failed parse: {dependency}') 340e5c31af7Sopenharmony_ci except Exception as e: 341e5c31af7Sopenharmony_ci print(dependency, f'failed eval: {dependency}') 342e5c31af7Sopenharmony_ci 343e5c31af7Sopenharmony_ci if val == expected: 344e5c31af7Sopenharmony_ci True 345e5c31af7Sopenharmony_ci # print(f'{dependency} = {val} (as expected)') 346e5c31af7Sopenharmony_ci else: 347e5c31af7Sopenharmony_ci print(f'{dependency} ERROR: {val} != {expected}') 348e5c31af7Sopenharmony_ci 349e5c31af7Sopenharmony_ci # Verify expressions are evaluated left-to-right 350e5c31af7Sopenharmony_ci 351e5c31af7Sopenharmony_ci test('false,false+false', False) 352e5c31af7Sopenharmony_ci test('false,false+true', False) 353e5c31af7Sopenharmony_ci test('false,true+false', False) 354e5c31af7Sopenharmony_ci test('false,true+true', True) 355e5c31af7Sopenharmony_ci test('true,false+false', False) 356e5c31af7Sopenharmony_ci test('true,false+true', True) 357e5c31af7Sopenharmony_ci test('true,true+false', False) 358e5c31af7Sopenharmony_ci test('true,true+true', True) 359e5c31af7Sopenharmony_ci 360e5c31af7Sopenharmony_ci test('false,(false+false)', False) 361e5c31af7Sopenharmony_ci test('false,(false+true)', False) 362e5c31af7Sopenharmony_ci test('false,(true+false)', False) 363e5c31af7Sopenharmony_ci test('false,(true+true)', True) 364e5c31af7Sopenharmony_ci test('true,(false+false)', True) 365e5c31af7Sopenharmony_ci test('true,(false+true)', True) 366e5c31af7Sopenharmony_ci test('true,(true+false)', True) 367e5c31af7Sopenharmony_ci test('true,(true+true)', True) 368e5c31af7Sopenharmony_ci 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_ci test('false+false,false', False) 371e5c31af7Sopenharmony_ci test('false+false,true', True) 372e5c31af7Sopenharmony_ci test('false+true,false', False) 373e5c31af7Sopenharmony_ci test('false+true,true', True) 374e5c31af7Sopenharmony_ci test('true+false,false', False) 375e5c31af7Sopenharmony_ci test('true+false,true', True) 376e5c31af7Sopenharmony_ci test('true+true,false', True) 377e5c31af7Sopenharmony_ci test('true+true,true', True) 378e5c31af7Sopenharmony_ci 379e5c31af7Sopenharmony_ci test('false+(false,false)', False) 380e5c31af7Sopenharmony_ci test('false+(false,true)', False) 381e5c31af7Sopenharmony_ci test('false+(true,false)', False) 382e5c31af7Sopenharmony_ci test('false+(true,true)', False) 383e5c31af7Sopenharmony_ci test('true+(false,false)', False) 384e5c31af7Sopenharmony_ci test('true+(false,true)', True) 385e5c31af7Sopenharmony_ci test('true+(true,false)', True) 386e5c31af7Sopenharmony_ci test('true+(true,true)', True) 387e5c31af7Sopenharmony_ci 388e5c31af7Sopenharmony_ci # Check formatting 389e5c31af7Sopenharmony_ci for dependency in [ 390e5c31af7Sopenharmony_ci #'true', 391e5c31af7Sopenharmony_ci #'true+true+false', 392e5c31af7Sopenharmony_ci 'true+false', 393e5c31af7Sopenharmony_ci 'true+(true+false),(false,true)', 394e5c31af7Sopenharmony_ci #'true+((true+false),(false,true))', 395e5c31af7Sopenharmony_ci 'VK_VERSION_1_0+VK_KHR_display', 396e5c31af7Sopenharmony_ci #'VK_VERSION_1_1+(true,false)', 397e5c31af7Sopenharmony_ci ]: 398e5c31af7Sopenharmony_ci print(f'expr = {dependency}\n{dependencyMarkup(dependency)}') 399e5c31af7Sopenharmony_ci print(f' spec language = {dependencyLanguageSpecMacros(dependency)}') 400e5c31af7Sopenharmony_ci print(f' comment language = {dependencyLanguageComment(dependency)}') 401e5c31af7Sopenharmony_ci print(f' C language = {dependencyLanguageC(dependency)}') 402e5c31af7Sopenharmony_ci print(f' names = {dependencyNames(dependency)}') 403e5c31af7Sopenharmony_ci print(f' value = {evaluateDependency(dependency, termSupported)}') 404