-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Overview
This issue tracks the implementation of Tier 1 core language features required to run examples/simple.naml. These are foundational features that many other language constructs depend on.
Features
1. Enums with Variants
Used in: simple.naml lines 152-166
enum UserStatus {
Active,
Inactive,
Suspended(string), // variant with associated data
PendingVerification(string),
Deleted(int)
}
// Usage
var status: UserStatus = UserStatus.Active;
var suspended: UserStatus = UserStatus::Suspended("policy violation");
Implementation Requirements:
-
Runtime representation - Tagged union structure:
#[repr(C)] pub struct NamlEnum { pub header: HeapHeader, pub variant_tag: u32, // which variant pub data_size: u32, // size of associated data // associated data follows (if any) }
-
Codegen changes (
codegen/cranelift/mod.rs):- Handle
Expression::Pathfor enum variant access (UserStatus::Active) - Handle
Expression::Callfor variants with data (UserStatus::Suspended("reason")) - Extend switch/case to pattern match on enum tags
- Implement enum comparison (
==,!=)
- Handle
-
Runtime functions (
runtime/enum.rs):naml_enum_new(type_id, variant_tag, data_ptr, data_size) -> *mut NamlEnumnaml_enum_get_tag(enum_ptr) -> u32naml_enum_get_data(enum_ptr) -> *mut u8naml_enum_incref/decref
2. Option Type
Used in: simple.naml lines 141, 173-183, 239, etc.
pub extension: option<string>
var first_name: option<string> = none;
var node: LinkedListNode<T> = self.tail else { return; }
self.first_name.or_default("")
optional.is_some()
optional.is_none()
some(value)
Implementation Requirements:
-
Runtime representation - Can be implemented as a special enum:
// Option is tag=0 for none, tag=1 for some // When some, data follows the tag
-
Codegen changes:
- Handle
noneliteral →naml_option_none() - Handle
some(value)constructor →naml_option_some(value) - Handle
.is_some(),.is_none()method calls - Handle
.or_default(value)method - Critical: Handle
var x = optional else { ... }pattern:if optional.is_none() { execute else block (may contain return/break) } else { x = optional.unwrap() }
- Handle
-
Runtime functions (
runtime/option.rs):naml_option_none() -> i64(returns tagged none)naml_option_some(value: i64) -> i64(returns tagged some)naml_option_is_some(opt: i64) -> boolnaml_option_is_none(opt: i64) -> boolnaml_option_unwrap(opt: i64) -> i64naml_option_or_default(opt: i64, default: i64) -> i64
3. Map Type
Used in: simple.naml lines 179, 424, 704-708
pub metadata: map<string, string>
pub headers: map<string, string>
return { "user_id": self.user_id.value, "email": self.email }
self.headers[name] = value
return self.headers[name]
Implementation Requirements:
-
Runtime representation:
#[repr(C)] pub struct NamlMap { pub header: HeapHeader, pub capacity: usize, pub length: usize, pub buckets: *mut MapBucket, // hash buckets } #[repr(C)] pub struct MapBucket { pub key: i64, pub value: i64, pub next: *mut MapBucket, // for chaining }
-
Codegen changes:
- Handle
Expression::Mapfor map literals{ "key": "value" } - Handle
Expression::Indexfor map accessmap[key] - Handle map assignment
map[key] = value - Handle map in struct fields
- Handle
-
Runtime functions (
runtime/map.rs):naml_map_new(capacity: usize) -> *mut NamlMapnaml_map_set(map: *mut NamlMap, key: i64, value: i64)naml_map_get(map: *mut NamlMap, key: i64) -> i64(returns option)naml_map_contains(map: *mut NamlMap, key: i64) -> boolnaml_map_remove(map: *mut NamlMap, key: i64) -> boolnaml_map_len(map: *mut NamlMap) -> i64naml_map_incref/decrefnaml_string_hash(str: *const u8) -> u64(for string keys)
4. Generics
Used in: simple.naml lines 5-30, 237-418, 736-836
interface Comparable<T> { ... }
pub struct LinkedList<T> implements Collection<T> { ... }
pub fn map_array<T, U>(arr: [T], f: fn(T) -> U) -> [U]
pub struct BinarySearchTree<T: Comparable<T>> { ... }
Implementation Requirements:
-
Monomorphization approach (recommended for JIT):
- At compile time, instantiate generic types/functions for each concrete type used
LinkedList<int>becomes a separate compiled struct fromLinkedList<string>
-
Codegen changes:
- Track generic instantiations during type checking
- Generate separate code for each instantiation
- Handle trait bounds (
T: Comparable<T>) by verifying method existence
-
Typechecker changes (
typechecker/):- Already handles generic type parameters
- Need to track which concrete instantiations are used
- Pass instantiation info to codegen
Files to Modify
| File | Changes |
|---|---|
namlc/src/runtime/mod.rs |
Add option, map, enum modules |
namlc/src/runtime/option.rs |
New file - option type implementation |
namlc/src/runtime/map.rs |
New file - hash map implementation |
namlc/src/runtime/enum.rs |
New file - enum runtime support |
namlc/src/codegen/cranelift/mod.rs |
Handle new expression types |
namlc/src/typechecker/mod.rs |
Track generic instantiations |
Testing
Create incremental test files:
// test_option.naml
fn main() {
var x: option<int> = some(42);
var y: option<int> = none;
if (x.is_some()) {
println("x has value");
}
var val: int = x.or_default(0);
println(val);
var unwrapped: int = x else {
println("x was none");
return;
};
println(unwrapped);
}
// test_enum.naml
enum Color {
Red,
Green,
Blue,
Custom(int, int, int)
}
fn main() {
var c: Color = Color.Red;
var custom: Color = Color::Custom(255, 128, 0);
switch (c) {
case Red: println("red");
case Green: println("green");
case Blue: println("blue");
case Custom(r, g, b): {
print("rgb: ");
println(r);
}
}
}
Priority
High - These features are prerequisites for most of simple.naml and block Tier 2 and Tier 3 features.