Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph.c
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,43 @@
+module;
+
+import graph/node;
+import graph/edge;
+
+import stdlib;
+
+export struct Graph {
+    struct Node *nodes;
+    struct Edge *edges;
+    int num_nodes;
+    int num_edges;
+};
+
+export struct Graph create_rand_graph(int num_nodes, int num_edges) {
+    struct Graph g;
+    g.num_nodes = num_nodes;
+    g.num_edges = num_edges;
+    g.nodes = (struct Node *) calloc(num_nodes, sizeof(struct Node));
+    g.edges = (struct Edge *) calloc(num_edges, * sizeof(struct Edge));
+    for (int i=0; i<num_edges; ++i) {
+        struct Node *first = grab_random_node(&g), *second = grab_random_node(&g);
+        g.edges[i] = create_edge(first, second);
+        add_edge(first, &g.edges[i]);
+        add_edge(second, &g.edges[i]);
+    }
+    return g;
+}
+
+export struct Node *grab_random_node(struct Graph *g) {
+    return &g->nodes[rand() % g->num_nodes];
+}
+
+const int max_steps_to_walk = 1000;
+export int path_found(struct Node *first, struct Node *second) {
+    return random_search(first, second, max_steps_to_walk);
+}
+
+export int destroy_graph(struct Graph *g) {
+    free(g->nodes);
+    free(g->edges);
+    return 0;
+}
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge.c
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,17 @@
+module;
+
+import node;
+
+export struct Edge {
+    struct Node *nodes[2];
+    struct Other o;
+};
+
+struct Other {};
+
+export struct Edge create_edge(struct Node *first, struct Node *second) {
+    struct Edge e;
+    e.nodes[0] = first;
+    e.nodes[1] = second;
+    return e;
+}
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge__tshell.h
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,9 @@
+#pragma once
+
+// [[size 16, align 8]]
+struct graph$edge$$Edge$$shell {
+    double contents[2];  // just to fill space, not used
+};
+
+// [[size 0, align 1]]
+struct graph$edge$$Other$$shell {};
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge_picker.c
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge_picker.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge_picker.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,18 @@
+module;
+
+import edge;
+import node;
+
+import stdlib;
+
+struct Controller {};
+
+export struct Controller get_controller() {
+    return (struct Controller){};
+}
+
+export struct Node *pick_next(struct Controller *c, struct Node *n) {
+    if (n->num_edges == 0) return NULL;
+    struct Edge *e = n->edges[rand() % n->num_edges];
+    return e->nodes[0] == n ? e->nodes[1] : e->nodes[0];
+}
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge_picker__tshell.h
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge_picker__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph/edge_picker__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,4 @@
+#pragma once
+
+// [[size 0, align 1]]
+struct graph$edge_picker$$Controller$$shell {};
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph/node.c
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph/node.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph/node.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,39 @@
+module;
+
+import edge;
+import edge_picker;
+
+import stdlib;
+
+export struct Node {
+    int num_edges;
+    struct Edge *edges[max_edges_per_node];
+    struct Other o;
+}
+const int max_edges_per_node = 100;  // don't want to set up a dynamic array
+
+struct Other {};
+
+export int add_edge(struct Node *n, struct Edge *e) {
+    if (n->num_edges >= max_edges_per_node) exit(2);
+    n->edges[n->num_edges++] = e;
+    return 1;
+}
+
+export int random_search(struct Node *start, struct Node *end, int steps_left) {
+    while (steps_left > 0) {
+        int result = random_search$$mangle(start, end, &steps_left);
+        if (result != 0) return result;
+    }
+    return 0;
+}
+
+const int continue_rate = 2;
+int random_search$$mangle(struct Node *start, struct Node *end, int *steps_left) {
+    if (start == end) return 1;
+    (*steps_left)--;
+    if (rand() % continue_rate == 0) return 0;
+    struct Controller c = get_controller();
+    struct Node *n = pick_next(&c, start);
+    return random_search$$mangle(n, end, steps_left);
+}
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph/node__tshell.h
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph/node__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph/node__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,9 @@
+#pragma once
+
+// [[size 808, align 8]]
+struct graph$node$$Node$$shell {
+    double contents[101];  // just to fill space, not used
+};
+
+// [[size 0, align 1]]
+struct graph$node$$Other$$shell {};
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/graph__tshell.h
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/graph__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/graph__tshell.h	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,6 @@
+#pragma once
+
+// [[size 24, align 8]]
+struct graph$$Graph$$shell {
+    double contents[3];  // just to fill space, not used
+};
Index: doc/proposals/modules-alvin/examples/graph/2_tshell/main.c
===================================================================
--- doc/proposals/modules-alvin/examples/graph/2_tshell/main.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
+++ doc/proposals/modules-alvin/examples/graph/2_tshell/main.c	(revision 7640ff5c2bfadbdbf25492ac84ec6e5be20a4989)
@@ -0,0 +1,83 @@
+// Graph searching algorithm testing script
+
+import graph;
+
+import stdio;
+import stdlib;
+import unistd;
+
+void print_usage() {
+    printf("Usage: program_name [-n num_iter] [-s seed] [-N num_nodes] [-E num_edges] [-c num_checks] [-h]\n");
+    printf("Options:\n");
+    printf("  -n num_iter   Number of graphs to run on\n");
+    printf("  -s seed       Seed for random number generator\n");
+    printf("  -N num_nodes  Number of nodes in generated graph\n");
+    printf("  -E num_edges  Number of edges in generated graph\n");
+    printf("  -c num_checks Number of times to check graph for paths\n");
+    printf("  -h            Display this help message\n");
+}
+
+struct Arg {
+    int num_iter, seed, num_nodes, num_edges, num_checks;
+};
+
+struct Arg process_args(int argc, char *argv[]) {
+    int opt;
+    struct Arg args;
+    args.num_iter = 10;
+    args.seed = 0;
+    args.num_nodes = 100;
+    args.num_edges = 100;
+    args.num_checks = 10;
+
+    // Parse command line options
+    while ((opt = getopt(argc, argv, "n:s:N:E:c:h")) != -1) {
+        switch (opt) {
+            case 'n':
+                args.num_iter = atoi(optarg);
+                break;
+            case 's':
+                args.seed = atoi(optarg);
+                break;
+            case 'N':
+                args.num_nodes = atoi(optarg);
+                break;
+            case 'E':
+                args.num_edges = atoi(optarg);
+                break;
+            case 'c':
+                args.num_checks = atoi(optarg);
+                break;
+            case 'h':
+                print_usage(); // Print usage information
+                exit(0);
+            case '?':
+                // Handle unknown options
+                fprintf(stderr, "Unknown option: -%c\n", optopt);
+                print_usage();
+                exit(1);
+            default:
+                print_usage();
+                exit(1);
+        }
+    }
+    return args;
+}
+
+int main(int argc, char *argv[]) {
+    struct Arg args = process_args(argc, argv);
+    int total_paths = 0;
+    srand(args.seed);
+    for (int i=0; i<args.num_iter; ++i) {
+        struct Graph g = create_rand_graph(args.num_nodes, args.num_edges);
+        int paths_found = 0;
+        for (int j=0; j<args.num_checks; ++j) {
+            struct Node *n1 = grab_random_node(&g);
+            struct Node *n2 = grab_random_node(&g);
+            paths_found += path_found(n1, n2);  // it's technically returning a bool
+        }
+        destroy_graph(&g);
+        printf("Graph %d: %d paths found over %d checks.\n", i, paths_found, args.num_checks);
+    }
+    printf("Summary: %d graphs * %d checks = %d total checks performed, %d paths found.\n", args.num_iter, args.num_checks, args.num_iter * args.num_checks, total_paths);
+}
