Skip to content

Commit 8dd1b71

Browse files
YashGupt29viferga
andauthored
feat:wrote a new tutorial of tree traversal for metacall (#8)
* feat:wrote a new tutorial of tree traversal for metacall * fixed double quotes to single * Update index.js --------- Co-authored-by: Vicente Eduardo Ferrer Garcia <[email protected]>
1 parent bb43782 commit 8dd1b71

File tree

6 files changed

+818
-2
lines changed

6 files changed

+818
-2
lines changed

docs/tutorials/treetraversal.mdx

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
import DocusaurusTreeVisualization from "@site/src/components/TreeTraversal/DocusaurusWrapper";
2+
3+
# Traversing a Polyglot Tree with MetaCall
4+
5+
A comprehensive guide to implementing and visualizing tree traversal across multiple programming languages using MetaCall.
6+
7+
## Table of Contents
8+
9+
- [Overview](#overview)
10+
- [Prerequisites](#prerequisites)
11+
- [Project Setup](#project-setup)
12+
- [Implementation Details](#implementation-details)
13+
- [Tree Visualization](#tree-visualization)
14+
- [Running the Project](#running-the-project)
15+
- [Technical Deep Dive](#technical-deep-dive)
16+
17+
## Overview
18+
19+
This tutorial demonstrates how to create a binary tree where each node is implemented in a different programming language:
20+
21+
- Root Node: Python
22+
- Middle Node: JavaScript
23+
- Leaf Node: C
24+
25+
The implementation showcases MetaCall's ability to seamlessly integrate functions across different programming languages in a single process.
26+
27+
## Prerequisites
28+
29+
- Linux environment
30+
- Git
31+
- CMake
32+
- Basic knowledge of:
33+
- Python
34+
- JavaScript
35+
- C
36+
- React/Next.js (for visualization)
37+
- MetaCall installation
38+
39+
## Project Setup
40+
41+
### 1. System Dependencies
42+
43+
```bash
44+
sudo apt-get update
45+
sudo apt-get install -y --no-install-recommends \
46+
ca-certificates \
47+
git \
48+
liburing-dev \
49+
cmake \
50+
curl
51+
```
52+
53+
### 2. MetaCall Installation
54+
55+
```bash
56+
git clone --branch v0.8.7 https://github.com/metacall/core
57+
cd core
58+
./tools/metacall-environment.sh release base nodejs c python
59+
sudo mkdir build && cd build
60+
sudo cmake \
61+
-DOPTION_BUILD_LOADERS_C=On \
62+
-DOPTION_BUILD_LOADERS_NODE=On \
63+
-DOPTION_BUILD_LOADERS_PY=On \
64+
-DOPTION_BUILD_PORTS=On \
65+
-DOPTION_BUILD_PORTS_NODE=On \
66+
-DOPTION_BUILD_PORTS_PY=On \
67+
-DOPTION_BUILD_DETOURS=Off \
68+
-DOPTION_BUILD_SCRIPTS=Off \
69+
-DOPTION_BUILD_TESTS=Off \
70+
-DOPTION_BUILD_EXAMPLES=Off \
71+
..
72+
sudo cmake --build . --target install
73+
sudo ldconfig /usr/local/lib
74+
```
75+
76+
### 3. Environment Configuration
77+
78+
```bash
79+
export LOADER_LIBRARY_PATH="/usr/local/lib"
80+
export LOADER_SCRIPT_PATH="$(pwd)"
81+
```
82+
83+
## Implementation Details
84+
85+
### Leaf Node (C)
86+
87+
`leaf_Node.c`:
88+
89+
```c
90+
#include <stdio.h>
91+
92+
void leaf_node(int currentNode) {
93+
printf("%d ", currentNode);
94+
}
95+
```
96+
97+
### Middle Node (JavaScript)
98+
99+
`middleNode.js`:
100+
101+
```javascript
102+
const { metacall, metacall_load_from_file } = require("metacall");
103+
metacall_load_from_file("c", ["leaf_Node.c"]);
104+
105+
function traverse_middleNode(currentNode) {
106+
// Left child
107+
metacall("leaf_node", 2 * currentNode);
108+
109+
// Current node
110+
process.stdout.write(currentNode.toString() + " ");
111+
112+
// Right child
113+
metacall("leaf_node", 2 * currentNode + 1);
114+
}
115+
116+
module.exports = traverse_middleNode;
117+
```
118+
119+
### Root Node (Python)
120+
121+
`rootNode.py`:
122+
123+
```python
124+
from metacall import metacall, metacall_load_from_file
125+
126+
# Load JavaScript middle node
127+
metacall_load_from_file('node', ['middleNode.js'])
128+
129+
currentNode = 1
130+
131+
# Traverse tree
132+
metacall('traverse_middleNode', 2 * currentNode) # Left subtree
133+
print(currentNode, end=" ", flush=True) # Current node
134+
metacall('traverse_middleNode', 2 * currentNode + 1) # Right subtree
135+
```
136+
137+
## Tree Visualization
138+
139+
The visualization component is built with Next.js and provides an interactive way to understand the tree traversal process. Let's dive into the implementation details.
140+
141+
<DocusaurusTreeVisualization />
142+
143+
### Component Architecture
144+
145+
```typescript
146+
interface TreeNode {
147+
id: number;
148+
language: "python" | "javascript" | "c";
149+
left?: number;
150+
right?: number;
151+
x: number;
152+
y: number;
153+
}
154+
```
155+
156+
### Key Features
157+
158+
1. **Tree Generation**
159+
160+
```typescript
161+
const generateTree = (input: string): TreeNode[] => {
162+
const values = input.split(",").map(Number);
163+
const height = Math.floor(Math.log2(values.length)) + 1;
164+
165+
return values.map((value, i) => {
166+
const level = Math.floor(Math.log2(i + 1));
167+
// Calculate x,y coordinates for visual layout
168+
const x = calculateXPosition(level, i);
169+
const y = calculateYPosition(level, height);
170+
171+
// Assign language based on node level
172+
const language =
173+
level === 0 ? "python" : level === height - 1 ? "c" : "javascript";
174+
175+
return {
176+
id: value,
177+
language,
178+
left: 2 * i + 1 < values.length ? values[2 * i + 1] : undefined,
179+
right: 2 * i + 2 < values.length ? values[2 * i + 2] : undefined,
180+
x,
181+
y,
182+
};
183+
});
184+
};
185+
```
186+
187+
2. **Traversal Implementation**
188+
189+
```typescript
190+
const getTraversalOrder = (type: string, nodes: TreeNode[]): number[] => {
191+
const result: number[] = [];
192+
193+
const traverse = (nodeId: number) => {
194+
const node = nodes.find((n) => n.id === nodeId);
195+
if (!node) return;
196+
197+
// Preorder: Root -> Left -> Right
198+
if (type === "preorder") result.push(node.id);
199+
200+
// Traverse left subtree
201+
if (node.left !== undefined) traverse(node.left);
202+
203+
// Inorder: Left -> Root -> Right
204+
if (type === "inorder") result.push(node.id);
205+
206+
// Traverse right subtree
207+
if (node.right !== undefined) traverse(node.right);
208+
209+
// Postorder: Left -> Right -> Root
210+
if (type === "postorder") result.push(node.id);
211+
};
212+
213+
if (nodes.length > 0) traverse(nodes[0].id);
214+
return result;
215+
};
216+
```
217+
218+
3. **Animation Control**
219+
220+
```typescript
221+
useEffect(() => {
222+
if (isAnimating && currentStep < traversalSteps.length - 1) {
223+
const timer = setTimeout(() => {
224+
const nextStep = currentStep + 1;
225+
setCurrentStep(nextStep);
226+
setActiveNode(traversalSteps[nextStep]);
227+
228+
// Highlight the path from parent to current node
229+
const currentNode = tree.find((n) => n.id === traversalSteps[nextStep]);
230+
if (currentNode) {
231+
const parentNode = tree.find(
232+
(n) => n.left === currentNode.id || n.right === currentNode.id
233+
);
234+
if (parentNode) {
235+
setActivePath(`${parentNode.id}-${currentNode.id}`);
236+
}
237+
}
238+
}, 1000);
239+
240+
return () => clearTimeout(timer);
241+
}
242+
}, [isAnimating, currentStep, traversalSteps, tree]);
243+
```
244+
245+
### Visual Elements
246+
247+
1. **Node Colors**
248+
249+
```typescript
250+
const getNodeClasses = (nodeId) => {
251+
const node = tree.find((n) => n.id === nodeId);
252+
if (!node) return styles.node;
253+
const isActive = nodeId === activeNode;
254+
return `${styles.node} ${styles[`node-${node.language}`]} ${
255+
isActive ? styles.active : ""
256+
}`;
257+
};
258+
```
259+
260+
2. **Arrow Connections**
261+
262+
```typescript
263+
<Xarrow
264+
start={`node-${node.id}`}
265+
end={`node-${node.left}`}
266+
color={getArrowColor(node.id, node.left)}
267+
strokeWidth={activePath === `${node.id}-${node.left}` ? 3 : 2}
268+
animateDrawing={true}
269+
dashness={{ animation: 5 }}
270+
/>
271+
```
272+
273+
### Traversal Types
274+
275+
The visualization supports three types of tree traversal:
276+
277+
1. **Inorder (Left -> Root -> Right)**
278+
279+
- Visit left subtree
280+
- Visit root
281+
- Visit right subtree
282+
283+
2. **Preorder (Root -> Left -> Right)**
284+
285+
- Visit root
286+
- Visit left subtree
287+
- Visit right subtree
288+
289+
3. **Postorder (Left -> Right -> Root)**
290+
- Visit left subtree
291+
- Visit right subtree
292+
- Visit root
293+
294+
## Running the Project
295+
296+
1. Start MetaCall CLI:
297+
298+
```bash
299+
metacallcli rootNode.py
300+
```
301+
302+
2. Launch visualization (if using Next.js):
303+
304+
```bash
305+
npm run dev
306+
```
307+
308+
## Technical Deep Dive
309+
310+
### MetaCall Integration
311+
312+
The project demonstrates three key MetaCall features:
313+
314+
1. **Cross-Language Loading**
315+
316+
```python
317+
metacall_load_from_file('node', ['middleNode.js'])
318+
```
319+
320+
2. **Function Execution**
321+
322+
```python
323+
metacall('traverse_middleNode', currentNode)
324+
```
325+
326+
3. **Data Type Handling**
327+
328+
- Numbers are automatically converted between languages
329+
- Stdout is properly managed across language boundaries
330+
331+
### Tree Traversal Logic
332+
333+
The traversal follows these steps:
334+
335+
1. Python root node initiates traversal
336+
2. JavaScript middle node processes:
337+
- Left child (C)
338+
- Current node
339+
- Right child (C)
340+
3. C leaf nodes print their values
341+
342+
### Performance Considerations
343+
344+
- MetaCall overhead is minimal for this use case
345+
- Memory usage is efficient due to:
346+
- No redundant data copying between languages
347+
- Direct function calls across language boundaries
348+
349+
## Resources
350+
351+
- [MetaCall Documentation](https://metacall.github.io/doc/docs/getting-started)
352+
- [Project GitHub Repository](https://github.com/metacall/doc)
353+
- [Next.js Documentation](https://nextjs.org/docs)
354+
355+
## Contributing
356+
357+
Contributions are welcome! Please:
358+
359+
1. Fork the repository
360+
2. Create a feature branch
361+
3. Submit a pull request

package-lock.json

Lines changed: 20 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)