summaryrefslogtreecommitdiff
path: root/lib9p/idl.gen
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/idl.gen')
-rwxr-xr-xlib9p/idl.gen28
1 files changed, 24 insertions, 4 deletions
diff --git a/lib9p/idl.gen b/lib9p/idl.gen
index 27396b4..0a43583 100755
--- a/lib9p/idl.gen
+++ b/lib9p/idl.gen
@@ -5,8 +5,10 @@
# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later
+import graphlib
import os.path
import sys
+import typing
sys.path.insert(0, os.path.normpath(os.path.join(__file__, "..")))
@@ -141,6 +143,24 @@ def ifdef_pop(n: int) -> str:
return ret
+def topo_sorted(typs: list[idl.Type]) -> typing.Iterable[idl.Type]:
+ ts: graphlib.TopologicalSorter[idl.Type] = graphlib.TopologicalSorter()
+ for typ in typs:
+ match typ:
+ case idl.Number():
+ ts.add(typ)
+ case idl.Bitfield():
+ ts.add(typ)
+ case idl.Struct(): # and idl.Message():
+ deps = [
+ member.typ
+ for member in typ.members
+ if not isinstance(member.typ, idl.Primitive)
+ ]
+ ts.add(typ, *deps)
+ return ts.static_order()
+
+
# Generate .h ##################################################################
@@ -201,7 +221,7 @@ enum {idprefix}version {{
ret += """
/* payload types **************************************************************/
"""
- for typ in typs:
+ for typ in topo_sorted(typs):
ret += "\n"
ret += ifdef_push(1, c_ver_ifdef(typ.in_versions))
match typ:
@@ -385,7 +405,7 @@ LM_ALWAYS_INLINE static bool _validate_list(struct _validate_ctx *ctx,
#define validate_4(ctx) _validate_size_net(ctx, 4)
#define validate_8(ctx) _validate_size_net(ctx, 8)
"""
- for typ in typs:
+ for typ in topo_sorted(typs):
inline = "LM_FLATTEN" if isinstance(typ, idl.Message) else "LM_ALWAYS_INLINE"
argfn = unused if (isinstance(typ, idl.Struct) and not typ.members) else used
ret += "\n"
@@ -525,7 +545,7 @@ LM_ALWAYS_INLINE static void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *o
\tctx->net_offset += 8;
}
"""
- for typ in typs:
+ for typ in topo_sorted(typs):
inline = "LM_FLATTEN" if isinstance(typ, idl.Message) else "LM_ALWAYS_INLINE"
argfn = unused if (isinstance(typ, idl.Struct) and not typ.members) else used
ret += "\n"
@@ -618,7 +638,7 @@ LM_ALWAYS_INLINE static bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val)
\treturn false;
}
"""
- for typ in typs:
+ for typ in topo_sorted(typs):
inline = "LM_FLATTEN" if isinstance(typ, idl.Message) else "LM_ALWAYS_INLINE"
argfn = unused if (isinstance(typ, idl.Struct) and not typ.members) else used
ret += "\n"