scripts: Simplified csv.py's func/uop/bop/top helpers

Now that I know my way around the weirdness that is Python's class
scope, this just required another function indirection to capture the
class-level dicts correctly.

I was considering using the __subclasses__ trick, but it seems like that
would actually be more complicated here.
This commit is contained in:
Christopher Haster
2025-04-15 01:34:03 -05:00
parent bd70270e11
commit 7c26bfc0a3
+24 -44
View File
@@ -541,20 +541,18 @@ class CsvExpr:
return fields[self.a] return fields[self.a]
# func expr helper # func expr helper
def func(funcs):
def func(name, args="a"): def func(name, args="a"):
def func(f): def func(f):
f._func = name f._func = name
f._fargs = args f._fargs = args
funcs[f._func] = f
return f return f
return func return func
return func
class Funcs: funcs = {}
@ft.cache func = func(funcs)
def __get__(self, _, cls):
return {x._func: x
for x in cls.__dict__.values()
if hasattr(x, '_func')}
funcs = Funcs()
# type exprs # type exprs
@func('int', 'a') @func('int', 'a')
@@ -881,19 +879,17 @@ class CsvExpr:
return CsvInt(0) return CsvInt(0)
# unary expr helper # unary expr helper
def uop(uops):
def uop(op): def uop(op):
def uop(f): def uop(f):
f._uop = op f._uop = op
uops[f._uop] = f
return f return f
return uop return uop
return uop
class UOps: uops = {}
@ft.cache uop = uop(uops)
def __get__(self, _, cls):
return {x._uop: x
for x in cls.__dict__.values()
if hasattr(x, '_uop')}
uops = UOps()
# unary ops # unary ops
@uop('+') @uop('+')
@@ -921,28 +917,20 @@ class CsvExpr:
return CsvInt(1) return CsvInt(1)
# binary expr help # binary expr help
def bop(bops, bprecs):
def bop(op, prec): def bop(op, prec):
def bop(f): def bop(f):
f._bop = op f._bop = op
f._bprec = prec f._bprec = prec
bops[f._bop] = f
bprecs[f._bop] = f._bprec
return f return f
return bop return bop
return bop
class BOps: bops = {}
@ft.cache bprecs = {}
def __get__(self, _, cls): bop = bop(bops, bprecs)
return {x._bop: x
for x in cls.__dict__.values()
if hasattr(x, '_bop')}
bops = BOps()
class BPrecs:
@ft.cache
def __get__(self, _, cls):
return {x._bop: x._bprec
for x in cls.__dict__.values()
if hasattr(x, '_bop')}
bprecs = BPrecs()
# binary ops # binary ops
@bop('*', 10) @bop('*', 10)
@@ -1052,28 +1040,20 @@ class CsvExpr:
return self.b.eval(fields) return self.b.eval(fields)
# ternary expr help # ternary expr help
def top(tops, tprecs):
def top(op_a, op_b, prec): def top(op_a, op_b, prec):
def top(f): def top(f):
f._top = (op_a, op_b) f._top = (op_a, op_b)
f._tprec = prec f._tprec = prec
tops[f._top] = f
tprecs[f._top] = f._tprec
return f return f
return top return top
return top
class TOps: tops = {}
@ft.cache tprecs = {}
def __get__(self, _, cls): top = top(tops, tprecs)
return {x._top: x
for x in cls.__dict__.values()
if hasattr(x, '_top')}
tops = TOps()
class TPrecs:
@ft.cache
def __get__(self, _, cls):
return {x._top: x._tprec
for x in cls.__dict__.values()
if hasattr(x, '_top')}
tprecs = TPrecs()
# ternary ops # ternary ops
@top('?', ':', 1) @top('?', ':', 1)