1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright © 2025–present Arlo Louis Byrne (idky137)
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0.
// See the LICENSE-APACHE file in the project root for license terms.
//! # limen-build — proc-macro front for `limen-codegen`
//!
//! Provides the `define_graph! { ... }` macro which parses the Limen graph DSL
//! and expands it into fully-typed Rust code via `limen-codegen`.
//!
//! See `limen-codegen` crate docs for the DSL shape and the exact generated API.
extern crate proc_macro;
use TokenStream;
use ;
use quote;
/// Define a Limen graph using the DSL and expand it into generated Rust code.
///
/// This macro forwards its input tokens directly to
/// [`limen_codegen::expand_tokens`] and returns the emitted items.
///
/// Each invocation emits a single concrete graph type. Use the trailing
/// `concurrent;` keyword to additionally request the std-only
/// `ScopedGraphApi` implementation for that same graph type.
///
/// # Example (no_std, `GraphApi` only)
/// ```ignore
/// use limen_build::define_graph;
///
/// define_graph! {
/// pub struct MyGraph;
///
/// nodes {
/// 0: { ty: my::Src, in_ports: 0, out_ports: 1, in_payload: (), out_payload: u32, name: Some("src"), ingress_policy: MY_Q },
/// 1: { ty: my::Map, in_ports: 1, out_ports: 1, in_payload: u32, out_payload: u32, name: Some("map") },
/// 2: { ty: my::Sink, in_ports: 1, out_ports: 0, in_payload: u32, out_payload: (), name: Some("sink") },
/// }
///
/// edges {
/// 0: { ty: TestSpscRingBuf<8>, payload: u32, manager: StaticMemoryManager<u32, 8>, from: (0, 0), to: (1, 0), policy: EDGE_POL, name: Some("src->map") },
/// 1: { ty: TestSpscRingBuf<8>, payload: u32, manager: StaticMemoryManager<u32, 8>, from: (1, 0), to: (2, 0), policy: EDGE_POL, name: Some("map->sink") },
/// }
/// }
/// ```
///
/// # Example (std, `GraphApi` + `ScopedGraphApi`)
///
/// Adding `concurrent;` inside the **same** invocation extends the generated graph type
/// with a std-only `ScopedGraphApi` impl — it does **not** emit a second graph type.
///
/// ```ignore
/// use limen_build::define_graph;
///
/// define_graph! {
/// pub struct MyGraph;
///
/// nodes {
/// 0: { ty: my::Src, in_ports: 0, out_ports: 1, in_payload: (), out_payload: u32, name: Some("src"), ingress_policy: MY_Q },
/// 1: { ty: my::Map, in_ports: 1, out_ports: 1, in_payload: u32, out_payload: u32, name: Some("map") },
/// 2: { ty: my::Sink, in_ports: 1, out_ports: 0, in_payload: u32, out_payload: (), name: Some("sink") },
/// }
///
/// edges {
/// 0: { ty: TestSpscRingBuf<8>, payload: u32, manager: ConcurrentMemoryManager<u32>, from: (0, 0), to: (1, 0), policy: EDGE_POL, name: Some("src->map") },
/// 1: { ty: TestSpscRingBuf<8>, payload: u32, manager: ConcurrentMemoryManager<u32>, from: (1, 0), to: (2, 0), policy: EDGE_POL, name: Some("map->sink") },
/// }
///
/// concurrent;
/// }
/// ```
/// Convert a `CodegenError` into a compile-time error token stream.
///
/// - For parse errors, preserve spans using `syn::Error::to_compile_error`.
/// - For other errors, use `compile_error!("<message>")`.