Skip to content
Merged
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
136 changes: 67 additions & 69 deletions examples/simple.naml
Original file line number Diff line number Diff line change
Expand Up @@ -465,11 +465,11 @@ pub fn (self: HttpResponse) is_server_error() -> bool {
}

interface HttpClient {
async fn get(url: string) -> HttpResponse throws NetworkError;
async fn post(url: string, body: bytes) -> HttpResponse throws NetworkError;
async fn put(url: string, body: bytes) -> HttpResponse throws NetworkError;
async fn delete(url: string) -> HttpResponse throws NetworkError;
async fn request(req: HttpRequest) -> HttpResponse throws NetworkError;
fn get(url: string) -> HttpResponse throws NetworkError;
fn post(url: string, body: bytes) -> HttpResponse throws NetworkError;
fn put(url: string, body: bytes) -> HttpResponse throws NetworkError;
fn delete(url: string) -> HttpResponse throws NetworkError;
fn request(req: HttpRequest) -> HttpResponse throws NetworkError;
}

pub struct SimpleHttpClient implements HttpClient {
Expand All @@ -480,54 +480,54 @@ pub struct SimpleHttpClient implements HttpClient {
pub retry_delay_ms: int
}

pub async fn (self: SimpleHttpClient) get(url: string) -> HttpResponse throws NetworkError {
pub fn (self: SimpleHttpClient) get(url: string) -> HttpResponse throws NetworkError {
var req: HttpRequest = HttpRequest {
method: "GET",
url: self.base_url + url,
headers: self.default_headers,
body: none,
timeout_ms: self.timeout_ms
};
return await self.request(req);
return self.request(req);
}

pub async fn (self: SimpleHttpClient) post(url: string, body: bytes) -> HttpResponse throws NetworkError {
pub fn (self: SimpleHttpClient) post(url: string, body: bytes) -> HttpResponse throws NetworkError {
var req: HttpRequest = HttpRequest {
method: "POST",
url: self.base_url + url,
headers: self.default_headers,
body: some(body),
timeout_ms: self.timeout_ms
};
return await self.request(req);
return self.request(req);
}

pub async fn (self: SimpleHttpClient) put(url: string, body: bytes) -> HttpResponse throws NetworkError {
pub fn (self: SimpleHttpClient) put(url: string, body: bytes) -> HttpResponse throws NetworkError {
var req: HttpRequest = HttpRequest {
method: "PUT",
url: self.base_url + url,
headers: self.default_headers,
body: some(body),
timeout_ms: self.timeout_ms
};
return await self.request(req);
return self.request(req);
}

pub async fn (self: SimpleHttpClient) delete(url: string) -> HttpResponse throws NetworkError {
pub fn (self: SimpleHttpClient) delete(url: string) -> HttpResponse throws NetworkError {
var req: HttpRequest = HttpRequest {
method: "DELETE",
url: self.base_url + url,
headers: self.default_headers,
body: none,
timeout_ms: self.timeout_ms
};
return await self.request(req);
return self.request(req);
}

pub async fn (self: SimpleHttpClient) request(req: HttpRequest) -> HttpResponse throws NetworkError {
pub fn (self: SimpleHttpClient) request(req: HttpRequest) -> HttpResponse throws NetworkError {
var attempts: int = 0;
while (attempts < self.retry_count) {
var response: HttpResponse = await self.do_request(req);
var response: HttpResponse = self.do_request(req);
if (response.is_success()) {
return response;
}
Expand All @@ -540,7 +540,7 @@ pub async fn (self: SimpleHttpClient) request(req: HttpRequest) -> HttpResponse
}
attempts = attempts + 1;
if (attempts < self.retry_count) {
await sleep(self.retry_delay_ms);
sleep(self.retry_delay_ms);
}
}
throw NetworkError {
Expand All @@ -550,7 +550,7 @@ pub async fn (self: SimpleHttpClient) request(req: HttpRequest) -> HttpResponse
};
}

async fn (self: SimpleHttpClient) do_request(req: HttpRequest) -> HttpResponse {
fn (self: SimpleHttpClient) do_request(req: HttpRequest) -> HttpResponse {
return HttpResponse {
status_code: 200,
status_text: "OK",
Expand All @@ -567,83 +567,83 @@ extern fn sleep(ms: int) -> promise<unit>;
// =============================================================================

interface Repository<T, ID> {
async fn find_by_id(id: ID) -> option<T> throws DatabaseError;
async fn find_all() -> [T] throws DatabaseError;
async fn save(entity: T) -> T throws DatabaseError;
async fn delete(id: ID) -> bool throws DatabaseError;
async fn exists(id: ID) -> bool throws DatabaseError;
async fn count() -> int throws DatabaseError;
fn find_by_id(id: ID) -> option<T> throws DatabaseError;
fn find_all() -> [T] throws DatabaseError;
fn save(entity: T) -> T throws DatabaseError;
fn delete(id: ID) -> bool throws DatabaseError;
fn exists(id: ID) -> bool throws DatabaseError;
fn count() -> int throws DatabaseError;
}

pub struct UserRepository implements Repository<User, UserId> {
pub connection_string: string,
pub table_name: string
}

pub async fn (self: UserRepository) find_by_id(id: UserId) -> option<User> throws DatabaseError {
pub fn (self: UserRepository) find_by_id(id: UserId) -> option<User> throws DatabaseError {
var query: string = "SELECT * FROM " + self.table_name + " WHERE id = ?";
var result: [map<string, string>] = await self.execute_query(query, [id.value]);
var result: [map<string, string>] = self.execute_query(query, [id.value]);
if (result.length == 0) {
return none;
}
return some(self.map_row_to_user(result[0]));
}

pub async fn (self: UserRepository) find_all() -> [User] throws DatabaseError {
pub fn (self: UserRepository) find_all() -> [User] throws DatabaseError {
var query: string = "SELECT * FROM " + self.table_name;
var result: [map<string, string>] = await self.execute_query(query, []);
var result: [map<string, string>] = self.execute_query(query, []);
var users: [User] = [];
for (row in result) {
users.push(self.map_row_to_user(row));
}
return users;
}

pub async fn (self: UserRepository) save(entity: User) -> User throws DatabaseError {
var existing: option<User> = await self.find_by_id(entity.id);
pub fn (self: UserRepository) save(entity: User) -> User throws DatabaseError {
var existing: option<User> = self.find_by_id(entity.id);
if (existing.is_some()) {
return await self.update(entity);
return self.update(entity);
}
return await self.insert(entity);
return self.insert(entity);
}

async fn (self: UserRepository) insert(entity: User) -> User throws DatabaseError {
fn (self: UserRepository) insert(entity: User) -> User throws DatabaseError {
var query: string = "INSERT INTO " + self.table_name + " (id, email, username) VALUES (?, ?, ?)";
await self.execute_update(query, [entity.id.value, entity.email.to_string(), entity.username]);
self.execute_update(query, [entity.id.value, entity.email.to_string(), entity.username]);
return entity;
}

async fn (self: UserRepository) update(entity: User) -> User throws DatabaseError {
fn (self: UserRepository) update(entity: User) -> User throws DatabaseError {
var query: string = "UPDATE " + self.table_name + " SET email = ?, username = ? WHERE id = ?";
await self.execute_update(query, [entity.email.to_string(), entity.username, entity.id.value]);
self.execute_update(query, [entity.email.to_string(), entity.username, entity.id.value]);
return entity;
}

pub async fn (self: UserRepository) delete(id: UserId) -> bool throws DatabaseError {
pub fn (self: UserRepository) delete(id: UserId) -> bool throws DatabaseError {
var query: string = "DELETE FROM " + self.table_name + " WHERE id = ?";
var affected: int = await self.execute_update(query, [id.value]);
var affected: int = self.execute_update(query, [id.value]);
return affected > 0;
}

pub async fn (self: UserRepository) exists(id: UserId) -> bool throws DatabaseError {
pub fn (self: UserRepository) exists(id: UserId) -> bool throws DatabaseError {
var query: string = "SELECT COUNT(*) FROM " + self.table_name + " WHERE id = ?";
var result: [map<string, string>] = await self.execute_query(query, [id.value]);
var result: [map<string, string>] = self.execute_query(query, [id.value]);
var count_str: string = result[0]["count"].or_default("0");
return count_str > "0";
}

pub async fn (self: UserRepository) count() -> int throws DatabaseError {
pub fn (self: UserRepository) count() -> int throws DatabaseError {
var query: string = "SELECT COUNT(*) as cnt FROM " + self.table_name;
var result: [map<string, string>] = await self.execute_query(query, []);
var result: [map<string, string>] = self.execute_query(query, []);
var cnt_str: string = result[0]["cnt"].or_default("0");
return cnt_str as int;
}

async fn (self: UserRepository) execute_query(query: string, params: [string]) -> [map<string, string>] throws DatabaseError {
fn (self: UserRepository) execute_query(query: string, params: [string]) -> [map<string, string>] throws DatabaseError {
return [];
}

async fn (self: UserRepository) execute_update(query: string, params: [string]) -> int throws DatabaseError {
fn (self: UserRepository) execute_update(query: string, params: [string]) -> int throws DatabaseError {
return 1;
}

Expand Down Expand Up @@ -679,12 +679,12 @@ interface Event {
}

interface EventHandler<E: Event> {
async fn handle(event: E) throws;
fn handle(event: E) throws;
}

interface EventBus {
fn subscribe<E: Event>(handler: EventHandler<E>);
async fn publish<E: Event>(event: E);
fn publish<E: Event>(event: E);
}

pub struct UserCreatedEvent implements Event {
Expand Down Expand Up @@ -827,13 +827,14 @@ pub fn min_value<T: Comparable<T>>(a: T, b: T) -> T {
return b;
}

pub fn compose<A, B, C>(f: fn(B) -> C, g: fn(A) -> B) -> fn(A) -> C {
return |a: A| f(g(a));
}

pub fn curry2<A, B, C>(f: fn(A, B) -> C) -> fn(A) -> fn(B) -> C {
return |a: A| |b: B| f(a, b);
}
// Note: compose and curry2 require advanced function type syntax not yet supported
// pub fn compose<A, B, C>(f: fn(B) -> C, g: fn(A) -> B) -> fn(A) -> C {
// return |a: A| f(g(a));
// }
//
// pub fn curry2<A, B, C>(f: fn(A, B) -> C) -> fn(A) -> fn(B) -> C {
// return |a: A| |b: B| f(a, b);
// }

// =============================================================================
// Concurrency Patterns
Expand All @@ -844,9 +845,9 @@ pub struct Mutex<T> {
pub locked: bool
}

pub async fn (mut self: Mutex<T>) lock() -> T {
pub fn (mut self: Mutex<T>) lock() -> T {
while (self.locked) {
await yield_now();
yield_now();
}
self.locked = true;
return self.value;
Expand All @@ -864,20 +865,20 @@ pub struct Channel<T> {
pub closed: bool
}

pub async fn (mut self: Channel<T>) send(value: T) -> bool {
pub fn (mut self: Channel<T>) send(value: T) -> bool {
if (self.closed) {
return false;
}
while (self.buffer.length >= self.capacity) {
await yield_now();
yield_now();
}
self.buffer.push(value);
return true;
}

pub async fn (mut self: Channel<T>) receive() -> option<T> {
pub fn (mut self: Channel<T>) receive() -> option<T> {
while (self.buffer.length == 0 && !self.closed) {
await yield_now();
yield_now();
}
if (self.buffer.length == 0) {
return none;
Expand All @@ -894,7 +895,7 @@ pub fn (mut self: Channel<T>) close() {
// Main Entry Point
// =============================================================================

async fn main() {
fn main() {
var client: SimpleHttpClient = SimpleHttpClient {
base_url: "https://api.example.com",
default_headers: HttpHeaders { headers: { "Content-Type": "application/json" } },
Expand All @@ -910,15 +911,15 @@ async fn main() {

var user_id: UserId = UserId { value: "user-123" };

var user_opt: option<User> = await user_repo.find_by_id(user_id);
var user_opt: option<User> = user_repo.find_by_id(user_id);

var user: User = user_opt else {
printf("User not found");
return;
}
printf("Found user: {}", user.full_name());

var response: HttpResponse = await client.get("/users/" + user_id.value);
var response: HttpResponse = client.get("/users/" + user_id.value);
if (response.is_success()) {
printf("API call successful: {} {}", response.status_code, response.status_text);
}
Expand Down Expand Up @@ -963,13 +964,10 @@ async fn main() {

printf("Active admins: {}", active_admins.length);

var tasks: [promise<HttpResponse>] = [];
for (i in 0..10) {
tasks.push(client.get("/items/" + (i as string)));
}

for (task in tasks) {
var response: HttpResponse = await task;
printf("Task completed: {}", response.status_code);
// Note: promise type and async task patterns removed as async/await is not supported
// Running synchronous requests instead
for (i: int in 0..10) {
var response: HttpResponse = client.get("/items/" + (i as string));
println("Task completed: {}", response.status_code);
}
}
47 changes: 47 additions & 0 deletions examples/test_generic_methods.naml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
///
/// Test: Generic Methods on Types
///

pub struct Box<T> {
pub value: T
}

pub fn (self: Box<T>) get_value() -> T {
return self.value;
}

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

pub fn (self: Pair<A, B>) get_first() -> A {
return self.first;
}

pub fn (self: Pair<A, B>) get_second() -> B {
return self.second;
}

fn main() {
println("=== Generic Method Tests ===");

// Test Box<int>
var int_box: Box<int> = Box { value: 42 };
print("Box<int>.get_value(): ");
println(int_box.get_value());

// Test Box<string>
var str_box: Box<string> = Box { value: "hello" };
print("Box<string>.get_value(): ");
println(str_box.get_value());

// Test Pair<int, string>
var pair: Pair<int, string> = Pair { first: 1, second: "one" };
print("Pair.get_first(): ");
println(pair.get_first());
print("Pair.get_second(): ");
println(pair.get_second());

println("=== Generic Method Tests Complete ===");
}
10 changes: 0 additions & 10 deletions examples/test_map.naml

This file was deleted.

Loading