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