h2lang 0.5.4

H2 Language - A Herbert Online Judge compatible programming language with multi-agent support
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# H2 Language

[![CI](https://github.com/ekusiadadus/h2lang/actions/workflows/ci.yml/badge.svg)](https://github.com/ekusiadadus/h2lang/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Rust](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://www.rust-lang.org/)
[![WebAssembly](https://img.shields.io/badge/wasm-supported-blueviolet.svg)](https://webassembly.org/)
[![Crates.io](https://img.shields.io/crates/v/h2lang.svg)](https://crates.io/crates/h2lang)
[![Documentation](https://docs.rs/h2lang/badge.svg)](https://docs.rs/h2lang)

<!-- Uncomment after publishing to npm -->
<!-- [![npm](https://img.shields.io/npm/v/h2lang.svg)](https://www.npmjs.com/package/h2lang) -->

**H2 Language** (h2lang) is a programming language compiler fully compatible with the [Herbert Online Judge (HOJ)](https://github.com/quolc/hoj) H language specification, extended with multi-agent support for robot swarm control.

## Features

- **HOJ Compatible** - Full support for Herbert Online Judge syntax including macros, functions, and recursion
- **Multi-Agent Support** - Control multiple robots simultaneously with parallel scheduling
- **WebAssembly Ready** - Runs in browsers via wasm-bindgen
- **Zero Dependencies Runtime** - Lightweight compiled output
- **Type-Safe** - Written in Rust with comprehensive error handling
- **Well Documented** - Extensive documentation following Rust API guidelines

## Quick Start

```h2
# Single robot drawing a square
0: f(X):XXXX f(sssr)

# Two robots moving in parallel
0: srl
1: lrs

# Recursive pattern with numeric argument
0: a(X):sra(X-1) a(4)
```

## Installation

### From crates.io (Rust)

```bash
cargo add h2lang
```

### From npm (WebAssembly)

```bash
npm install h2lang
```

### From Source

```bash
# Clone the repository
git clone https://github.com/ekusiadadus/h2lang.git
cd h2lang

# Build WebAssembly package
wasm-pack build --target web --out-dir pkg

# Or build native library
cargo build --release

# Run tests
cargo test
```

### Requirements

- Rust 1.70+
- wasm-pack (for WebAssembly builds)
- Node.js 16+ (for npm usage)

## Language Specification

### Basic Commands

| Command | Description | Action |
|---------|-------------|--------|
| `s` | **S**traight | Move forward one step |
| `r` | **R**ight | Rotate 90° clockwise |
| `l` | **L**eft | Rotate 90° counter-clockwise |

### Agent Definition

Each line defines commands for a specific robot (agent):

```h2
agent_id: commands

# Examples
0: srl        # Agent 0: straight, right, left
1: llss       # Agent 1: left, left, straight, straight
```

### Macros

Define reusable command sequences with single lowercase letters:

```h2
# Syntax: name:body
x:ss          # Define macro 'x' as 'ss'
xrx           # Expands to: ssrss

# Full example
0: x:sssr xrxrxrx   # Square pattern using macro
```

### Functions

Functions support parameters (uppercase letters) and recursion:

```h2
# Syntax: name(PARAMS):body
f(X):XXX f(s)           # Repeats argument 3 times → sss
f(X):XXXX f(sssr)       # Square pattern → sssrsssrsssrsssr

# Multiple parameters
a(X,Y):Ya(X-1,Y) a(4,s) # Repeat 's' four times → ssss

# Numeric arguments with recursion
a(X):sra(X-1) a(4)      # Spiral pattern (terminates when X ≤ 0)
```

### Numeric Expressions

Functions support numeric arguments and arithmetic:

```h2
a(X):sa(X-1) a(4)       # X decrements: 4→3→2→1→0(stop)
a(X):sa(X+1) a(-2)      # X increments: -2→-1→0(stop)
```

**Termination Rule**: When a numeric argument is ≤ 0, the function returns empty (recursion stops).

### Comments

```h2
# This is a comment
0: srl  # Inline comment
// C-style comments also work
```

### Implementation Notes

#### Whitespace Handling

- **Agent ID**: Agent IDs must appear at the start of a line. Leading spaces/tabs before the agent ID are permitted and treated as line-start context.
- **Function/Macro Definitions**: No whitespace is allowed between the identifier and `(` in function definitions (e.g., `f(X):...` is valid, `f (X):...` is not).
- **Spaces**: Spaces and tabs between tokens are generally ignored except where they affect line-start detection.

#### Recursion and Termination

- **Maximum Recursion Depth**: The expander has a maximum recursion depth of **100** to prevent stack overflow from deeply nested macro/function calls. Exceeding this limit results in an expansion error.
- **Numeric Termination**: When any numeric argument becomes ≤ 0, the function call returns an empty sequence (no commands). This applies to all numeric parameters in the function.
- **Expansion Limit**: There is no explicit limit on the total number of expanded commands, but deeply recursive patterns may hit the depth limit first.

#### Error Handling

Compilation errors include:
- **Line and column information** for precise error location
- **Expected vs. found tokens** for parse errors
- **Undefined macro/function references**
- **Maximum recursion depth exceeded**

## Examples

### Drawing Shapes

```h2
# Square (4 sides)
0: f(X):XXXX f(sssr)

# Triangle (3 sides)
0: f(X):XXX f(ssssrr)

# Spiral
0: a(X):sra(X-1) a(8)
```

### Multi-Robot Choreography

```h2
# Two robots moving in mirror pattern
0: srlsrl
1: slrslr

# Three robots with different patterns
0: f(X):XXXX f(sr)
1: f(X):XXXX f(sl)
2: ssssssss
```

### Complex Recursion

```h2
# Nested function calls
0: f(X):XX f(f(s))      # f(s)=ss, f(ss)=ssss → 4 commands

# Parameterized repetition
0: a(X,Y):Ya(X-1,Y) a(3,sr)  # srsrsr (repeat 'sr' 3 times)
```

## API Reference

### Rust (Native)

```rust
use h2lang::compile_native;
use h2lang::output::CompileResult;

let result = compile_native("0: srl\n1: lrs");

match result {
    CompileResult::Success { program } => {
        println!("Agents: {}", program.agents.len());
        println!("Max steps: {}", program.max_steps);
        for entry in &program.timeline {
            println!("Step {}: {:?}", entry.step, entry.agent_commands);
        }
    }
    CompileResult::Error { errors } => {
        for err in errors {
            eprintln!("Error at {}:{}: {}", err.line, err.column, err.message);
        }
    }
}
```

### JavaScript/TypeScript (WebAssembly)

```javascript
import init, { compile, validate, version } from 'h2lang';

await init();

// Compile source code
const result = compile('0: srl');
if (result.status === 'success') {
  console.log(result.program.timeline);  // Parallel execution timeline
  console.log(result.program.agents);    // Per-agent command lists
}

// Validate without compiling
const validation = validate('0: srl');
console.log(validation.valid);  // true or false

// Get compiler version
console.log(version());  // "0.1.0"
```

### Output Format

The compiler produces a JSON structure:

```json
{
  "status": "success",
  "program": {
    "agents": [
      {
        "id": 0,
        "commands": [
          {"type": "straight", "steps": 1},
          {"type": "rotate_right", "angle": 90},
          {"type": "rotate_left", "angle": -90}
        ]
      }
    ],
    "max_steps": 3,
    "timeline": [
      {
        "step": 0,
        "agent_commands": [
          {"agent_id": 0, "command": {"type": "straight", "steps": 1}}
        ]
      }
    ]
  }
}
```

## Building from Source

### WebAssembly Build

```bash
# Install wasm-pack if not already installed
cargo install wasm-pack

# Build for web
npm run build
# or
wasm-pack build --target web --out-dir pkg

# Build for Node.js
wasm-pack build --target nodejs --out-dir pkg
```

### Native Build

```bash
# Debug build
cargo build

# Release build
cargo build --release

# Run tests
cargo test

# Generate documentation
cargo doc --no-deps --open
```

## Testing

```bash
# Run all tests (241 tests)
cargo test

# Run tests with output
cargo test -- --nocapture

# Run specific test module
cargo test basic_commands

# WebAssembly tests (requires Chrome)
wasm-pack test --headless --chrome
```

## Project Structure

```
h2lang/
├── .github/
│   ├── workflows/
│   │   └── ci.yml              # CI pipeline (fmt, clippy, test, wasm)
│   ├── ISSUE_TEMPLATE/         # Issue templates
│   └── PULL_REQUEST_TEMPLATE.md
├── src/
│   ├── lib.rs          # Main entry point, WASM bindings
│   ├── lexer.rs        # Tokenizer
│   ├── parser.rs       # Recursive descent parser
│   ├── ast.rs          # Abstract Syntax Tree definitions
│   ├── expander.rs     # Macro/function expansion
│   ├── scheduler.rs    # Multi-agent parallel scheduling
│   ├── output.rs       # JSON output structures
│   ├── token.rs        # Token definitions
│   └── error.rs        # Error types
├── tests/
│   └── h_language_compatibility.rs  # 145 HOJ compatibility tests
├── Cargo.toml          # Rust dependencies
├── package.json        # npm configuration
├── rust-toolchain.toml # Rust toolchain configuration
├── CONTRIBUTING.md     # Contribution guidelines
├── CODE_OF_CONDUCT.md  # Community guidelines (Contributor Covenant)
├── CHANGELOG.md        # Version history
└── LICENSE             # MIT License
```

### Architecture

```
Source Code → Lexer → Parser → AST → Expander → Scheduler → Output
     ↓          ↓        ↓       ↓        ↓          ↓         ↓
   "0:srl"   Tokens   Parse   Tree   Commands   Timeline    JSON
                      Tree          (expanded)  (parallel)
```

## Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

### Quick Contribution Guide

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Write tests for new functionality
4. Ensure all tests pass (`cargo test`)
5. Format code (`cargo fmt`)
6. Run linter (`cargo clippy`)
7. Commit with clear messages following [Conventional Commits]https://www.conventionalcommits.org/
8. Open a Pull Request

### Development Commands

```bash
# Format code
cargo fmt

# Run linter
cargo clippy -- -D warnings

# Run all checks before PR
cargo fmt --check && cargo clippy -- -D warnings && cargo test
```

## Community

- [GitHub Issues]https://github.com/ekusiadadus/h2lang/issues - Bug reports and feature requests
- [GitHub Discussions]https://github.com/ekusiadadus/h2lang/discussions - Questions and ideas

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Related Links

- [Herbert Online Judge]http://herbert.tealang.info/ - Original HOJ platform
- [HOJ GitHub]https://github.com/quolc/hoj - HOJ source code
- [Codeforces Discussion]https://codeforces.com/blog/entry/5579 - Community discussion
- [wasm-bindgen]https://rustwasm.github.io/wasm-bindgen/ - Rust/WebAssembly bindings

## Acknowledgments

- Herbert Online Judge by [@quolc]https://github.com/quolc
- Microsoft ImagineCup for the original Herbert game concept
- The Rust community for excellent tooling