Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
409 changes: 160 additions & 249 deletions .claude/TODO.md

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,19 @@
"Bash(grep:*)",
"Bash(cat:*)",
"mcp__ide__getDiagnostics",
"Bash(cargo test:*)"
"Bash(cargo test:*)",
"Bash(cargo build:*)",
"Bash(cargo run:*)",
"Bash(xargs ls:*)",
"Bash(cargo check:*)",
"Bash(find:*)",
"Bash(gh issue create --title \"Fix Remaining 35 Rust Codegen Compilation Errors\" --body \"$\\(cat <<''EOF''\n## Problem\n\nThe Rust code generated by `naml run` produces 35 compilation errors, preventing programs from executing.\n\n## Error Breakdown\n\n| Error | Count | Root Cause |\n|-------|-------|------------|\n| E0308 | 17 | Type mismatches \\(closures ≠ fn pointers, compare method\\) |\n| E0382 | 8 | Use of moved value |\n| E0594 | 2 | Parameter needs `mut` keyword |\n| E0599 | 3 | Missing methods \\(compare, iter on String\\) |\n| E0277 | 3 | Missing trait bounds |\n| E0505/E0507 | 3 | Borrow/move conflicts |\n\n## Implementation Plan\n\n### 1. Fix Closure Return Types \\(E0308\\)\n- [ ] Detect when return type is `fn\\(A\\) -> B` and closure is returned\n- [ ] Change codegen to use `impl Fn\\(A\\) -> B` or `Box<dyn Fn\\(A\\) -> B>`\n- [ ] Handle closure capture semantics\n\n### 2. Add Parameter Mutability \\(E0594\\)\n- [ ] Analyze function body for assignments to parameters\n- [ ] Add `mut` keyword to parameters that are mutated\n- [ ] Create AST visitor to detect mutations\n\n### 3. Fix Use-After-Move \\(E0382\\)\n- [ ] Track variable usage in struct literals\n- [ ] Clone fields when used multiple times\n- [ ] Handle loop variable reuse\n\n### 4. Remove compare\\(\\) Method \\(E0599\\)\n- [ ] Replace `a.compare\\(b\\)` with `a.partial_cmp\\(&b\\)`\n- [ ] Or use comparison operators directly\n- [ ] Update generic function codegen\n\n### 5. Fix Remaining Borrow Conflicts \\(E0505/E0507\\)\n- [ ] Clone self fields before unwrap in `&self` methods\n- [ ] Use `.as_ref\\(\\)` where appropriate\n\n## Files to Modify\n\n- `namlc/src/codegen/rust/expressions.rs`\n- `namlc/src/codegen/rust/statements.rs`\n- `namlc/src/codegen/rust/mod.rs`\n\n## Acceptance Criteria\n\n- [ ] `naml run examples/simple.naml` compiles with 0 Rust errors\n- [ ] All existing tests pass\n- [ ] Generated Rust code is idiomatic\n\n## Related\n\n- Continues work from #3\nEOF\n\\)\" --label \"enhancement\" --label \"priority:critical\")",
"Bash(gh issue create --title \"Fix Remaining 35 Rust Codegen Compilation Errors\" --body \"$\\(cat <<''EOF''\n## Priority: 🔴 Critical\n\nThe Rust code generated by `naml run` produces 35 compilation errors, preventing programs from executing.\n\n## Error Breakdown\n\n| Error | Count | Root Cause |\n|-------|-------|------------|\n| E0308 | 17 | Type mismatches \\(closures ≠ fn pointers, compare method\\) |\n| E0382 | 8 | Use of moved value |\n| E0594 | 2 | Parameter needs `mut` keyword |\n| E0599 | 3 | Missing methods \\(compare, iter on String\\) |\n| E0277 | 3 | Missing trait bounds |\n| E0505/E0507 | 3 | Borrow/move conflicts |\n\n## Implementation Plan\n\n### 1. Fix Closure Return Types \\(E0308\\)\n- [ ] Detect when return type is `fn\\(A\\) -> B` and closure is returned\n- [ ] Change codegen to use `impl Fn\\(A\\) -> B` or `Box<dyn Fn\\(A\\) -> B>`\n- [ ] Handle closure capture semantics\n\n### 2. Add Parameter Mutability \\(E0594\\)\n- [ ] Analyze function body for assignments to parameters\n- [ ] Add `mut` keyword to parameters that are mutated\n- [ ] Create AST visitor to detect mutations\n\n### 3. Fix Use-After-Move \\(E0382\\)\n- [ ] Track variable usage in struct literals\n- [ ] Clone fields when used multiple times\n- [ ] Handle loop variable reuse\n\n### 4. Remove compare\\(\\) Method \\(E0599\\)\n- [ ] Replace `a.compare\\(b\\)` with `a.partial_cmp\\(&b\\)`\n- [ ] Or use comparison operators directly\n- [ ] Update generic function codegen\n\n### 5. Fix Remaining Borrow Conflicts \\(E0505/E0507\\)\n- [ ] Clone self fields before unwrap in `&self` methods\n- [ ] Use `.as_ref\\(\\)` where appropriate\n\n## Files to Modify\n\n- `namlc/src/codegen/rust/expressions.rs`\n- `namlc/src/codegen/rust/statements.rs`\n- `namlc/src/codegen/rust/mod.rs`\n\n## Acceptance Criteria\n\n- [ ] `naml run examples/simple.naml` compiles with 0 Rust errors\n- [ ] All existing tests pass\n- [ ] Generated Rust code is idiomatic\n\n## Related\n\n- Continues work from #3\nEOF\n\\)\" --label \"enhancement\")",
"Bash(gh issue view:*)",
"Skill(superpowers:using-git-worktrees)",
"Skill(superpowers:writing-plans)",
"Bash(gh issue list:*)",
"Bash(gh issue create:*)"
]
},
"hooks": {
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ rust-project.json


.naml_build/
settings.local.json
settings.local.json

.worktrees/
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ memchr = "2.7"
##
bumpalo = { version = "3.16", features = ["collections"] }

##
## C library bindings for runtime
##
libc = "0.2"

[profile.release]
lto = true
codegen-units = 1
Expand Down
30 changes: 30 additions & 0 deletions examples/arrays.naml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
fn main() {
println("Testing arrays with for loop:");

var arr: [int] = [10, 20, 30, 40, 50];

print("Array length: ");
println(arr.len());

println("Iterating with for loop:");
for (val in arr) {
print(" Value: ");
println(val);
}

println("Iterating with index:");
for (i, val in arr) {
print(" arr[");
print(i);
print("] = ");
println(val);
}

println("Sum of elements:");
var sum: int = 0;
for (val in arr) {
sum = sum + val;
}
print(" Total: ");
println(sum);
}
46 changes: 46 additions & 0 deletions examples/channels.naml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
fn main() {
println("Testing channels:");

// Create a channel with capacity 5
var ch: channel<int> = make_channel(5);

// Send values
println("Sending values...");
ch.send(10);
ch.send(20);
ch.send(30);

// Receive values
println("Receiving values...");
var v1: int = ch.receive();
print("Received: ");
println(v1);

var v2: int = ch.receive();
print("Received: ");
println(v2);

var v3: int = ch.receive();
print("Received: ");
println(v3);

// Test with a loop
println("Testing channel with loop:");
var i: int = 0;
while (i < 5) {
ch.send(i * 10);
i = i + 1;
}

var sum: int = 0;
i = 0;
while (i < 5) {
sum = sum + ch.receive();
i = i + 1;
}
print("Sum of received values: ");
println(sum);

ch.close();
println("Channel closed.");
}
18 changes: 18 additions & 0 deletions examples/ffi.naml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Declare external C functions from libc
extern fn abs(x: int) -> int;
extern fn labs(x: int) -> int;

fn main() {
println("Testing FFI with libc functions:");

var x: int = -42;
print("abs(-42) = ");
println(abs(x));

var y: int = -100;
print("labs(-100) = ");
println(labs(y));

print("abs(10) = ");
println(abs(10));
}
27 changes: 27 additions & 0 deletions examples/ffi_math.naml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Declare external C math functions
extern fn sqrt(x: float) -> float;
extern fn sin(x: float) -> float;
extern fn cos(x: float) -> float;
extern fn pow(base: float, exp: float) -> float;
extern fn floor(x: float) -> float;
extern fn ceil(x: float) -> float;

fn main() {
println("Testing FFI with math functions:");

print("sqrt(16.0) = ");
var s: float = sqrt(16.0);
println(s);

print("pow(2.0, 10.0) = ");
var p: float = pow(2.0, 10.0);
println(p);

print("floor(3.7) = ");
var f: float = floor(3.7);
println(f);

print("ceil(3.2) = ");
var c: float = ceil(3.2);
println(c);
}
180 changes: 180 additions & 0 deletions examples/generics_test.naml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
///
/// Generics Test - Basic generic features
///

enum UserStatus {
Active,
Inactive,
Suspended(string),
PendingVerification(string)
}

enum Result<T, E> {
Ok(T),
Err(E)
}

struct Pair<A, B> {
first: A,
second: B
}

struct Box<T> {
value: T
}

fn test_user_status() {
println("=== UserStatus Enum Tests ===");

var active: UserStatus = UserStatus::Active;
var inactive: UserStatus = UserStatus::Inactive;
var suspended: UserStatus = UserStatus::Suspended("policy violation");
var pending: UserStatus = UserStatus::PendingVerification("email sent");

print("Testing Active: ");
switch (active) {
case Active: {
println("PASS");
}
default: {
println("FAIL");
}
}

print("Testing Inactive: ");
switch (inactive) {
case Inactive: {
println("PASS");
}
default: {
println("FAIL");
}
}

print("Testing Suspended with data: ");
switch (suspended) {
case Suspended(reason): {
print("PASS - reason: ");
println(reason);
}
default: {
println("FAIL");
}
}

print("Testing PendingVerification: ");
switch (pending) {
case PendingVerification(msg): {
print("PASS - msg: ");
println(msg);
}
default: {
println("FAIL");
}
}

print("Testing switch default for Inactive: ");
switch (inactive) {
case Active: {
println("FAIL");
}
case Suspended(r): {
println("FAIL");
}
default: {
println("PASS - matched default");
}
}
}

fn test_generic_struct() {
println("=== Generic Struct Tests ===");

var int_pair: Pair<int, int> = Pair { first: 10, second: 20 };

print("Testing Pair<int, int>.first: ");
if (int_pair.first == 10) {
println("PASS");
} else {
println("FAIL");
}

print("Testing Pair<int, int>.second: ");
if (int_pair.second == 20) {
println("PASS");
} else {
println("FAIL");
}

var mixed_pair: Pair<string, int> = Pair { first: "hello", second: 42 };

print("Testing Pair<string, int>.first: ");
if (mixed_pair.first == "hello") {
println("PASS");
} else {
println("FAIL");
}

print("Testing Pair<string, int>.second: ");
if (mixed_pair.second == 42) {
println("PASS");
} else {
println("FAIL");
}

var nested: Pair<Box<int>, string> = Pair { first: Box { value: 100 }, second: "nested" };
print("Testing nested generic: ");
if (nested.second == "nested") {
println("PASS");
} else {
println("FAIL");
}
}

fn test_generic_box() {
println("=== Generic Box Tests ===");

var int_box: Box<int> = Box { value: 42 };
print("Testing Box<int>.value: ");
if (int_box.value == 42) {
println("PASS");
} else {
println("FAIL");
}

var str_box: Box<string> = Box { value: "boxed string" };
print("Testing Box<string>.value: ");
if (str_box.value == "boxed string") {
println("PASS");
} else {
println("FAIL");
}

var point_box: Box<Pair<int, int>> = Box { value: Pair { first: 1, second: 2 } };
print("Testing Box<Pair>.value.first: ");
if (point_box.value.first == 1) {
println("PASS");
} else {
println("FAIL");
}
}

fn main() {
println("========================================");
println(" NAML Generics Test ");
println("========================================");
println("");

test_user_status();
println("");

test_generic_struct();
println("");

test_generic_box();
println("");

println("========================================");
println(" Tests Completed! ");
println("========================================");
}
Loading