diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 20:38:23 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 20:38:23 +0000 |
commit | ff6e3c025658a5fa1affd094f220b623e7e1b24b (patch) | |
tree | 9faab72d69c92d24e349d184f5869b9796f17e0c /tools/glsl_preproc/variables.py | |
parent | Initial commit. (diff) | |
download | libplacebo-ff6e3c025658a5fa1affd094f220b623e7e1b24b.tar.xz libplacebo-ff6e3c025658a5fa1affd094f220b623e7e1b24b.zip |
Adding upstream version 6.338.2.upstream/6.338.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/glsl_preproc/variables.py')
-rw-r--r-- | tools/glsl_preproc/variables.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/tools/glsl_preproc/variables.py b/tools/glsl_preproc/variables.py new file mode 100644 index 0000000..187fd79 --- /dev/null +++ b/tools/glsl_preproc/variables.py @@ -0,0 +1,79 @@ +import re + +def slugify(value): + value = re.sub(r'[^\w]+', '_', value.lower()).strip('_') + if value[:1].isdigit(): + value = '_' + value + return value + +# A single variable (enclosed by the template) +class Var(object): + STRUCT_NAME = 'vars' + CSIZES = { + # This array doesn't have to be exact, it's only used for sorting + # struct members to save a few bytes of memory here and there + 'int': 4, + 'unsigned': 4, + 'float': 4, + 'ident_t': 2, + 'uint8_t': 1, + 'bool': 1, + } + + def __init__(self, ctype, expr, name, csize=0, linenr=0): + self.ctype = ctype + self.csize = csize or Var.CSIZES[ctype] + self.expr = expr + self.name = name + self.linenr = linenr + + def __str__(self): + return f'{Var.STRUCT_NAME}.{self.name}' + +def is_literal(expr): + return expr.isnumeric() or expr in ['true', 'false'] + +# A (deduplicated) set of variables +class VarSet(object): + def __init__(self): + self.varmap = {} # expr -> cvar + + def __iter__(self): + # Sort from largest to smallest variable to optimize struct padding + yield from sorted(self.varmap.values(), + reverse=True, + key=lambda v: v.csize, + ) + + def __bool__(self): + return True if self.varmap else False + + def add_var_raw(self, var): + # Re-use existing entry for identical expression/type pairs + if old := self.varmap.get(var.expr): + if var.ctype != old.ctype: + raise SyntaxError(f'Conflicting types for expression {var.expr}, ' + f'got {var.ctype}, expected {old.ctype}') + assert old.name == var.name + return old + + names = [ v.name for v in self.varmap.values() ] + while var.name in names: + var.name += '_' + self.varmap[var.expr] = var + return var + + # Returns the added variable + def add_var(self, ctype, expr, name=None, linenr=0): + assert expr + expr = expr.strip() + if is_literal(expr): + return expr + name = name or slugify(expr) + + var = Var(ctype, expr=expr, name=name, linenr=linenr) + return self.add_var_raw(var) + + def merge(self, other): + for var in other: + self.add_var_raw(var) |