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