All examples live in the repository examples directory:
https://github.com/jordanhubbard/nanolang/tree/main/examples
Top-level examples
sdl_example_launcher.nano (View on GitHub)
advanced
beads_assert_with_bead.nano
# Example: Using assert_with_bead for automatic issue tracking
# This demonstrates the killer feature - assertions that create beads
from "stdlib/beads.nano" import assert_with_bead, assert_with_bead_context
# Example function with validation
fn divide(a: int, b: int) -> int {
# Use assert_with_bead instead of regular assert
# If this fails, it will create a P0 bug automatically
(assert_with_bead
(!= b 0)
"Division by zero detected"
0
"Attempted to divide by zero in divide() function"
)
return (/ a b)
}
shadow divide {
assert (== (divide 10 2) 5)
assert (== (divide 20 4) 5)
# Note: Can't test divide by zero in shadow test as it would create a bead
}
# Example: Data validation with automatic issue creation
fn validate_user_input(age: int, name: string) -> bool {
let mut all_valid: bool = true
# Age validation - creates P1 bug if fails
if (not (assert_with_bead
(and (>= age 0) (< age 150))
"Invalid age value detected"
1
(+ "Age validation failed: " (int_to_string age))
)) {
set all_valid false
}
# Name validation - creates P2 bug if fails
if (not (assert_with_bead
(> (str_length name) 0)
"Empty name detected"
2
"Name field cannot be empty"
)) {
set all_valid false
}
return all_valid
}
shadow validate_user_input {
assert (== (validate_user_input 25 "Alice") true)
assert (== (validate_user_input 30 "Bob") true)
}
# Example: Using context-aware assertions
fn process_array(arr: array<int>) -> int {
# Enhanced assertion with file/line context
(assert_with_bead_context
(> (array_length arr) 0)
"Empty array passed to process_array"
1
"beads_assert_with_bead.nano"
45
"process_array() requires non-empty array"
)
let mut sum: int = 0
for i in (range 0 (array_length arr)) {
set sum (+ sum (at arr i))
}
return sum
}
shadow process_array {
let test_arr: array<int> = (array_new 3 0)
(array_set test_arr 0 1)
(array_set test_arr 1 2)
(array_set test_arr 2 3)
assert (== (process_array test_arr) 6)
}
# Example: Batch validation with prioritized issues
fn validate_config(max_connections: int, timeout_ms: int, retry_count: int) -> bool {
let mut valid: bool = true
# Critical validation - P0
if (not (assert_with_bead
(> max_connections 0)
"Invalid max_connections: must be positive"
0
(+ "max_connections=" (int_to_string max_connections))
)) {
set valid false
}
# Important validation - P1
if (not (assert_with_bead
(>= timeout_ms 100)
"Timeout too low: may cause premature failures"
1
(+ "timeout_ms=" (int_to_string timeout_ms))
)) {
set valid false
}
# Nice-to-have validation - P3
if (not (assert_with_bead
(<= retry_count 10)
"Retry count excessive: may cause performance issues"
3
(+ "retry_count=" (int_to_string retry_count))
)) {
set valid false
}
return valid
}
shadow validate_config {
assert (== (validate_config 100 1000 3) true)
assert (== (validate_config 50 500 5) true)
}
fn main() -> int {
(println "=== assert_with_bead Example ===")
(println "")
(println "This example demonstrates automatic issue creation from assertions.")
(println "When an assertion fails, a bead is created automatically.")
(println "")
# Example 1: Basic assertion
(println "1. Testing divide function...")
let result1: int = (divide 10 2)
(println (+ " 10 / 2 = " (int_to_string result1)))
(println "")
# Example 2: Validation with multiple assertions
(println "2. Testing user input validation...")
let valid1: bool = (validate_user_input 25 "Alice")
(println (+ " validate_user_input(25, 'Alice') = " (if valid1 "valid" "invalid")))
let valid2: bool = (validate_user_input -5 "")
(println (+ " validate_user_input(-5, '') = " (if valid2 "valid" "invalid")))
(println " (If invalid, beads were created for the failures)")
(println "")
# Example 3: Array processing
(println "3. Testing array processing...")
let test_arr: array<int> = (array_new 3 0)
(array_set test_arr 0 5)
(array_set test_arr 1 10)
(array_set test_arr 2 15)
let sum: int = (process_array test_arr)
(println (+ " Sum of [5, 10, 15] = " (int_to_string sum)))
(println "")
# Example 4: Config validation
(println "4. Testing config validation...")
let config_valid: bool = (validate_config 100 1000 3)
(println (+ " validate_config(100, 1000, 3) = " (if config_valid "valid" "invalid")))
(println "")
(println "✓ Example complete!")
(println "")
(println "Check 'bd list' to see any beads created by failed assertions.")
return 0
}
shadow main {
assert (== (main) 0)
}
beads_basic_usage.nano
# Basic usage example for the beads module
# Demonstrates querying and creating beads programmatically
from "stdlib/beads.nano" import
Bead, BeadStats, BeadCreateOptions,
bd_open, bd_ready, bd_stats, bd_create, bd_close
fn main() -> int {
(println "=== Beads Module Basic Usage ===")
(println "")
# Get project statistics
(println "1. Getting project statistics...")
let stats: BeadStats = (bd_stats)
(println (+ " Total issues: " (int_to_string stats.total)))
(println (+ " Open: " (int_to_string stats.open)))
(println (+ " In Progress: " (int_to_string stats.in_progress)))
(println (+ " Closed: " (int_to_string stats.closed)))
(println (+ " Ready to work: " (int_to_string stats.ready_to_work)))
(println "")
# List open beads
(println "2. Listing open beads...")
let open_beads: array<Bead> = (bd_open)
(println (+ " Found " (+ (int_to_string (array_length open_beads)) " open beads")))
(println "")
# List ready-to-work beads
(println "3. Listing ready-to-work beads...")
let ready_beads: array<Bead> = (bd_ready)
(println (+ " Found " (+ (int_to_string (array_length ready_beads)) " ready beads")))
(println "")
# Create a new bead
(println "4. Creating a new test bead...")
let bead_id: string = (bd_create
"Example bead created from NanoLang"
"This bead was created programmatically using stdlib/beads.nano"
4
"task"
)
if (!= bead_id "") {
(println (+ " ✓ Created bead: " bead_id))
(println "")
# Close the test bead
(println "5. Closing the test bead...")
let closed: bool = (bd_close bead_id "Example completed - cleaning up test bead")
if closed {
(println " ✓ Bead closed successfully")
} else {
(println " ✗ Failed to close bead")
}
} else {
(println " ✗ Failed to create bead")
(println " (Note: bd command might not be available)")
}
(println "")
(println "Example complete!")
return 0
}
shadow main {
assert (== (main) 0)
}
beads_workflow_automation.nano
# Advanced example: Workflow automation with beads module
# Demonstrates programmatic issue management and triage
from "stdlib/beads.nano" import
Bead, BeadStats, BeadCreateOptions,
bd_open, bd_ready, bd_by_priority, bd_stats,
bd_create, bd_create_with_options, bd_close
# Automatically triage issues based on project state
fn auto_triage() -> int {
(println "=== Automatic Issue Triage ===")
(println "")
let stats: BeadStats = (bd_stats)
(println "Current project status:")
(println (+ " Open: " (int_to_string stats.open)))
(println (+ " In Progress: " (int_to_string stats.in_progress)))
(println (+ " Ready to work: " (int_to_string stats.ready_to_work)))
(println "")
# Check for urgent work
let p0_beads: array<Bead> = (bd_by_priority 0)
let p0_count: int = (array_length p0_beads)
if (> p0_count 0) {
(println "⚠️ URGENT: Found P0 issues!")
(println (+ " " (+ (int_to_string p0_count) " critical issues need immediate attention")))
return 1
}
# Check work capacity
if (> stats.ready_to_work 0) {
(println "✓ Work available:")
(println (+ " " (+ (int_to_string stats.ready_to_work) " issues ready to start")))
} else {
(println "ℹ️ No issues ready to work")
if (> stats.blocked 0) {
(println (+ " " (+ (int_to_string stats.blocked) " issues are blocked")))
}
}
return 0
}
shadow auto_triage {
# Should run without crashing
let result: int = (auto_triage)
assert (or (== result 0) (== result 1))
}
# Create standardized bug report
fn create_bug_report(
title: string,
error_message: string,
file: string,
line: int,
is_critical: bool
) -> string {
let priority: int = (if is_critical 0 1)
let mut description: string = "Bug Report\n\n"
set description (+ description (+ "Error: " error_message))
set description (+ description (+ "\nLocation: " file))
set description (+ description (+ ":" (int_to_string line)))
set description (+ description "\n\nAutomatic bug report generated by workflow automation.")
let labels: array<string> = (array_new 2 "")
(array_set labels 0 "bug")
(array_set labels 1 (if is_critical "critical" "normal"))
let opts: BeadCreateOptions = BeadCreateOptions {
title: title,
description: description,
priority: priority,
issue_type: "bug",
labels: labels
}
return (bd_create_with_options opts)
}
shadow create_bug_report {
# Test with non-critical bug (won't actually create if bd unavailable)
let id: string = (create_bug_report
"Test bug"
"Null pointer exception"
"test.nano"
42
false
)
# Should return empty string or valid ID
assert true
}
# Create feature request with proper categorization
fn create_feature_request(
feature_name: string,
use_case: string,
priority: int
) -> string {
let mut description: string = "Feature Request\n\n"
set description (+ description (+ "Feature: " feature_name))
set description (+ description (+ "\n\nUse Case:\n" use_case))
set description (+ description "\n\nAutomatically created feature request.")
let labels: array<string> = (array_new 2 "")
(array_set labels 0 "feature")
(array_set labels 1 "enhancement")
let opts: BeadCreateOptions = BeadCreateOptions {
title: feature_name,
description: description,
priority: priority,
issue_type: "feature",
labels: labels
}
return (bd_create_with_options opts)
}
shadow create_feature_request {
let id: string = (create_feature_request
"Test feature"
"Testing feature creation"
3
)
assert true
}
# Batch close completed tasks
fn close_completed_tasks(task_ids: array<string>, reason: string) -> int {
let mut closed_count: int = 0
for i in (range 0 (array_length task_ids)) {
let id: string = (at task_ids i)
let success: bool = (bd_close id reason)
if success {
set closed_count (+ closed_count 1)
(println (+ "✓ Closed: " id))
} else {
(println (+ "✗ Failed: " id))
}
}
return closed_count
}
shadow close_completed_tasks {
let empty: array<string> = (array_new 0 "")
let count: int = (close_completed_tasks empty "test")
assert (== count 0)
}
# Generate daily summary report
fn daily_summary() -> int {
(println "=== Daily Issue Summary ===")
(println "")
let stats: BeadStats = (bd_stats)
# Overall health
let total_active: int = (+ stats.open (+ stats.in_progress stats.blocked))
let completion_rate: int = (if (> stats.total 0)
(/ (* stats.closed 100) stats.total)
0
)
(println "Project Health:")
(println (+ " Total issues: " (int_to_string stats.total)))
(println (+ " Active: " (int_to_string total_active)))
(println (+ " Closed: " (int_to_string stats.closed)))
(println (+ " Completion rate: " (+ (int_to_string completion_rate) "%")))
(println "")
# Priority breakdown
(println "By Priority:")
for p in (range 0 5) {
let priority_beads: array<Bead> = (bd_by_priority p)
let count: int = (array_length priority_beads)
(println (+ " P" (+ (int_to_string p) (+ ": " (+ (int_to_string count) " issues")))))
}
(println "")
# Action items
(println "Action Items:")
let ready: array<Bead> = (bd_ready)
if (> (array_length ready) 0) {
(println (+ " ✓ " (+ (int_to_string (array_length ready)) " issues ready to work")))
}
if (> stats.blocked 0) {
(println (+ " ⚠️ " (+ (int_to_string stats.blocked) " issues are blocked")))
}
return 0
}
shadow daily_summary {
let result: int = (daily_summary)
assert (== result 0)
}
fn main() -> int {
(println "=== Beads Workflow Automation ===")
(println "")
# Run triage
(println "1. Running automatic triage...")
(println "")
let triage_result: int = (auto_triage)
(println "")
# Example: Create a bug report
(println "2. Creating example bug report...")
let bug_id: string = (create_bug_report
"Example bug from automation"
"Division by zero in calculate()"
"calculator.nano"
142
false
)
if (!= bug_id "") {
(println (+ " ✓ Created bug: " bug_id))
} else {
(println " ℹ️ Bug creation skipped (bd not available)")
}
(println "")
# Example: Create a feature request
(println "3. Creating example feature request...")
let feature_id: string = (create_feature_request
"Add caching layer"
"Improve performance by caching frequently accessed data"
2
)
if (!= feature_id "") {
(println (+ " ✓ Created feature: " feature_id))
} else {
(println " ℹ️ Feature creation skipped (bd not available)")
}
(println "")
# Generate daily summary
(println "4. Generating daily summary...")
(println "")
let summary_result: int = (daily_summary)
(println "")
(println "✓ Workflow automation complete!")
return 0
}
shadow main {
assert (== (main) 0)
}
datetime_demo.nano
// Datetime Library Demo
module "std/datetime/datetime.nano as DT" as DT
fn current_time_example() -> void {
(println "=== Current Time Example ===")
let now: DT.DateTime = (DT.now)
let iso_str: string = (DT.to_iso now)
(println (string_concat "Current time (ISO): " iso_str))
let formatted: string = (DT.format now "%A, %B %d, %Y at %I:%M %p")
(println (string_concat "Formatted: " formatted))
let year: int = (DT.year now)
let month: int = (DT.month now)
let day: int = (DT.day now)
(println (string_concat "Year: " (int_to_string year)))
(println (string_concat "Month: " (string_concat (DT.month_name month) (string_concat " (" (string_concat (int_to_string month) ")")))))
(println (string_concat "Day: " (int_to_string day)))
(println (string_concat "Weekday: " (DT.weekday_name now)))
(DT.free now)
}
fn parsing_example() -> void {
(println "")
(println "=== Parsing Example ===")
let iso_date: string = "2024-12-17T15:30:00"
let parsed: DT.DateTime = (DT.parse_iso iso_date)
if (!= parsed (cast 0 DT.DateTime)) {
(println (string_concat "Parsed: " (DT.to_iso parsed)))
(println (string_concat "Year: " (int_to_string (DT.year parsed))))
(println (string_concat "Month: " (int_to_string (DT.month parsed))))
(println (string_concat "Day: " (int_to_string (DT.day parsed))))
(DT.free parsed)
} else {
(println "Failed to parse date")
}
}
fn arithmetic_example() -> void {
(println "")
(println "=== Arithmetic Example ===")
let base: DT.DateTime = (DT.create 2024 1 1 12 0 0)
(println (string_concat "Base date: " (DT.to_iso base)))
let plus_days: DT.DateTime = (DT.add_days base 30)
(println (string_concat "Plus 30 days: " (DT.to_iso plus_days)))
let plus_hours: DT.DateTime = (DT.add_hours base 48)
(println (string_concat "Plus 48 hours: " (DT.to_iso plus_hours)))
let diff: int = (DT.diff_seconds plus_days base)
(println (string_concat "Difference: " (string_concat (int_to_string diff) " seconds")))
(DT.free base)
(DT.free plus_days)
(DT.free plus_hours)
}
fn comparison_example() -> void {
(println "")
(println "=== Comparison Example ===")
let dt1: DT.DateTime = (DT.create 2024 6 15 12 0 0)
let dt2: DT.DateTime = (DT.create 2024 12 25 12 0 0)
(println (string_concat "Date 1: " (DT.to_iso dt1)))
(println (string_concat "Date 2: " (DT.to_iso dt2)))
if (DT.before dt1 dt2) {
(println "✓ Date 1 is before Date 2")
}
if (DT.after dt2 dt1) {
(println "✓ Date 2 is after Date 1")
}
let dt3: DT.DateTime = (DT.create 2024 6 15 12 0 0)
if (DT.equals dt1 dt3) {
(println "✓ Date 1 equals Date 3")
}
(DT.free dt1)
(DT.free dt2)
(DT.free dt3)
}
fn utilities_example() -> void {
(println "")
(println "=== Utilities Example ===")
let year: int = 2024
if (DT.is_leap_year year) {
(println (string_concat (int_to_string year) " is a leap year"))
} else {
(println (string_concat (int_to_string year) " is not a leap year"))
}
(println "")
(println "Days in each month of 2024:")
let mut month: int = 1
while (<= month 12) {
let days: int = (DT.days_in_month year month)
(println (string_concat (DT.month_name month) (string_concat ": " (string_concat (int_to_string days) " days"))))
set month (+ month 1)
}
}
fn timestamp_example() -> void {
(println "")
(println "=== Timestamp Example ===")
let now: DT.DateTime = (DT.now)
let timestamp: int = (DT.to_timestamp now)
(println (string_concat "Current timestamp: " (int_to_string timestamp)))
let from_ts: DT.DateTime = (DT.from_timestamp timestamp)
(println (string_concat "Converted back: " (DT.to_iso from_ts)))
(DT.free now)
(DT.free from_ts)
}
fn main() -> int {
(current_time_example)
(parsing_example)
(arithmetic_example)
(comparison_example)
(utilities_example)
(timestamp_example)
(println "")
(println "✅ Datetime demo complete!")
return 0
}
error_handling_patterns.nano
# Example: Error Handling Patterns
# Purpose: Demonstrate comprehensive error handling strategies in NanoLang
# Features: Return codes, sentinel values, early returns, validation
# Difficulty: Advanced
# Usage: ./bin/nanoc examples/advanced/error_handling_patterns.nano -o /tmp/errors && /tmp/errors
# Expected Output: Demonstrates various error handling approaches
#
# Learning Objectives:
# 1. Use return codes for error signaling (0 = success, non-zero = error)
# 2. Implement validation functions that return bool
# 3. Use early returns to handle error cases first
# 4. Design APIs that make errors explicit
# 5. Document error conditions in shadow tests
#
# NanoLang Philosophy:
# - Explicit over implicit: errors are return values, not exceptions
# - Fail fast: validate inputs early and return immediately on error
# - Document behavior: shadow tests show both success and failure cases
# Pattern 1: Return Code (0 = success, negative = error code)
fn divide_safe(a: int, b: int) -> int {
# Error case: division by zero
if (== b 0) {
return -1 # Error code: division by zero
} else {}
# Success case
return (/ a b)
}
shadow divide_safe {
# Success cases
assert (== (divide_safe 10 2) 5)
assert (== (divide_safe 7 3) 2)
# Error case: division by zero returns -1
assert (== (divide_safe 10 0) -1)
}
# Pattern 2: Validation Function (returns bool)
fn is_valid_age(age: int) -> bool {
return (and (>= age 0) (<= age 150))
}
shadow is_valid_age {
# Valid ages
assert (== (is_valid_age 0) true)
assert (== (is_valid_age 25) true)
assert (== (is_valid_age 150) true)
# Invalid ages
assert (== (is_valid_age -1) false)
assert (== (is_valid_age 151) false)
}
# Pattern 3: Early Return for Error Cases
fn process_value(x: int) -> int {
# Validate input first (early return pattern)
if (< x 0) {
return -1 # Error: negative input
} else {}
if (> x 1000) {
return -2 # Error: value too large
} else {}
# Main logic only runs for valid input
return (* x 2)
}
shadow process_value {
# Success cases
assert (== (process_value 0) 0)
assert (== (process_value 10) 20)
assert (== (process_value 500) 1000)
# Error cases
assert (== (process_value -1) -1) # Negative input
assert (== (process_value 1001) -2) # Too large
}
# Pattern 4: Sentinel Value (-1 for "not found")
fn find_in_array(arr: array<int>, target: int) -> int {
let len: int = (array_length arr)
let mut i: int = 0
while (< i len) {
if (== (at arr i) target) {
return i # Found: return index
} else {}
set i (+ i 1)
}
return -1 # Not found: sentinel value
}
shadow find_in_array {
let test_arr: array<int> = [10, 20, 30, 40, 50]
# Success cases: element found
assert (== (find_in_array test_arr 10) 0)
assert (== (find_in_array test_arr 30) 2)
assert (== (find_in_array test_arr 50) 4)
# Error case: element not found
assert (== (find_in_array test_arr 99) -1)
}
# Pattern 5: Validate-Then-Process
fn safe_sqrt(x: int) -> int {
# Validation
if (< x 0) {
return -1 # Error: cannot take sqrt of negative
} else {}
# Processing (simplified integer sqrt)
let mut guess: int = x
let mut i: int = 0
while (< i 10) {
if (== guess 0) {
return 0
} else {}
let new_guess: int = (/ (+ guess (/ x guess)) 2)
set guess new_guess
set i (+ i 1)
}
return guess
}
shadow safe_sqrt {
# Success cases
assert (== (safe_sqrt 0) 0)
assert (== (safe_sqrt 1) 1)
assert (== (safe_sqrt 4) 2)
assert (== (safe_sqrt 9) 3)
assert (== (safe_sqrt 16) 4)
# Error case: negative input
assert (== (safe_sqrt -1) -1)
}
# Pattern 6: Chaining Validations
fn validate_and_compute(a: int, b: int, c: int) -> int {
# Chain of validations
if (< a 0) {
return -1 # Error: a is negative
} else {}
if (< b 0) {
return -2 # Error: b is negative
} else {}
if (< c 0) {
return -3 # Error: c is negative
} else {}
if (== b 0) {
return -4 # Error: b is zero (division)
} else {}
# All validations passed, compute result
return (/ (+ a c) b)
}
shadow validate_and_compute {
# Success case
assert (== (validate_and_compute 10 2 6) 8) # (10+6)/2 = 8
# Error cases with specific codes
assert (== (validate_and_compute -1 2 6) -1) # a negative
assert (== (validate_and_compute 10 -1 6) -2) # b negative
assert (== (validate_and_compute 10 2 -1) -3) # c negative
assert (== (validate_and_compute 10 0 6) -4) # b is zero
}
fn main() -> int {
(println "Error Handling Patterns Demo")
(println "")
# Pattern 1: Return codes
(println "Pattern 1: Return Codes")
(println (divide_safe 10 2)) # 5
(println (divide_safe 10 0)) # -1 (error)
(println "")
# Pattern 2: Validation
(println "Pattern 2: Validation Functions")
(println (is_valid_age 25)) # true
(println (is_valid_age -5)) # false
(println "")
# Pattern 3: Early returns
(println "Pattern 3: Early Returns")
(println (process_value 10)) # 20
(println (process_value -1)) # -1 (error)
(println (process_value 2000)) # -2 (error)
(println "")
# Pattern 4: Sentinel values
(println "Pattern 4: Sentinel Values")
let arr: array<int> = [10, 20, 30]
(println (find_in_array arr 20)) # 1 (found at index 1)
(println (find_in_array arr 99)) # -1 (not found)
(println "")
# Pattern 5: Validate-then-process
(println "Pattern 5: Validate-Then-Process")
(println (safe_sqrt 16)) # 4
(println (safe_sqrt -1)) # -1 (error)
(println "")
# Pattern 6: Chained validations
(println "Pattern 6: Chained Validations")
(println (validate_and_compute 10 2 6)) # 8
(println (validate_and_compute -1 2 6)) # -1 (error code)
return 0
}
shadow main {
assert (== (main) 0)
}
event_example.nano
# Async Events with libevent - Event Notification Example
#
# Concept: Asynchronous event notification using libevent
# Topics: event loops, async notifications, libevent, non-blocking I/O, C FFI
# Difficulty: Advanced
#
# Description:
# Demonstrates libevent for asynchronous event notification and handling.
# Shows how to set up event loops, register callbacks, and handle events
# in a non-blocking manner. Alternative to libuv with different API.
#
# Key Features Demonstrated:
# - libevent event loop setup
# - Event registration and callbacks
# - Async event handling
# - Non-blocking architecture
# - Timer events
#
# Real-World Use Cases:
# - Event-driven servers
# - Real-time notification systems
# - Network protocol implementations
# - Async I/O applications
# - High-concurrency systems
#
# Libevent vs libuv:
# - libevent: Mature, battle-tested, callback-based
# - libuv: Modern, cross-platform, used by Node.js
# - Both: Excellent for async I/O
#
# Prerequisites:
# - uv_example.nano - Async I/O concepts
# - Understanding of event-driven programming
# - C FFI familiarity
#
# Next Steps:
# - Add network event examples
# - Implement signal handling
# - Build async HTTP client
# - Compare with libuv approach
module "modules/event/event.nano"
fn show_version() -> void {
(println "=== libevent Version ===")
(print "Version: ")
(println (nl_event_get_version))
let ver_num: int = (nl_event_get_version_number)
(print "Version number: ")
(println ver_num)
(println "")
}
shadow show_version {
# Skip - uses extern functions
}
fn test_event_base() -> void {
(println "=== Event Base Test ===")
# Create event base
let base: int = (nl_event_base_new)
if (== base 0) {
(println "Failed to create event base")
return
}
(println "Event base created successfully")
# Get backend method
let method: string = (nl_event_base_get_method base)
(print "Backend method: ")
(println method)
# Get number of events
let num_events: int = (nl_event_base_get_num_events base)
(print "Number of active events: ")
(println num_events)
# Check if loop would run
if (== num_events 0) {
(println "No events registered - loop would exit immediately")
}
# Free event base
(nl_event_base_free base)
(println "Event base freed")
(println "")
}
shadow test_event_base {
# Skip - uses extern functions
}
fn test_timer_event() -> void {
(println "=== Timer Event Test ===")
let base: int = (nl_event_base_new)
if (== base 0) {
(println "Failed to create event base")
return
}
# Create timer event
let timer: int = (nl_evtimer_new base)
if (== timer 0) {
(println "Failed to create timer")
(nl_event_base_free base)
return
}
(println "Timer event created")
# Note: Full timer functionality requires callback support
# This is a simplified demonstration
# Clean up
(nl_event_free timer)
(nl_event_base_free base)
(println "Timer and base freed")
(println "")
}
shadow test_timer_event {
# Skip - uses extern functions
}
fn test_sleep() -> void {
(println "=== Event-based Sleep Test ===")
let base: int = (nl_event_base_new)
if (== base 0) {
(println "Failed to create event base")
return
}
(println "Sleeping for 1 second using event loop...")
# Schedule loop exit after 1 second
(nl_event_sleep base 1)
# Run the loop (will exit after timeout)
let result: int = (nl_event_base_dispatch base)
if (== result 0) {
(println "Sleep completed successfully")
} else {
(println "Sleep returned with code:")
(println result)
}
(nl_event_base_free base)
(println "")
}
shadow test_sleep {
# Skip - uses extern functions
}
fn test_loop_modes() -> void {
(println "=== Loop Mode Test ===")
let base: int = (nl_event_base_new)
if (== base 0) {
(println "Failed to create event base")
return
}
# Test non-blocking loop (should return immediately with no events)
(println "Running non-blocking loop...")
let result: int = (nl_event_base_loop base 1)
(print "Result: ")
(println result)
# Test run-once mode
(println "Running once mode...")
set result (nl_event_base_loop base 2)
(print "Result: ")
(println result)
(nl_event_base_free base)
(println "")
}
shadow test_loop_modes {
# Skip - uses extern functions
}
fn main() -> int {
(println "libevent Examples for nanolang")
(println "==============================")
(println "")
show_version
test_event_base
test_timer_event
test_sleep
test_loop_modes
(println "All tests completed!")
(println "")
(println "Note: Full event handling with callbacks requires")
(println "additional nanolang support for function pointers.")
return 0
}
shadow main {
# Skip - uses extern functions
}
ffi_tutorial.nano
# Example: FFI (Foreign Function Interface) Tutorial
# Purpose: Step-by-step guide to calling C functions from NanoLang
# Features: extern keyword, C interop, opaque types, type mapping
# Difficulty: Advanced
# Usage: ./bin/nanoc examples/advanced/ffi_tutorial.nano -o /tmp/ffi && /tmp/ffi
# Expected Output: Demonstrates various FFI patterns
#
# Learning Objectives:
# 1. Declare extern functions to call C library functions
# 2. Understand type mappings (int→int64_t, string→char*, etc.)
# 3. Work with opaque C types (pointers you can't inspect)
# 4. Use pub extern for module exports
# 5. Handle C return values and error codes
#
# FFI Basics:
# - extern fn declares a C function without implementing it
# - NanoLang types map to C types automatically
# - Shadow tests are NOT required for extern functions
# - Use pub extern to export FFI wrappers from modules
# ==================================================================
# Part 1: Basic C Standard Library Functions
# ==================================================================
# Math functions from <math.h>
extern fn sqrt(x: float) -> float
extern fn pow(base: float, exp: float) -> float
extern fn sin(x: float) -> float
extern fn cos(x: float) -> float
# String functions from <string.h>
extern fn strlen(s: string) -> int
# Memory functions from <stdlib.h>
extern fn abs(x: int) -> int
# ==================================================================
# Part 2: Wrapper Functions (Add Shadow Tests)
# ==================================================================
# Wrapper functions CAN have shadow tests (they're regular NanoLang functions)
fn safe_sqrt(x: float) -> float {
if (< x 0.0) {
return 0.0 # Return 0 for negative input
} else {}
return (sqrt x)
}
shadow safe_sqrt {
assert (== (safe_sqrt 4.0) 2.0)
assert (== (safe_sqrt 9.0) 3.0)
assert (== (safe_sqrt -1.0) 0.0) # Negative handled
}
fn power(base: float, exp: float) -> float {
return (pow base exp)
}
shadow power {
assert (== (power 2.0 3.0) 8.0)
assert (== (power 10.0 2.0) 100.0)
assert (== (power 5.0 0.0) 1.0)
}
# ==================================================================
# Part 3: Type Mappings
# ==================================================================
# NanoLang Type → C Type Mapping:
# int → int64_t
# float → double
# bool → bool
# string → char*
# void → void
# array<T> → (internal GC type)
# struct Foo → nl_Foo (with nl_ prefix)
fn demonstrate_type_mapping() -> int {
# int → int64_t
let i: int = (abs -42)
(println i) # 42
# float → double
let f: float = (sqrt 16.0)
(println f) # 4.0
# string → char*
let s: string = "Hello"
let len: int = (strlen s)
(println len) # 5
return 0
}
shadow demonstrate_type_mapping {
assert (== (demonstrate_type_mapping) 0)
}
# ==================================================================
# Part 4: Working with C Return Values
# ==================================================================
# Many C functions return error codes or special values
# You must check these in your wrapper functions
fn check_math_result(x: float) -> bool {
let result: float = (sqrt x)
# In real code, you'd check for NaN, infinity, etc.
# For this example, just check if result is positive
return (> result 0.0)
}
shadow check_math_result {
assert (== (check_math_result 4.0) true)
assert (== (check_math_result 0.0) false)
}
# ==================================================================
# Part 5: Best Practices for FFI
# ==================================================================
# 1. Always wrap extern functions in NanoLang functions
# - Adds type safety
# - Allows shadow testing
# - Handles error cases
# - Provides better API
# 2. Document C function behavior
fn documented_wrapper(x: float) -> float {
# C function: double sqrt(double x)
# Returns: square root of x
# Special cases: sqrt(negative) returns NaN
# Our wrapper: returns 0.0 for negative input
if (< x 0.0) {
return 0.0
} else {}
return (sqrt x)
}
shadow documented_wrapper {
assert (== (documented_wrapper 16.0) 4.0)
assert (== (documented_wrapper -1.0) 0.0)
}
# 3. Use pub extern for module exports
# (This would go in a module file like modules/math_ext/math_ext.nano)
# pub extern fn special_function(x: int) -> int
# 4. Handle C error codes explicitly
fn safe_division(a: int, b: int) -> int {
# If this were calling a C function that returns error codes:
# - Check return value
# - Convert to NanoLang error convention
# - Document error cases in shadow tests
if (== b 0) {
return -1 # Error code
} else {}
return (/ a b)
}
shadow safe_division {
assert (== (safe_division 10 2) 5)
assert (== (safe_division 10 0) -1) # Error case
}
# ==================================================================
# Part 6: Common Pitfalls
# ==================================================================
# PITFALL 1: Forgetting extern functions don't need shadow tests
# extern fn some_c_function(x: int) -> int
# # NO shadow test needed! (would cause error)
# PITFALL 2: Not checking C function error returns
# Always check return values from C functions that can fail
# PITFALL 3: String lifetime issues
# C strings (char*) must remain valid for the duration of use
# NanoLang handles this automatically for you
# PITFALL 4: Opaque types
# Some C types are opaque (you can't see inside them)
# Example: FILE*, SDL_Window*, etc.
# Just pass them around, don't try to inspect them
fn main() -> int {
(println "FFI Tutorial Demo")
(println "")
(println "Part 1: Basic C Functions")
(println (sqrt 16.0)) # 4.0
(println (pow 2.0 8.0)) # 256.0
(println "")
(println "Part 2: Wrapper Functions")
(println (safe_sqrt 25.0)) # 5.0
(println (safe_sqrt -1.0)) # 0.0 (handled)
(println "")
(println "Part 3: Type Mappings")
(demonstrate_type_mapping)
(println "")
(println "Part 4: Error Handling")
(println (safe_division 10 2)) # 5
(println (safe_division 10 0)) # -1 (error)
return 0
}
shadow main {
assert (== (main) 0)
}
large_project_structure.nano (View on GitHub)
libc_demo.nano
/* Demonstration of using libc as a module
*
* Shows the new "everything is a module" syntax.
*/
unsafe module "libc" as C
fn demo_stdio() -> void {
(println "=== stdio.h Demo ===")
/* Use C printf directly */
(C.printf "Hello from C printf!\n")
(C.puts "Hello from C puts!")
(println "")
}
shadow demo_stdio {
(demo_stdio)
}
fn demo_string() -> void {
(println "=== string.h Demo ===")
let s1: string = "Hello"
let s2: string = "World"
/* Compare strings */
let cmp: int = (C.strcmp s1 s2)
if (< cmp 0) {
(println "Hello < World")
} else {
if (> cmp 0) {
(println "Hello > World")
} else {
(println "Equal")
}
}
/* Get string length */
let len: int = (C.strlen s1)
(print "Length of 'Hello': ")
(println len)
(println "")
}
shadow demo_string {
(demo_string)
}
fn demo_math() -> void {
(println "=== math.h Demo ===")
/* Square root */
let x: float = 16.0
let root: float = (C.sqrt x)
(print "sqrt(16.0) = ")
(println root)
/* Power */
let base: float = 2.0
let exp: float = 8.0
let result: float = (C.pow base exp)
(print "2.0^8.0 = ")
(println result)
/* Trigonometry */
let angle: float = 0.0
let sine: float = (C.sin angle)
(print "sin(0.0) = ")
(println sine)
(println "")
}
shadow demo_math {
(demo_math)
}
fn demo_stdlib() -> void {
(println "=== stdlib.h Demo ===")
/* String to int */
let num_str: string = "42"
let num: int = (C.atoi num_str)
(print "atoi(\"42\") = ")
(println num)
/* String to float */
let float_str: string = "3.14"
let fnum: float = (C.atof float_str)
(print "atof(\"3.14\") = ")
(println fnum)
(println "")
}
shadow demo_stdlib {
(demo_stdlib)
}
fn main() -> int {
(println "=== libc Module Demo ===")
(println "Everything is a module!")
(println "")
(demo_stdio)
(demo_string)
(demo_math)
(demo_stdlib)
(println "=== Demo Complete ===")
return 0
}
shadow main {
assert (== (main) 0)
}
math_ext_demo.nano (View on GitHub)
math_helper.nano
/* Math helper module for nl_demo_selfhosting.nano */
pub fn add(a: int, b: int) -> int {
return (+ a b)
}
shadow add {
assert (== (add 2 3) 5)
assert (== (add 10 20) 30)
}
pub fn multiply(a: int, b: int) -> int {
return (* a b)
}
shadow multiply {
assert (== (multiply 2 3) 6)
assert (== (multiply 12 8) 96)
}
pub fn square(n: int) -> int {
return (* n n)
}
shadow square {
assert (== (square 5) 25)
assert (== (square 11) 121)
}
module_introspection_demo.nano
/* Test Module Introspection - Query module metadata at compile-time */
unsafe module "modules/sdl/sdl.nano" as SDL
module "modules/vector2d/vector2d.nano" as Vec
/* Declare extern functions for module introspection (auto-generated by compiler) */
extern fn ___module_is_unsafe_sdl() -> bool
extern fn ___module_has_ffi_sdl() -> bool
extern fn ___module_name_sdl() -> string
extern fn ___module_path_sdl() -> string
extern fn ___module_is_unsafe_vector2d() -> bool
extern fn ___module_has_ffi_vector2d() -> bool
extern fn ___module_name_vector2d() -> string
extern fn ___module_path_vector2d() -> string
fn main() -> int {
(println "=== Module Introspection Test ===")
(println "")
/* Query SDL module metadata */
(println "SDL Module:")
(print " Name: ")
unsafe { (println (___module_name_sdl)) }
(print " Path: ")
unsafe { (println (___module_path_sdl)) }
(print " Is Unsafe: ")
let mut sdl_unsafe: bool = false
unsafe { set sdl_unsafe (___module_is_unsafe_sdl) }
(println (cond (sdl_unsafe "yes") (else "no")))
(print " Has FFI: ")
let mut sdl_ffi: bool = false
unsafe { set sdl_ffi (___module_has_ffi_sdl) }
(println (cond (sdl_ffi "yes") (else "no")))
(println "")
/* Query vector2d module metadata */
(println "Vector2D Module:")
(print " Name: ")
unsafe { (println (___module_name_vector2d)) }
(print " Path: ")
unsafe { (println (___module_path_vector2d)) }
(print " Is Unsafe: ")
let mut vec_unsafe: bool = false
unsafe { set vec_unsafe (___module_is_unsafe_vector2d) }
(println (cond (vec_unsafe "yes") (else "no")))
(print " Has FFI: ")
let mut vec_ffi: bool = false
unsafe { set vec_ffi (___module_has_ffi_vector2d) }
(println (cond (vec_ffi "yes") (else "no")))
(println "")
(println "✅ Module introspection working!")
return 0
}
shadow main {
assert (== (main) 0)
}
namespace_demo.nano
/* =============================================================================
* Namespace System Demo
* =============================================================================
* Demonstrates NanoLang's namespace system features:
* - Module declarations
* - Public/private visibility
* - Namespace-scoped functions
*
* This example shows the core namespace features without external imports.
*/
module namespace_demo
/* =============================================================================
* Public API - Exported Functions
* =============================================================================
*/
/* Public function - accessible from other modules */
pub fn public_add(a: int, b: int) -> int {
return (+ a b)
}
shadow public_add {
assert (== (public_add 5 7) 12)
}
/* Public function using private helper */
pub fn calculate_sum(numbers: array<int>) -> int {
let count: int = (array_length numbers)
return (sum_array numbers 0 count 0)
}
shadow calculate_sum {
let nums: array<int> = [1, 2, 3, 4, 5]
assert (== (calculate_sum nums) 15)
}
/* =============================================================================
* Private Implementation - Module-Internal Functions
* =============================================================================
*/
/* Private recursive helper - not exported */
fn sum_array(arr: array<int>, idx: int, len: int, acc: int) -> int {
if (>= idx len) {
return acc
} else {
let val: int = (at arr idx)
let new_acc: int = (+ acc val)
return (sum_array arr (+ idx 1) len new_acc)
}
}
shadow sum_array {
let nums: array<int> = [10, 20, 30]
assert (== (sum_array nums 0 3 0) 60)
}
/* Private helper for validation */
fn is_positive(n: int) -> bool {
return (> n 0)
}
shadow is_positive {
assert (== (is_positive 5) true)
assert (== (is_positive -3) false)
assert (== (is_positive 0) false)
}
/* =============================================================================
* Public Data Processing
* =============================================================================
*/
/* Public struct - exported type */
pub struct DataPoint {
value: int,
valid: bool
}
/* Public function using public struct */
pub fn create_data_point(value: int) -> DataPoint {
return DataPoint {
value: value,
valid: (is_positive value)
}
}
shadow create_data_point {
let dp1: DataPoint = (create_data_point 42)
assert (== dp1.value 42)
assert (== dp1.valid true)
let dp2: DataPoint = (create_data_point -5)
assert (== dp2.value -5)
assert (== dp2.valid false)
}
/* Public function for percentage calculation */
pub fn calculate_percentage(part: int, total: int) -> int {
if (== total 0) {
return 0
} else {
return (/ (* part 100) total)
}
}
shadow calculate_percentage {
assert (== (calculate_percentage 50 100) 50)
assert (== (calculate_percentage 25 100) 25)
assert (== (calculate_percentage 0 100) 0)
assert (== (calculate_percentage 100 0) 0)
}
/* =============================================================================
* Main Demo
* =============================================================================
*/
pub fn main() -> int {
(println "=== Namespace System Demo ===")
(println "")
/* Test public API */
(println "1. Public Functions:")
let sum: int = (public_add 10 20)
(print " public_add(10, 20) = ")
(println sum)
let nums: array<int> = [1, 2, 3, 4, 5]
let total: int = (calculate_sum nums)
(print " calculate_sum([1,2,3,4,5]) = ")
(println total)
(println "")
/* Test public struct */
(println "2. Public Struct (DataPoint):")
let dp: DataPoint = (create_data_point 42)
(print " DataPoint { value: ")
(print dp.value)
(print ", valid: ")
(print dp.valid)
(println " }")
(println "")
/* Test percentage calculation */
(println "3. Percentage Calculation:")
let pct: int = (calculate_percentage 50 100)
(print " calculate_percentage(50, 100) = ")
(print pct)
(println "%")
(println "")
/* Demonstrate visibility */
(println "4. Visibility Control:")
(println " ✓ Public functions: public_add, calculate_sum, create_data_point, calculate_percentage")
(println " ✓ Private functions: sum_array, is_positive (not accessible from other modules)")
(println " ✓ Public types: DataPoint")
(println "")
(println "✅ All namespace features working correctly!")
(println "")
(println "Key Features Demonstrated:")
(println " - Module declaration (module namespace_demo)")
(println " - Public API (pub fn, pub struct)")
(println " - Private implementation details (fn without pub)")
(println " - Namespace isolation and visibility control")
(println " - Shadow tests for validation")
return 0
}
shadow main {
assert (== (main) 0)
}
performance_optimization.nano (View on GitHub)
regex_demo.nano
# NanoLang Regex Demo - Pythonic API
# Showcases one-shot operations (Tier 1) and compiled patterns (Tier 2)
from "std/regex/regex.nano" import regex_match, regex_find, regex_replace, regex_replace_all, regex_split, compile, matches, free
# =============================================================================
# TIER 1 DEMOS: Simple One-Shot API (90% of use cases)
# =============================================================================
fn demo_validation() -> void {
(println "╔════════════════════════════════════════╗")
(println "║ TIER 1: Simple Validation (No Handles!) ║")
(println "╚════════════════════════════════════════╝")
(println "")
# Email validation - one line, no memory management!
if (regex_match "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-z]+" "user@example.com") {
(println "✓ Valid email: user@example.com")
}
# Phone validation
if (regex_match "^[0-9]{3}-[0-9]{3}-[0-9]{4}$" "555-123-4567") {
(println "✓ Valid phone: 555-123-4567")
}
if (not (regex_match "^[0-9]{3}-[0-9]{3}-[0-9]{4}$" "invalid")) {
(println "✗ Invalid phone: invalid")
}
}
fn demo_replacement() -> void {
(println "")
(println "╔════════════════════════════════════════╗")
(println "║ TIER 1: Text Replacement ║")
(println "╚════════════════════════════════════════╝")
(println "")
let text: string = "I have 3 apples and 5 oranges"
(println (+ "Original: " text))
# Replace first number - one line!
let r1: string = (regex_replace "[0-9]+" "X" text)
(println (+ "First: " r1))
# Replace all numbers - still one line!
let r2: string = (regex_replace_all "[0-9]+" "X" text)
(println (+ "All: " r2))
}
fn demo_split() -> void {
(println "")
(println "╔════════════════════════════════════════╗")
(println "║ TIER 1: Split by Pattern ║")
(println "╚════════════════════════════════════════╝")
(println "")
let csv: string = "apple,banana;cherry,date;elderberry"
let parts: array<string> = (regex_split "[,;]" csv)
(println (+ "Input: " csv))
(println (+ "Split into " (+ (int_to_string (array_length parts)) " parts:")))
let mut i: int = 0
while (< i (array_length parts)) {
(println (+ " [" (+ (int_to_string i) (+ "] " (array_get parts i)))))
set i (+ i 1)
}
}
fn demo_find() -> void {
(println "")
(println "╔════════════════════════════════════════╗")
(println "║ TIER 1: Find Pattern Position ║")
(println "╚════════════════════════════════════════╝")
(println "")
let text: string = "The answer is 42 and the year is 2024"
let pos: int = (regex_find "[0-9]+" text)
(println (+ "Text: " text))
if (>= pos 0) {
(println (+ "First number at position: " (int_to_string pos)))
}
}
# =============================================================================
# TIER 2 DEMOS: Compiled Patterns (Power Users - for performance)
# =============================================================================
fn demo_compiled_loop() -> void {
(println "")
(println "╔════════════════════════════════════════╗")
(println "║ TIER 2: Compiled Pattern in Loop ║")
(println "╚════════════════════════════════════════╝")
(println "")
(println "Validating 5 emails with ONE compiled pattern...")
(println "")
# Compile once - efficient for loops
let email_pattern: opaque = (compile "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-z]+")
# Test valid email
if (matches email_pattern "alice@example.com") {
(println " ✓ Valid: alice@example.com")
} else {
(println " ✗ Invalid: alice@example.com")
}
# Test another valid
if (matches email_pattern "bob@test.org") {
(println " ✓ Valid: bob@test.org")
} else {
(println " ✗ Invalid: bob@test.org")
}
# Test invalid
if (matches email_pattern "invalid.email") {
(println " ✓ Valid: invalid.email")
} else {
(println " ✗ Invalid: invalid.email")
}
# Test valid
if (matches email_pattern "charlie@company.net") {
(println " ✓ Valid: charlie@company.net")
} else {
(println " ✗ Invalid: charlie@company.net")
}
# Test invalid
if (matches email_pattern "not-an-email") {
(println " ✓ Valid: not-an-email")
} else {
(println " ✗ Invalid: not-an-email")
}
# Don't forget to free!
(free email_pattern)
(println "")
(println "✓ Pattern freed - no memory leaks")
}
fn demo_comparison() -> void {
(println "")
(println "╔════════════════════════════════════════╗")
(println "║ API Comparison ║")
(println "╚════════════════════════════════════════╝")
(println "")
(println "TIER 1 (Simple): One line, automatic cleanup")
(println " if (regex_match pattern text) { ... }")
(println "")
(println "TIER 2 (Power): Compile once, use many times")
(println " let re: opaque = (compile pattern)")
(println " if (matches re text1) { ... }")
(println " if (matches re text2) { ... }")
(println " (free re)")
}
# =============================================================================
# MAIN
# =============================================================================
fn main() -> int {
(println "")
(println "═══════════════════════════════════════════════════")
(println " NanoLang Regex - Pythonic API Demo")
(println " No Manual Memory Management Required!")
(println "═══════════════════════════════════════════════════")
(println "")
# Tier 1: Simple one-shot operations
(demo_validation)
(demo_replacement)
(demo_split)
(demo_find)
# Tier 2: Power user API
(demo_compiled_loop)
# Comparison
(demo_comparison)
(println "")
(println "═══════════════════════════════════════════════════")
(println "✓ All demos completed successfully!")
(println "═══════════════════════════════════════════════════")
return 0
}
regex_demo_simple.nano
# Regular Expression Demo - Pythonic One-Shot API
# No opaque handle management needed!
module "std/regex/regex.nano as Regex" as Regex
fn match_example() -> void {
(println "=== Pattern Matching ===")
# Validate phone number - one line, no handles!
if (Regex.regex_match "[0-9]{3}-[0-9]{3}-[0-9]{4}" "555-123-4567") {
(println "✓ Valid phone number: 555-123-4567")
}
# Validate email
if (Regex.regex_match "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-z]+" "user@example.com") {
(println "✓ Valid email: user@example.com")
}
if (not (Regex.regex_match "[0-9]{3}-[0-9]{3}-[0-9]{4}" "invalid")) {
(println "✗ Invalid phone number: invalid")
}
}
fn replace_example() -> void {
(println "")
(println "=== Find and Replace ===")
# Replace first number
let text1: string = "I have 3 apples and 5 oranges"
let result1: string = (Regex.regex_replace "[0-9]+" "X" text1)
(println (string_concat "Original: " text1))
(println (string_concat "Replace 1st: " result1))
# Replace all numbers
let result2: string = (Regex.regex_replace_all "[0-9]+" "X" text1)
(println (string_concat "Replace all: " result2))
}
fn split_example() -> void {
(println "")
(println "=== Split by Pattern ===")
let text: string = "apple,banana;cherry,date;elderberry"
let parts: array<string> = (Regex.regex_split "[,;]" text)
(println (string_concat "Input: " text))
(println (string_concat "Split into " (string_concat (int_to_string (len parts)) " parts:")))
let mut i: int = 0
while (< i (len parts)) {
(println (string_concat " [" (string_concat (int_to_string i) (string_concat "]: " (get parts i)))))
set i (+ i 1)
}
}
fn find_example() -> void {
(println "")
(println "=== Find Pattern Position ===")
let text: string = "The answer is 42 and the year is 2024"
let pos: int = (Regex.regex_find "[0-9]+" text)
(println (string_concat "Text: " text))
if (>= pos 0) {
(println (string_concat "First number starts at position: " (int_to_string pos)))
} else {
(println "No numbers found")
}
}
fn sanitize_example() -> void {
(println "")
(println "=== Sanitize User Input ===")
# Remove all non-alphanumeric characters
let unsafe: string = "Hello<script>alert('xss')</script>World"
let safe: string = (Regex.regex_replace_all "<[^>]*>" "" unsafe)
(println (string_concat "Unsafe: " unsafe))
(println (string_concat "Safe: " safe))
}
fn main() -> int {
(println "╔════════════════════════════════════════════════════════╗")
(println "║ NanoLang Regex - Pythonic One-Shot API ║")
(println "║ No opaque handles. No free(). Just works! ║")
(println "╚════════════════════════════════════════════════════════╝")
(println "")
(match_example)
(replace_example)
(split_example)
(find_example)
(sanitize_example)
(println "")
(println "✓ All operations completed successfully!")
(println " No memory management needed - handled automatically!")
return 0
}
sqlite_simple.nano
# Simple SQLite Database Example
# Demonstrates SECURE database operations with SQLite3
#
# Concept: Safe database CRUD with prepared statements
# Topics: SQL, database security, parameter binding
# Difficulty: Intermediate
#
# Description:
# Shows secure database operations using prepared statements
# to prevent SQL injection attacks. Demonstrates proper use
# of nl_sqlite3_prepare with result iteration.
#
# Key Features Demonstrated:
# - Prepared statements (nl_sqlite3_prepare) for queries
# - Result iteration with nl_sqlite3_step
# - Column access (nl_sqlite3_column_*)
# - Proper resource cleanup (nl_sqlite3_finalize)
#
# SECURITY NOTE:
# This example is SAFE because it uses:
# ✅ Hardcoded SQL strings (no user input concatenation)
# ✅ Prepared statements for queries
#
# For dynamic queries with user input, ALWAYS use parameter binding:
# ✅ SAFE: let stmt = (nl_sqlite3_prepare db "SELECT * FROM users WHERE id = ?")
# (nl_sqlite3_bind_int stmt 1 user_id)
#
# ❌ UNSAFE: Concatenating user input into SQL string
# This would allow SQL injection attacks!
module "modules/sqlite/sqlite.nano"
fn main() -> int {
(println "")
(println "📇 SQLite Database Example")
(println "==========================")
(println "")
# Open database
let db_path: string = "test.db"
let db: int = (nl_sqlite3_open db_path)
if (== db 0) {
(println "❌ Failed to open database")
return 1
} else {
(print "✓ Database opened: ")
(println db_path)
}
# Create table
(println "")
(println "Creating table...")
let create_sql: string = "CREATE TABLE IF NOT EXISTS contacts (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"
let create_result: int = (nl_sqlite3_exec db create_sql)
if (== create_result 0) {
(println "✓ Table created")
} else {
(print "❌ Create failed: ")
(println (nl_sqlite3_errmsg db))
}
# Insert data
(println "")
(println "Inserting contacts...")
let insert1: string = "INSERT INTO contacts (name, email) VALUES ('Alice', 'alice@example.com')"
(nl_sqlite3_exec db insert1)
(println "✓ Inserted Alice")
let insert2: string = "INSERT INTO contacts (name, email) VALUES ('Bob', 'bob@example.com')"
(nl_sqlite3_exec db insert2)
(println "✓ Inserted Bob")
# Query data
(println "")
(println "Querying all contacts...")
(println "")
let select_sql: string = "SELECT id, name, email FROM contacts"
let stmt: int = (nl_sqlite3_prepare db select_sql)
if (== stmt 0) {
(println "❌ Failed to prepare query")
} else {
let mut running: bool = true
let mut count: int = 0
while running {
let result: int = (nl_sqlite3_step stmt)
if (== result 100) { # SQLITE_ROW
set count (+ count 1)
let id: int = (nl_sqlite3_column_int stmt 0)
let name: string = (nl_sqlite3_column_text stmt 1)
let email: string = (nl_sqlite3_column_text stmt 2)
(print "ID: ")
(print id)
(print " | Name: ")
(print name)
(print " | Email: ")
(println email)
} else {
set running false
}
}
(nl_sqlite3_finalize stmt)
(println "")
(print "Total: ")
(print count)
(println " contacts")
}
# Close database
(nl_sqlite3_close db)
(println "")
(println "✅ Database operations completed!")
(println "")
(print "View with: sqlite3 ")
(println db_path)
(println "")
return 0
}
shadow main {
# Uses extern functions
assert true
}
stdio_file_processor.nano
# File Processor Example
# Demonstrates stdio module for reading, filtering, transforming, and writing files
# Real-world problem: Process log files, filter by severity, count occurrences
from "modules/std/fs.nano" import file_read, file_write, file_exists
fn count_chars(text: string) -> int {
return (str_length text)
}
shadow count_chars {
assert (== (count_chars "hello") 5)
assert (== (count_chars "") 0)
}
fn count_lines(text: string) -> int {
let mut count: int = 1
let mut i: int = 0
while (< i (str_length text)) {
if (== (char_at text i) '\n') {
set count (+ count 1)
} else {}
set i (+ i 1)
}
return count
}
shadow count_lines {
assert (== (count_lines "hello") 1)
assert (== (count_lines "hello\nworld") 2)
assert (== (count_lines "a\nb\nc") 3)
}
fn to_uppercase(text: string) -> string {
let mut result: string = ""
let mut i: int = 0
while (< i (str_length text)) {
let ch: int = (char_at text i)
if (and (>= ch 97) (<= ch 122)) {
# lowercase letter (a-z), convert to uppercase
set result (+ result (string_from_char (- ch 32)))
} else {
set result (+ result (string_from_char ch))
}
set i (+ i 1)
}
return result
}
shadow to_uppercase {
assert (== (to_uppercase "hello") "HELLO")
assert (== (to_uppercase "World") "WORLD")
assert (== (to_uppercase "123abc") "123ABC")
}
fn main() -> int {
(println "╔════════════════════════════════════════════════════════╗")
(println "║ STDIO FILE PROCESSOR ║")
(println "╚════════════════════════════════════════════════════════╝")
(println "")
(println "Demonstrating file operations:")
(println " • Reading files")
(println " • Transforming text (uppercase)")
(println " • Computing statistics (lines, chars)")
(println "")
# Check if README exists
if (file_exists "README.md") {
(println "✓ Found README.md")
let content: string = (file_read "README.md")
let lines: int = (count_lines content)
let chars: int = (count_chars content)
(println (+ " Lines: " (int_to_string lines)))
(println (+ " Characters: " (int_to_string chars)))
(println "")
(println "✓ File statistics computed successfully!")
} else {
(println "ℹ README.md not found, using sample text")
let sample: string = "Hello\nWorld\nNanoLang"
let lines: int = (count_lines sample)
let chars: int = (count_chars sample)
let upper: string = (to_uppercase sample)
(println (+ " Original: " sample))
(println (+ " Uppercase: " upper))
(println (+ " Lines: " (int_to_string lines)))
(println (+ " Characters: " (int_to_string chars)))
}
(println "")
(println "✓ File processing demo complete!")
return 0
}
shadow main {
assert (== (main) 0)
}
stdlib_ast_demo.nano
/* =============================================================================
* AST Module Demo - Metaprogramming Showcase
*
* Concept: Direct access to Abstract Syntax Tree for code analysis
* Topics: AST, metaprogramming, compiler internals, programmatic code generation
* Difficulty: Advanced
*
* Description:
* Demonstrates NanoLang's unique capability to build and manipulate Abstract
* Syntax Trees programmatically. Shows how to construct AST nodes, create
* code structures, and perform metaprogramming tasks.
*
* Key Features Demonstrated:
* - Programmatic AST node creation
* - AST construction for literals, identifiers, calls
* - Code structure building
* - Metaprogramming capabilities
* - Compiler internals exposure
*
* Use Cases:
* - Building code generators
* - Creating DSLs (Domain Specific Languages)
* - Implementing macros and code transformations
* - Automated refactoring tools
* - Template engines
*
* Prerequisites:
* - Understanding of Abstract Syntax Trees
* - Knowledge of compiler design basics
* - Advanced NanoLang features
*
* Next Steps:
* - Build a simple code generator
* - Create a custom DSL
* - Implement macro system
* - Explore code transformation tools
* =============================================================================
*/
module "stdlib/ast.nano"
fn demo_basic_nodes() -> void {
(println "=== Demo 1: Basic Node Creation ===")
/* Create various node types */
let int_lit: AST = (ast_int "100")
let str_lit: AST = (ast_string "Hello, AST!")
let identifier: AST = (ast_identifier "myVariable")
let function: AST = (ast_function "calculate")
let call: AST = (ast_call "println" 2)
/* Pretty print them */
(println (ast_to_string int_lit))
(println (ast_to_string str_lit))
(println (ast_to_string identifier))
(println (ast_to_string function))
(println (ast_to_string call))
(println "")
}
shadow demo_basic_nodes {
(demo_basic_nodes)
}
fn demo_type_checking() -> void {
(println "=== Demo 2: Type Checking ===")
let num: AST = (ast_int "42")
let text: AST = (ast_string "test")
let var: AST = (ast_identifier "x")
let func_call: AST = (ast_call "add" 2)
/* Check types */
(println "Type checks:")
if (== (ast_is_literal num) true) {
(println " 42 is a literal ✓")
} else {
(println " ERROR")
}
if (== (ast_is_identifier var) true) {
(println " x is an identifier ✓")
} else {
(println " ERROR")
}
if (== (ast_is_call func_call) true) {
(println " add() is a call ✓")
} else {
(println " ERROR")
}
(println "")
}
shadow demo_type_checking {
(demo_type_checking)
}
fn demo_program_structure() -> void {
(println "=== Demo 3: Building Program Structure ===")
/* Build: program with main function */
let prog: AST = (ast_program)
let main_func: AST = (ast_function "main")
let body: AST = (ast_block 2)
(println "Built program structure:")
(println (+ " " (ast_to_string prog)))
(println (+ " " (ast_to_string main_func)))
(println (+ " " (ast_to_string body)))
(println "")
}
shadow demo_program_structure {
(demo_program_structure)
}
fn demo_ast_queries() -> void {
(println "=== Demo 4: AST Queries ===")
let node1: AST = (ast_int "999")
let node2: AST = (ast_call "compute" 3)
/* Get type names */
let type1: string = (ast_type_name node1)
let type2: string = (ast_type_name node2)
(println (+ "Node 1 type: " type1))
(println (+ "Node 2 type: " type2))
/* Check child counts */
(println (+ "Node 2 has " (+ (cast_string node2.child_count) " children")))
(println "")
}
shadow demo_ast_queries {
(demo_ast_queries)
}
fn demo_use_cases() -> void {
(println "=== Demo 5: Real-World Use Cases ===")
(println "")
(println "The AST module enables:")
(println " • Code generation tools")
(println " • AST transformations (optimizers)")
(println " • Static analysis tools")
(println " • Domain-specific languages (DSLs)")
(println " • Parser generators")
(println " • Macro systems")
(println "")
(println "Next: LALR Parser Generator will use this module!")
(println "")
}
shadow demo_use_cases {
(demo_use_cases)
}
fn main() -> int {
(println "")
(println "╔════════════════════════════════════════╗")
(println "║ AST Module - Feature Demonstration ║")
(println "╚════════════════════════════════════════╝")
(println "")
(demo_basic_nodes)
(demo_type_checking)
(demo_program_structure)
(demo_ast_queries)
(demo_use_cases)
(println "╔════════════════════════════════════════╗")
(println "║ Demo Complete! ✓ ║")
(println "╚════════════════════════════════════════╝")
(println "")
return 0
}
testing_strategies.nano (View on GitHub)
ui_code_display_demo.nano
unsafe module "modules/sdl/sdl.nano"
unsafe module "modules/sdl_ttf/sdl_ttf.nano"
unsafe module "modules/sdl_helpers/sdl_helpers.nano"
module "modules/ui_widgets/ui_widgets.nano"
# Build sample code with line breaks
fn build_sample_code() -> string {
let mut code: string = ""
set code (+ code "fn factorial(n: int) -> int {\n")
set code (+ code " if (<= n 1) {\n")
set code (+ code " return 1\n")
set code (+ code " } else {\n")
set code (+ code " return (* n (factorial (- n 1)))\n")
set code (+ code " }\n")
set code (+ code "}\n")
set code (+ code "\n")
set code (+ code "shadow factorial {\n")
set code (+ code " assert (== (factorial 0) 1)\n")
set code (+ code " assert (== (factorial 5) 120)\n")
set code (+ code "}\n")
set code (+ code "\n")
set code (+ code "# Main function example\n")
set code (+ code "fn main() -> int {\n")
set code (+ code " let name: string = \"NanoLang\"\n")
set code (+ code " let version: float = 1.0\n")
set code (+ code " let count: int = 42\n")
set code (+ code " let flag: bool = true\n")
set code (+ code " \n")
set code (+ code " # Array operations\n")
set code (+ code " let arr: array<int> = (array_new 5 0)\n")
set code (+ code " (array_set arr 0 100)\n")
set code (+ code " let val: int = (array_get arr 0)\n")
set code (+ code " \n")
set code (+ code " # Conditionals with cond\n")
set code (+ code " let result: int = (cond\n")
set code (+ code " ((> count 50) 1)\n")
set code (+ code " ((< count 30) -1)\n")
set code (+ code " (else 0)\n")
set code (+ code " )\n")
set code (+ code " return 0\n")
set code (+ code "}\n")
return code
}
shadow build_sample_code {
let code: string = (build_sample_code)
assert (> (str_length code) 100)
}
# Demo of the nl_ui_code_display widget with syntax highlighting
fn main() -> int {
# Initialize SDL and TTF
(SDL_Init SDL_INIT_VIDEO)
(TTF_Init)
# Create window
let window: SDL_Window = (SDL_CreateWindow "Code Display Widget Demo" 100 100 1000 700 SDL_WINDOW_SHOWN)
let renderer: SDL_Renderer = (SDL_CreateRenderer window -1 SDL_RENDERER_ACCELERATED)
# Load fonts
let font: TTF_Font = (TTF_OpenFont "modules/sdl_ttf/fonts/DejaVuSansMono.ttf" 14)
let title_font: TTF_Font = (TTF_OpenFont "modules/sdl_ttf/fonts/DejaVuSansMono.ttf" 18)
# Build sample code
let sample_code: string = (build_sample_code)
let mut running: bool = true
let mut scroll_offset: int = 0
(println "🎨 Code Display Widget Demo")
(println "Press UP/DOWN to scroll")
(println "Press ESC to quit")
(println "")
while running {
# Poll events
let key: int = (nl_sdl_poll_keypress)
if (== key 41) {
# ESC key
set running false
} else {
if (== key 82) {
# UP arrow
if (> scroll_offset 0) {
set scroll_offset (- scroll_offset 1)
} else {}
} else {
if (== key 81) {
# DOWN arrow
set scroll_offset (+ scroll_offset 1)
} else {}
}
}
if (== (nl_sdl_poll_event_quit) 1) {
set running false
} else {}
(nl_ui_update_mouse_state)
# Clear screen
(SDL_SetRenderDrawColor renderer 25 25 35 255)
(SDL_RenderClear renderer)
# Title
(nl_ui_label renderer title_font "Code Display Widget - Syntax Highlighting Demo" 20 10 220 220 255 255)
(nl_ui_label renderer font "Use UP/DOWN arrows to scroll" 20 40 180 180 200 255)
# Display the code with syntax highlighting
(nl_ui_code_display renderer font sample_code 20 70 960 600 scroll_offset 18)
# Scroll indicator
let scroll_text: string = (+ "Scroll: " (int_to_string scroll_offset))
(nl_ui_label renderer font scroll_text 850 40 160 160 180 255)
(SDL_RenderPresent renderer)
(SDL_Delay 16)
}
# Cleanup
(TTF_CloseFont font)
(TTF_CloseFont title_font)
(TTF_Quit)
(SDL_DestroyRenderer renderer)
(SDL_DestroyWindow window)
(SDL_Quit)
return 0
}
shadow main {
# Cannot test windowing functions
}
unicode_demo.nano
/* Unicode String Operations Demo
* Demonstrates grapheme-aware string handling
*/
/* FFI declarations */
extern fn nl_str_byte_length(s: string) -> int
extern fn nl_str_grapheme_length(s: string) -> int
extern fn nl_str_to_lowercase(s: string) -> string
extern fn nl_str_to_uppercase(s: string) -> string
extern fn nl_str_is_ascii(s: string) -> bool
extern fn nl_str_is_valid_utf8(s: string) -> bool
fn main() -> int {
(println "=== Unicode String Operations Demo ===")
(println "")
/* Test ASCII */
(println "ASCII Tests:")
let ascii: string = "Hello, World!"
(print " String: ")
(println ascii)
unsafe {
(print " Byte length: ")
(println (nl_str_byte_length ascii))
(print " Grapheme length: ")
(println (nl_str_grapheme_length ascii))
(print " Is ASCII: ")
(println (nl_str_is_ascii ascii))
}
(println "")
/* Test emoji */
(println "Emoji Tests:")
let emoji: string = "😀😁😂🤣"
(print " String: ")
(println emoji)
unsafe {
(print " Byte length: ")
(println (nl_str_byte_length emoji))
(print " Grapheme length: ")
(println (nl_str_grapheme_length emoji))
(print " Is ASCII: ")
(println (nl_str_is_ascii emoji))
}
(println "")
/* Test complex grapheme (family emoji) */
(println "Complex Grapheme Test:")
let family: string = "👨👩👧👦"
(print " Family emoji: ")
(println family)
unsafe {
(print " Byte length: ")
(println (nl_str_byte_length family))
(print " Grapheme length (should be 1): ")
(println (nl_str_grapheme_length family))
}
(println "")
/* Test case conversion */
(println "Case Conversion Tests:")
let mixed: string = "Hello World"
(print " Original: ")
(println mixed)
unsafe {
(print " Lowercase: ")
(println (nl_str_to_lowercase mixed))
(print " Uppercase: ")
(println (nl_str_to_uppercase mixed))
}
(println "")
/* Test mixed content */
(println "Mixed Content Test:")
let mixed_content: string = "Hello 世界 🌍"
(print " String: ")
(println mixed_content)
unsafe {
(print " Byte length: ")
(println (nl_str_byte_length mixed_content))
(print " Grapheme length: ")
(println (nl_str_grapheme_length mixed_content))
(print " Is valid UTF-8: ")
(println (nl_str_is_valid_utf8 mixed_content))
}
(println "")
(println "✓ All Unicode operations completed successfully!")
(println "")
(println "Key insights:")
(println " • Emoji can be 1 grapheme but many bytes")
(println " • Family emoji (👨👩👧👦) is 1 grapheme despite visual complexity")
(println " • Use grapheme_length for user-visible character count")
(println " • Use byte_length for buffer sizes and file I/O")
return 0
}
/* Note: No shadow test because it uses extern functions */
unsafe_demo.nano
/* Demonstration of unsafe blocks in NanoLang
*
* The `unsafe` keyword marks code sections that perform operations
* requiring extra care. Currently required for:
* - Calls to extern (FFI) functions
*
* By explicitly marking these sections as `unsafe`, the compiler
* enforces that programmers consciously acknowledge potentially
* dangerous operations.
*/
/* Example: Demonstrating unsafe block syntax */
fn computation_in_unsafe_block() -> int {
let mut result: int = 0
/* Unsafe blocks are regular code blocks with the 'unsafe' keyword */
unsafe {
let x: int = 10
let y: int = 5
set result (+ x y)
}
return result
}
shadow computation_in_unsafe_block {
assert (== (computation_in_unsafe_block) 15)
}
/* Example: Nested unsafe blocks */
fn nested_unsafe() -> int {
let mut total: int = 0
unsafe {
let a: int = 10
set total (+ total a)
unsafe {
let b: int = 20
set total (+ total b)
}
}
return total
}
shadow nested_unsafe {
assert (== (nested_unsafe) 30)
}
/* Example: Multiple unsafe blocks in same function */
fn multiple_unsafe_blocks() -> int {
let mut result: int = 0
unsafe {
set result 10
}
/* Regular safe code */
let x: int = (+ result 5)
unsafe {
set result (+ x 5)
}
return result
}
shadow multiple_unsafe_blocks {
assert (== (multiple_unsafe_blocks) 20)
}
fn main() -> int {
(println "=== NanoLang Unsafe Blocks Demo ===")
(println "")
(println "1. Computation in unsafe block:")
(print " Result: ")
(println (computation_in_unsafe_block))
(println "")
(println "2. Nested unsafe blocks:")
(print " Result: ")
(println (nested_unsafe))
(println "")
(println "3. Multiple unsafe blocks:")
(print " Result: ")
(println (multiple_unsafe_blocks))
(println "")
(println "Key points:")
(println "- Extern functions MUST be called inside unsafe blocks")
(println "- Unsafe blocks can be nested")
(println "- Functions can have multiple unsafe blocks")
(println "- Unsafe blocks explicitly mark potentially dangerous code")
return 0
}
shadow main {
assert (== (main) 0)
}
uv_example.nano (View on GitHub)
vector2d_demo.nano
/* =============================================================================
* Vector2D Module Demo
* =============================================================================
* Demonstrates 2D vector mathematics using the std::math::vector2d module.
* Shows: vector creation, operations, normalization, rotation.
*/
from "std/math/vector2d.nano" import Vector2D, vec_new, vec_length, vec_add, vec_normalize, vec_rotate
fn main() -> int {
(println "Testing Vector2D module...")
# Test basic creation
let v1: Vector2D = (vec_new 3.0 4.0)
(print "v1 = (")
(print v1.x)
(print ", ")
(print v1.y)
(println ")")
# Test length
let len: float = (vec_length v1)
(print "Length: ")
(println len)
# Test addition
let v2: Vector2D = (vec_new 1.0 2.0)
let v3: Vector2D = (vec_add v1 v2)
(print "v1 + v2 = (")
(print v3.x)
(print ", ")
(print v3.y)
(println ")")
# Test normalization
let norm: Vector2D = (vec_normalize v1)
(print "Normalized = (")
(print norm.x)
(print ", ")
(print norm.y)
(println ")")
# Test rotation
let pi_over_2: float = 1.5708
let rotated: Vector2D = (vec_rotate (vec_new 1.0 0.0) pi_over_2)
(print "Rotated 90° = (")
(print rotated.x)
(print ", ")
(print rotated.y)
(println ")")
(println "✓ All vector2d tests passed!")
return 0
}
shadow main {
assert (== (main) 0)
}
vector2d_physics_simple.nano
# Vector2D Physics Example (Simplified)
# Demonstrates physics simulation with simple 2D vectors
# Real-world problem: Bouncing ball with gravity
struct Ball {
x: int,
y: int,
vx: int,
vy: int
}
# Update ball position
fn update_ball(ball: Ball) -> Ball {
let new_x: int = (+ ball.x ball.vx)
let new_y: int = (+ ball.y ball.vy)
return Ball { x: new_x, y: new_y, vx: ball.vx, vy: ball.vy }
}
shadow update_ball {
let ball: Ball = Ball { x: 0, y: 0, vx: 5, vy: 10 }
let updated: Ball = (update_ball ball)
assert (== updated.x 5)
assert (== updated.y 10)
}
# Apply gravity
fn apply_gravity(ball: Ball, gravity: int) -> Ball {
let new_vy: int = (+ ball.vy gravity)
return Ball { x: ball.x, y: ball.y, vx: ball.vx, vy: new_vy }
}
shadow apply_gravity {
let ball: Ball = Ball { x: 0, y: 0, vx: 0, vy: 0 }
let updated: Ball = (apply_gravity ball 2)
assert (== updated.vy 2)
}
# Bounce off ground
fn bounce(ball: Ball, ground: int) -> Ball {
if (>= ball.y ground) {
let new_vy: int = (/ (* ball.vy -8) 10) # 80% damping
return Ball { x: ball.x, y: ground, vx: ball.vx, vy: new_vy }
} else {
return ball
}
}
shadow bounce {
let ball: Ball = Ball { x: 0, y: 100, vx: 0, vy: 10 }
let bounced: Ball = (bounce ball 100)
assert (== bounced.y 100)
assert (== bounced.vy -8)
}
fn main() -> int {
(println "╔════════════════════════════════════════════════════════╗")
(println "║ 2D PHYSICS SIMULATION (Bouncing Ball) ║")
(println "╚════════════════════════════════════════════════════════╝")
(println "")
(println "Simulating ball with gravity and ground collision")
(println "")
let mut ball: Ball = Ball { x: 50, y: 0, vx: 2, vy: 0 }
let gravity: int = 2
let ground: int = 100
(println (+ "Initial: y=" (+ (int_to_string ball.y) (+ ", vy=" (int_to_string ball.vy)))))
# Simulate 50 frames
let mut frame: int = 0
while (< frame 50) {
set ball (apply_gravity ball gravity)
set ball (update_ball ball)
set ball (bounce ball ground)
if (== (% frame 10) 0) {
(println (+ "Frame " (+ (int_to_string frame) (+ ": y=" (+ (int_to_string ball.y) (+ ", vy=" (int_to_string ball.vy)))))))
} else {}
set frame (+ frame 1)
}
(println "")
(println "✓ Simulation complete! Ball bounces get smaller due to damping.")
return 0
}
shadow main {
assert (== (main) 0)
}
audio
sdl_audio_player.nano (View on GitHub)
sdl_audio_wav.nano
# Test WAV Playback
# Simple test to verify our converted samples play with SDL_mixer
unsafe module "modules/sdl/sdl.nano"
unsafe module "modules/sdl_mixer/sdl_mixer.nano"
# Command-line argument support
extern fn get_argc() -> int
extern fn get_argv(index: int) -> string
fn main() -> int {
(println "Testing WAV playback...")
# This example plays a user-provided .wav file.
# (Older versions expected a pt2-clone/"ProTracker" sample export step that no longer exists.)
let argc: int = (get_argc)
if (< argc 2) {
(println "")
(println "No WAV file specified.")
(println "Usage: ./bin/sdl_audio_wav path/to/file.wav")
(println "")
(println "Tip: to quickly verify audio output works with a bundled file, run:")
(println " ./bin/sdl_mod_visualizer (plays examples/gabba-studies-12.mod)")
return 1
} else {}
# Initialize SDL
if (!= (SDL_Init SDL_INIT_AUDIO) 0) {
(println "SDL_Init failed")
return 1
} else {}
# Initialize SDL_mixer
if (!= (Mix_OpenAudio 44100 MIX_DEFAULT_FORMAT 2 2048) 0) {
(println "Mix_OpenAudio failed")
(SDL_Quit)
return 1
} else {}
(println "SDL_mixer initialized")
(print "Channels: ")
(println (Mix_AllocateChannels (- 0 1)))
# Load a sample WAV file
let mut sample_file: string = ""
set sample_file (get_argv 1)
(print "Loading: ")
(println sample_file)
let sample: Mix_Chunk = (Mix_LoadWAV sample_file)
if (== sample 0) {
(println "ERROR: Failed to load WAV file")
(println (Mix_GetError))
(println "Make sure the path is correct and the file is a supported .wav.")
(Mix_CloseAudio)
(SDL_Quit)
return 1
} else {}
(println "✓ WAV loaded successfully!")
(println "")
(println "Playing sample on channel 0...")
# Play sample on channel 0, no loops
let channel: int = (Mix_PlayChannel 0 sample 0)
if (== channel (-1)) {
(println "ERROR: Failed to play sample")
} else {
(print "✓ Playing on channel ")
(println channel)
(println "")
(println "Listening for 2 seconds...")
# Wait for playback
(SDL_Delay 2000)
}
# Cleanup
# (Mix_FreeChunk sample) # TODO: Fix void function issue
(Mix_CloseAudio)
(SDL_Quit)
(println "")
(println "✓ Test complete!")
return 0
}
sdl_mod_visualizer.nano (View on GitHub)
sdl_nanoamp.nano (View on GitHub)
sdl_tracker_shell.nano (View on GitHub)
data
json_demo.nano
// JSON Library Demo
module "std/json/json.nano as JSON" as JSON
fn parse_example() -> int {
// Parse JSON string
let json_str: string = "{\"name\": \"Alice\", \"age\": 30, \"active\": true}"
let obj: opaque = (JSON.parse json_str)
if (== obj (null_opaque)) {
(println "Failed to parse JSON")
return 1
}
// Extract values
let name_item: opaque = (JSON.get_field obj "name")
let age_item: opaque = (JSON.get_field obj "age")
let active_item: opaque = (JSON.get_field obj "active")
if (JSON.is_string name_item) {
let name: string = (JSON.get_string name_item)
(println (string_concat "Name: " name))
}
if (JSON.is_number age_item) {
let age: float = (JSON.get_number age_item)
(println (string_concat "Age: " (float_to_string age)))
}
if (JSON.is_bool active_item) {
let active: bool = (JSON.get_bool active_item)
if active {
(println "Status: Active")
} else {
(println "Status: Inactive")
}
}
// Clean up
(JSON.free obj)
return 0
}
fn create_example() -> int {
// Create JSON object
let obj: opaque = (JSON.new_object)
// Add fields
(JSON.add_field obj "name" (JSON.new_string "Bob"))
(JSON.add_field obj "age" (JSON.new_number 25.0))
(JSON.add_field obj "active" (JSON.new_bool true))
// Create array
let arr: opaque = (JSON.new_array)
(JSON.add_to_array arr (JSON.new_string "foo"))
(JSON.add_to_array arr (JSON.new_string "bar"))
(JSON.add_to_array arr (JSON.new_string "baz"))
(JSON.add_field obj "tags" arr)
// Convert to string
let json_str: string = (JSON.stringify obj)
(println "Generated JSON:")
(println json_str)
// Clean up
(JSON.free obj)
return 0
}
fn array_example() -> int {
// Parse array
let json_str: string = "[1, 2, 3, 4, 5]"
let arr: opaque = (JSON.parse json_str)
if (== arr (null_opaque)) {
(println "Failed to parse JSON array")
return 1
}
// Iterate array
let len: int = (JSON.array_length arr)
(println (string_concat "Array length: " (int_to_string len)))
let mut i: int = 0
while (< i len) {
let item: opaque = (JSON.array_get arr i)
if (JSON.is_number item) {
let num: float = (JSON.get_number item)
(println (string_concat " [" (string_concat (int_to_string i)
(string_concat "] = " (float_to_string num)))))
}
set i (+ i 1)
}
(JSON.free arr)
return 0
}
fn main() -> int {
(println "=== JSON Parse Example ===")
(parse_example)
(println "")
(println "=== JSON Create Example ===")
(create_example)
(println "")
(println "=== JSON Array Example ===")
(array_example)
return 0
}
debug
coverage_demo.nano
# examples/coverage_demo.nano - Demonstrate coverage and instrumentation APIs
#
# Shows how to use stdlib/coverage.nano for execution tracing and coverage tracking
from "stdlib/coverage.nano" import coverage_init, coverage_record, coverage_report, coverage_reset
from "stdlib/coverage.nano" import trace_init, trace_record, trace_report, trace_reset
# Example function with manual instrumentation
fn fibonacci(n: int) -> int {
(trace_record "CALL" "fibonacci" (int_to_string n))
(coverage_record "coverage_demo.nano" 12 5)
if (<= n 1) {
(coverage_record "coverage_demo.nano" 15 9)
(trace_record "RETURN" "fibonacci" "base_case")
return n
}
(coverage_record "coverage_demo.nano" 20 5)
let fib1: int = (fibonacci (- n 1))
let fib2: int = (fibonacci (- n 2))
let result: int = (+ fib1 fib2)
(trace_record "RETURN" "fibonacci" (int_to_string result))
return result
}
shadow fibonacci {
assert (== (fibonacci 0) 0)
assert (== (fibonacci 1) 1)
assert (== (fibonacci 5) 5)
}
# Function demonstrating conditional coverage
fn classify_number(x: int) -> string {
(trace_record "CALL" "classify_number" (int_to_string x))
(coverage_record "coverage_demo.nano" 31 5)
if (< x 0) {
(coverage_record "coverage_demo.nano" 34 9)
(trace_record "RETURN" "classify_number" "negative")
return "negative"
} else {
if (== x 0) {
(coverage_record "coverage_demo.nano" 39 13)
(trace_record "RETURN" "classify_number" "zero")
return "zero"
} else {
(coverage_record "coverage_demo.nano" 43 13)
(trace_record "RETURN" "classify_number" "positive")
return "positive"
}
}
}
shadow classify_number {
assert (== (classify_number -3) "negative")
assert (== (classify_number 0) "zero")
assert (== (classify_number 4) "positive")
}
# Function with loop coverage
fn sum_array(arr: array<int>) -> int {
(trace_record "CALL" "sum_array" (int_to_string (array_length arr)))
(coverage_record "coverage_demo.nano" 53 5)
let mut total: int = 0
let mut i: int = 0
while (< i (array_length arr)) {
(coverage_record "coverage_demo.nano" 59 9)
set total (+ total (at arr i))
set i (+ i 1)
}
(trace_record "RETURN" "sum_array" (int_to_string total))
return total
}
shadow sum_array {
assert (== (sum_array []) 0)
assert (== (sum_array [1, 2, 3]) 6)
}
fn main() -> int {
(println "========================================")
(println "Coverage and Instrumentation Demo")
(println "========================================")
(println "")
# Initialize coverage and tracing
(coverage_init)
(trace_init)
(println "=== Test 1: Fibonacci Sequence ===")
let fib5: int = (fibonacci 5)
(println (+ "fibonacci(5) = " (int_to_string fib5)))
(println "")
(println "=== Test 2: Number Classification ===")
let c1: string = (classify_number -5)
(println (+ "classify_number(-5) = " c1))
let c2: string = (classify_number 0)
(println (+ "classify_number(0) = " c2))
let c3: string = (classify_number 10)
(println (+ "classify_number(10) = " c3))
(println "")
(println "=== Test 3: Array Sum ===")
let numbers: array<int> = [1, 2, 3, 4, 5]
let sum: int = (sum_array numbers)
(println (+ "sum([1,2,3,4,5]) = " (int_to_string sum)))
(println "")
# Print coverage report
(coverage_report)
(println "")
# Print execution trace (first 20 events)
(println "Execution Trace (sample):")
(trace_report)
return 0
}
logging_categories_demo.nano
# Demonstration of category-based logging for organizing output
# Shows how categories help separate concerns in larger applications
from "stdlib/log.nano" import log_info, log_debug, log_error
struct User {
name: string,
age: int,
email: string
}
fn validate_user(user: User) -> bool {
(log_info "validation" (+ "Validating user: " user.name))
if (== user.name "") {
(log_error "validation" "Username cannot be empty")
return false
}
if (< user.age 0) {
(log_error "validation" (+ "Invalid age: " (int_to_string user.age)))
return false
}
if (> user.age 150) {
(log_error "validation" (+ "Suspicious age: " (int_to_string user.age)))
return false
}
if (== user.email "") {
(log_error "validation" "Email cannot be empty")
return false
}
(log_info "validation" "User validation passed")
return true
}
shadow validate_user {
let valid_user: User = User { name: "Alice", age: 30, email: "alice@example.com" }
assert (validate_user valid_user)
let invalid_user1: User = User { name: "", age: 30, email: "test@example.com" }
assert (not (validate_user invalid_user1))
let invalid_user2: User = User { name: "Bob", age: -5, email: "bob@example.com" }
assert (not (validate_user invalid_user2))
}
fn save_user(user: User) -> bool {
(log_info "database" (+ "Attempting to save user: " user.name))
if (not (validate_user user)) {
(log_error "database" "User validation failed, cannot save")
return false
}
(log_debug "database" (+ "User data - Name: " (+ user.name (+ ", Age: " (+ (int_to_string user.age) (+ ", Email: " user.email))))))
# Simulate database operation
(log_info "database" "User saved successfully")
return true
}
shadow save_user {
let user: User = User { name: "Charlie", age: 25, email: "charlie@example.com" }
assert (save_user user)
let bad_user: User = User { name: "", age: 25, email: "test@example.com" }
assert (not (save_user bad_user))
}
fn send_welcome_email(user: User) -> bool {
(log_info "email" (+ "Sending welcome email to: " user.email))
if (== user.email "") {
(log_error "email" "Cannot send email: empty email address")
return false
}
(log_debug "email" (+ "Email subject: Welcome, " user.name))
(log_debug "email" (+ "Email recipient: " user.email))
# Simulate email sending
(log_info "email" "Welcome email sent successfully")
return true
}
shadow send_welcome_email {
let user: User = User { name: "Diana", age: 28, email: "diana@example.com" }
assert (send_welcome_email user)
}
fn register_user(name: string, age: int, email: string) -> bool {
(log_info "registration" (+ "Starting user registration for: " name))
let user: User = User { name: name, age: age, email: email }
if (not (save_user user)) {
(log_error "registration" "User registration failed: could not save user")
return false
}
if (not (send_welcome_email user)) {
(log_error "registration" "User saved but welcome email failed")
# Still return true - user is registered even if email fails
}
(log_info "registration" (+ "User registration complete for: " name))
return true
}
shadow register_user {
assert (register_user "Eve" 32 "eve@example.com")
assert (not (register_user "" 32 "test@example.com"))
}
fn main() -> int {
(log_info "app" "=== Category-Based Logging Demonstration ===")
(println "")
(log_info "app" "Notice how categories help organize output:")
(log_info "app" "- [validation] for input validation")
(log_info "app" "- [database] for data persistence")
(log_info "app" "- [email] for email operations")
(log_info "app" "- [registration] for high-level workflow")
(println "")
(log_info "app" "=== Successful Registration ===")
let success: bool = (register_user "Frank" 35 "frank@example.com")
(println "")
(log_info "app" "=== Failed Registration (invalid data) ===")
let failure: bool = (register_user "" 35 "test@example.com")
(println "")
(log_info "app" "=== Failed Registration (invalid age) ===")
let failure2: bool = (register_user "Grace" -10 "grace@example.com")
(println "")
if (and success (and (not failure) (not failure2))) {
(log_info "app" "Demonstration complete - categories help trace execution flow")
return 0
} else {
(log_error "app" "Unexpected results")
return 1
}
}
shadow main {
assert (== (main) 0)
}
logging_demo.nano
# Demo of the structured logging API
from "stdlib/log.nano" import log_debug, log_info, log_trace, log_error
fn calculate_fibonacci(n: int) -> int {
(log_debug "fibonacci" (+ "Calculating fibonacci(" (+ (int_to_string n) ")")))
if (<= n 1) {
(log_trace "fibonacci" (+ "Base case: n=" (int_to_string n)))
return n
} else {
(print "")
}
let a: int = (calculate_fibonacci (- n 1))
let b: int = (calculate_fibonacci (- n 2))
let result: int = (+ a b)
(log_debug "fibonacci" (+ "Result: fibonacci(" (+ (int_to_string n) (+ ") = " (int_to_string result)))))
return result
}
fn main() -> int {
(log_info "app" "Starting logging demo")
(log_info "math" "Calculating fibonacci sequence")
let fib10: int = (calculate_fibonacci 10)
(log_info "result" (+ "Fibonacci(10) = " (int_to_string fib10)))
if (!= fib10 55) {
(log_error "validation" (+ "Expected 55, got " (int_to_string fib10)))
return 1
} else {
(print "")
}
(log_info "app" "Demo complete - all tests passed!")
return 0
}
shadow main {
assert (== (main) 0)
}
logging_levels_demo.nano (View on GitHub)
property_test_math.nano (View on GitHub)
property_test_sorting.nano (View on GitHub)
games
sdl_asteroids.nano (View on GitHub)
sdl_checkers.nano (View on GitHub)
sdl_pong.nano (View on GitHub)
graphics
sdl_boids.nano (View on GitHub)
sdl_drawing_primitives.nano (View on GitHub)
sdl_falling_sand.nano (View on GitHub)
sdl_fire.nano (View on GitHub)
sdl_game_of_life.nano (View on GitHub)
sdl_glass_sphere.nano (View on GitHub)
sdl_image_demo.nano (View on GitHub)
sdl_image_effects.nano (View on GitHub)
sdl_image_sprite_animation.nano (View on GitHub)
sdl_image_test.nano (View on GitHub)
sdl_image_tiled_background.nano (View on GitHub)
sdl_mouse_click.nano (View on GitHub)
sdl_nanoviz.nano (View on GitHub)
sdl_particles.nano (View on GitHub)
sdl_physics_demo.nano (View on GitHub)
sdl_raytracer.nano (View on GitHub)
sdl_starfield.nano (View on GitHub)
sdl_terrain_explorer.nano (View on GitHub)
sdl_texture_demo.nano (View on GitHub)
sdl_ui_widgets_extended.nano (View on GitHub)
language
nl_advanced_math.nano (View on GitHub)
nl_array_bounds.nano (View on GitHub)
nl_array_complete.nano (View on GitHub)
nl_boids.nano (View on GitHub)
nl_calculator.nano (View on GitHub)
nl_checked_math_demo.nano (View on GitHub)
nl_comparisons.nano (View on GitHub)
nl_control_for.nano (View on GitHub)
nl_control_if_while.nano (View on GitHub)
nl_control_match.nano (View on GitHub)
nl_csv_processor.nano (View on GitHub)
nl_data_analytics.nano (View on GitHub)
nl_demo_selfhosting.nano (View on GitHub)
nl_extern_char.nano (View on GitHub)
nl_extern_math.nano (View on GitHub)
nl_extern_string.nano (View on GitHub)
nl_factorial.nano (View on GitHub)
nl_falling_sand.nano (View on GitHub)
nl_fibonacci.nano (View on GitHub)
nl_filter_map_fold.nano (View on GitHub)
nl_first_class_functions.nano (View on GitHub)
nl_floats.nano (View on GitHub)
nl_function_factories_v2.nano (View on GitHub)
nl_function_return_values.nano (View on GitHub)
nl_function_variables.nano (View on GitHub)
nl_functions_basic.nano (View on GitHub)
nl_game_of_life.nano (View on GitHub)
nl_generics_demo.nano (View on GitHub)
nl_hello.nano (View on GitHub)
nl_logical.nano (View on GitHub)
nl_matrix_operations.nano (View on GitHub)
nl_mutable.nano (View on GitHub)
nl_operators.nano (View on GitHub)
nl_pi_calculator.nano (View on GitHub)
nl_primes.nano (View on GitHub)
nl_random_sentence.nano (View on GitHub)
nl_snake.nano (View on GitHub)
nl_string_operations.nano (View on GitHub)
nl_struct.nano (View on GitHub)
nl_tictactoe.nano (View on GitHub)
nl_tracing.nano (View on GitHub)
nl_types.nano (View on GitHub)
nl_types_tuple.nano (View on GitHub)
nl_types_union_construct.nano (View on GitHub)
nl_union_types.nano (View on GitHub)
nl_unsafe_demo.nano (View on GitHub)
nl_word_frequency.nano (View on GitHub)
network
curl_example.nano (View on GitHub)
http_demo.nano (View on GitHub)
http_hello_world.nano (View on GitHub)
http_rest_api.nano (View on GitHub)
http_static_server.nano (View on GitHub)
opengl
opengl_cube.nano (View on GitHub)
opengl_modern_hello_triangle.nano (View on GitHub)
opengl_modern_postprocess.nano (View on GitHub)
opengl_particle_fountain.nano (View on GitHub)
opengl_solar_system.nano (View on GitHub)
opengl_teapot.nano (View on GitHub)
opl
- opl/README.md
- opl/bundle/AST_IR.schema.json
- opl/bundle/BUILTINS.md
- opl/bundle/ERRORS.md
- opl/bundle/EXAMPLES.expected_ast.json
- opl/bundle/EXAMPLES.expected_plan.json
- opl/bundle/EXAMPLES.opl
- opl/bundle/GRAMMAR.ebnf
- opl/bundle/IMPLEMENTATION_GUIDE.md
- opl/bundle/PLAN.md
- opl/bundle/PLAN_IR.schema.json
- opl/bundle/SEMANTICS.md
- opl/bundle/SPEC.md
- opl/bundle/STYLE.md
- opl/bundle/TESTS.cases.json
- opl/bundle/TESTS.md
- opl/bundle/TOKENS.md
- opl/bundle/VALIDATION.md
- opl/examples/Makefile
- opl/examples/README.md
- opl/examples/conditional.opl
- opl/examples/hello.opl
- opl/examples/multi_tool.opl
- opl/examples/output/conditional.ast.json
- opl/examples/output/conditional.plan.json
- opl/examples/output/conditional.validate.json
- opl/examples/output/hello.ast.json
- opl/examples/output/hello.plan.json
- opl/examples/output/web_search.ast.json
- opl/examples/output/web_search.plan.json
- opl/examples/output/web_search.validate.json
- opl/examples/service_spec.opl
- opl/examples/web_search.opl
opl_codegen.nano (View on GitHub)
opl_compile.nano (View on GitHub)
opl_json.nano (View on GitHub)
opl_lexer.nano (View on GitHub)
opl_lexer_driver.nano (View on GitHub)
opl_parser.nano (View on GitHub)
opl_parser_driver.nano (View on GitHub)
opl_validate.nano (View on GitHub)
opl_validate_driver.nano (View on GitHub)
physics
bullet_beads_simple.nano (View on GitHub)
bullet_beads_visual.nano (View on GitHub)
bullet_bouncy_balls.nano (View on GitHub)
bullet_rigid_megastacks.nano (View on GitHub)
bullet_soft_body_beads.nano (View on GitHub)
bullet_soft_body_modern.nano (View on GitHub)
bullet_softbody_hourglass.nano (View on GitHub)
terminal
ncurses_game_of_life.nano (View on GitHub)