diff options
Diffstat (limited to 'awk/rawk/README.md')
-rw-r--r-- | awk/rawk/README.md | 832 |
1 files changed, 85 insertions, 747 deletions
diff --git a/awk/rawk/README.md b/awk/rawk/README.md index e3b3dc4..d68217a 100644 --- a/awk/rawk/README.md +++ b/awk/rawk/README.md @@ -1,812 +1,150 @@ -# rawk - A Functional Programming Language for awk +# rawk +## Make awk rawk. -**rawk** is a modern, functional-style language dialect that compiles to highly portable, standard `awk`. It provides a more expressive syntax for writing awk programs while maintaining full compatibility with existing awk code. +Rawk helps to bring some modern developer comforts to awk while maintaining awk's portability and inbuilt goodness. -## Features - -- **Functional Programming**: Define functions with a clean, modern syntax -- **Portable**: Compiles to standard awk that runs on any implementation -- **Mixed Code**: Seamlessly mix rawk functions with regular awk code -- **Standard Library**: Built-in functional programming utilities -- **Error Handling**: Comprehensive error messages and validation - -## Quick Start - -### Installation - -No installation required! Just download `rawk.awk` and you're ready to go. - -### Basic Usage - -1. **Run the comprehensive demo** (recommended): -```bash -awk -f rawk.awk demo.rawk | awk -f - -``` - -2. **Create a simple program** (`hello.rawk`): +## Create a rawk file (`example.rawk`): ```rawk -$greet = (name) -> "Hello, " name "!"; -$add = (x, y) -> x + y; - BEGIN { - print greet("World") - print "2 + 3 =", add(2, 3) + print "Hello from rawk!" } -``` - -3. **Compile and run**: -```bash -awk -f rawk.awk hello.rawk | awk -f - -``` - -4. **Or compile to a file**: -```bash -awk -f rawk.awk hello.rawk > hello.awk -awk -f hello.awk -``` - -> **💡 Tip**: Start with `demo.rawk` to see most rawk features in action with whimsical fantasy-themed data! - -## Language Syntax - -### Function Definitions - -**Single-line functions**: -```rawk -$add = (x, y) -> x + y; -$greet = (name) -> "Hello, " name; -$square = (x) -> x * x; -``` - -**Multi-line functions**: -```rawk -$calculate_area = (width, height) -> { - area = width * height - return area -}; - -$factorial = (n) -> { - if (n <= 1) { - return 1 - } else { - return n * factorial(n - 1) - } -}; -``` - -### Function Calls - -Functions can be called directly, nested, and recursively: -```rawk -$double = (x) -> x * 2; -$square = (x) -> x * x; -$factorial = (n) -> { - if (n <= 1) return 1 - else return n * factorial(n - 1) -}; -BEGIN { - result = double(square(5)) # Returns 50 - print result - print factorial(5) # Returns 120 +RAWK { + $greet = (name) -> { + return "Hello, " name "!"; + }; + + $add = (x, y) -> { + return x + y; + }; } -``` - -### Mixed awk/rawk Code - -Regular awk code works seamlessly with rawk functions: -```rawk -BEGIN { print "Starting processing..." } - -$process_line = (line) -> "Processed: " line; { - if (length($0) > 10) { - print process_line($0) " (long line)" - } else { - print process_line($0) " (short line)" - } + print greet("World"); + print "2 + 3 =", add(2, 3); + exit 0; } - -END { print "Processing complete." } ``` -## Standard Library +A `.awk` file should, generally, be a totally valid `.rawk` file. Just like any valid JavaScript is valid TypeScript, likewise with awk and rawk. -The following functions are automatically available: - -### Testing Functions -- `assert(condition, message)`: Asserts a condition is true -- `expect_equal(actual, expected, message)`: Asserts actual equals expected -- `expect_true(condition, message)`: Asserts condition is true -- `expect_false(condition, message)`: Asserts condition is false - -### Array Utilities -- `keys(array)`: Returns count of keys in array -- `values(array)`: Returns count of values in array -- `get_keys(array, result)`: Populates result array with keys -- `get_values(array, result)`: Populates result array with values - -### Functional Programming Functions -- `map(func_name, array, result)`: Apply function to each element of array -- `reduce(func_name, array, initial)`: Reduce array using function (left fold) -- `pipe(value, func_name)`: Pipe value through a single function -- `pipe_multi(value, func_names)`: Pipe value through multiple functions -- `dispatch_call(func_name, arg1, arg2, ...)`: Dynamic function dispatch - -### Enhanced Array Utilities -- `filter(predicate_func, array, result)`: Filter array elements based on predicate function -- `find(predicate_func, array)`: Find first element that matches predicate -- `findIndex(predicate_func, array)`: Find index of first element that matches predicate -- `flatMap(func_name, array, result)`: Apply function to each element and flatten the result -- `take(count, array, result)`: Take first n elements from array -- `drop(count, array, result)`: Drop first n elements from array - -### Predicate Functions -**Type Checking:** -- `is_number(value)`: Check if value is a number -- `is_string(value)`: Check if value is a string -- `is_array(value)`: Check if value is an array (limited detection) -- `is_empty(value)`: Check if value is empty - -**Numeric Predicates:** -- `is_positive(value)`: Check if number is positive -- `is_negative(value)`: Check if number is negative -- `is_zero(value)`: Check if number is zero -- `is_integer(value)`: Check if number is integer -- `is_float(value)`: Check if number is float -- `is_even(value)`: Check if number is even -- `is_odd(value)`: Check if number is odd -- `is_prime(value)`: Check if number is prime -- `is_in_range(value, min, max)`: Check if number is in range - -**Boolean Predicates:** -- `is_boolean(value)`: Check if value is boolean (0 or 1) -- `is_truthy(value)`: Check if value is truthy -- `is_falsy(value)`: Check if value is falsy - -**String Predicates:** -- `is_alpha(value)`: Check if string is alphabetic -- `is_numeric(value)`: Check if string is numeric -- `is_alphanumeric(value)`: Check if string is alphanumeric -- `is_whitespace(value)`: Check if string is whitespace -- `is_uppercase(value)`: Check if string is uppercase -- `is_lowercase(value)`: Check if string is lowercase -- `is_palindrome(value)`: Enhanced palindrome detection with better whitespace and punctuation handling -- `is_length(value, target_length)`: Check if string/array has specific length -- `is_hex(value)`: Enhanced hex validation with optional 0x and # prefixes -- `is_csv(value)`: Check if string appears to be CSV format (robust detection with quote handling) -- `is_tsv(value)`: Check if string appears to be TSV format (robust detection with field splitting) - -**Validation Predicates:** -- `is_email(value)`: Enhanced email validation with proper format checking -- `is_url(value)`: Enhanced URL validation supporting multiple protocols (http, https, ftp, ftps, mailto, tel) -- `is_ipv4(value)`: Basic IPv4 validation -- `is_ipv6(value)`: Enhanced IPv6 validation with interface identifiers and proper :: handling -- `is_uuid(value)`: UUID validation (comprehensive format support: hyphenated, no-hyphens, URN format) - -## Usage - -### Basic Compilation +Rawk introduces a new semantic block to awk, so that you can write special forms within the `RAWK {...}` block. +## Compile and run: ```bash -# Compile and run immediately -awk -f rawk.awk my_program.rawk | awk -f - +# Compile to awk +awk -f rawk.awk example.rawk > example.awk -# Compile to file for later use -awk -f rawk.awk my_program.rawk > my_program.awk -awk -f my_program.awk +# Run the compiled program +echo "test" | awk -f example.awk -# Process input data -awk -f rawk.awk processor.rawk | awk -f - input.txt +# Or compile and run in one line +echo "test" | awk -f rawk.awk example.rawk | awk -f - ``` -### Function Definition Syntax - -```rawk -# Single-line functions -$add = (x, y) -> x + y; -$greet = (name) -> "Hello, " name; -$square = (x) -> x * x; - -# Multi-line functions -$calculate = (width, height) -> { - area = width * height - perimeter = 2 * (width + height) - return "Area: " area ", Perimeter: " perimeter -}; - -# Functions with complex logic -$process_data = (data, threshold) -> { - if (data > threshold) { - return "HIGH: " data - } else if (data < 0) { - return "LOW: " data - } else { - return "NORMAL: " data - } -}; -``` +## How to run the example: +```bash +# Compile the example file +awk -f rawk.awk example.rawk > example_output.awk -### Standard Library Usage +# Run with sample log data +awk -f example_output.awk sample.log -```rawk -# Array utilities -$get_stats = (array) -> { - count = keys(array) - sum = 0 - for (i in array) sum += array[i] - return "Count: " count ", Sum: " sum -}; - -# Functional programming -$double = (x) -> x * 2; -$add = (x, y) -> x + y; -BEGIN { - numbers[1] = 1; numbers[2] = 2; numbers[3] = 3; - doubled_count = map("double", numbers, doubled); - sum = reduce("add", numbers); - result = pipe(5, "double"); # result = 10 -} +# Or run with just a few lines +head -10 sample.log | awk -f example_output.awk -# Enhanced utilities -$is_positive = (x) -> x > 0; -$is_even = (x) -> x % 2 == 0; -BEGIN { - data[1] = -1; data[2] = 2; data[3] = -3; data[4] = 4; - positive_count = filter("is_positive", data, positive); - first_even = find("is_even", data); - first_three = take(3, data, first_three); -} +# Or compile and run without outputting an awk file to disk +awk -f rawk.awk example.rawk | awk -f - sample.log ``` -### Testing with Built-in Framework +## Syntax -```rawk -$add = (x, y) -> x + y; -$is_valid_email = (email) -> is_email(email); - -BEGIN { - # Test basic functionality - expect_equal(add(2, 3), 5, "add(2, 3) should return 5"); - - # Test edge cases - expect_equal(add(0, 0), 0, "add(0, 0) should return 0"); - - # Test predicates - expect_true(is_valid_email("user@example.com"), "Valid email should pass"); - expect_false(is_valid_email("invalid-email"), "Invalid email should fail"); - - print "All tests passed!"; -} -``` - -### Mixed AWK and rawk Code +### Function Definitions +All functions go inside an `RAWK { ... }` block. ```rawk -# Standard AWK code -BEGIN { - print "Starting processing..." - FS = "," # Set field separator -} - -# rawk function definitions -$process_line = (line) -> { - if (line ~ /^#/) return "" # Skip comments - return "Processed: " line -}; - -$validate_data = (field1, field2) -> { - if (field1 == "" || field2 == "") return 0 - return 1 -}; - -# AWK pattern-action blocks -/^[^#]/ { # Process non-comment lines - if (validate_data($1, $2)) { - result = process_line($0) - print result - } -} - -END { - print "Processing complete." +RAWK { + $function_name = (param1, param2) -> { + return param1 + param2; + }; } ``` -## Examples - -### 🏰 Comprehensive Demo - -The `demo.rawk` file showcases most rawk features with whimsical fantasy-themed data: - -```bash -# Run the full demo -awk -f rawk.awk demo.rawk | awk -f - -``` - -**Features demonstrated:** -- 20+ predicate functions (validation, type checking, math) -- Array utilities and functional programming -- Enhanced utilities (filter, find, take, drop, flatMap) -- Complex data processing pipelines -- Error handling and edge cases -- Integration testing - -**Fantasy theme includes:** -- Kingdom citizens (Gandalf, Frodo, Aragorn, etc.) -- Magical artifacts and adventurer levels -- Rarity systems and power calculations -- CSV-like data processing - -See `DEMO.md` for detailed documentation of the demo. +### Function Calls +Call rawk functions from anywhere in the code, -### System Monitoring ```rawk -# Process df output to monitor disk usage -$analyze_disk = (filesystem, size, used, avail, percent, mount) -> { - if (percent > 90) { - return "CRITICAL: " filesystem " (" mount ") is " percent "% full!" - } else if (percent > 80) { - return "WARNING: " filesystem " (" mount ") is " percent "% full" - } else { - return "OK: " filesystem " (" mount ") has " avail " blocks free" - } -}; - -/^\/dev\// { - result = analyze_disk($1, $2, $3, $4, $5, $6) - print "DISK: " result +{ + result = add(5, 3); + print result; } ``` -### Log Parsing -```rawk -# Process Apache log entries -$parse_apache_log = (ip, method, url, status, bytes) -> { - if (status >= 400) { - return "ERROR: " status " - " method " " url " from " ip - } else { - return "SUCCESS: " status " - " method " " url " (" bytes " bytes)" - } -}; - -/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ { - result = parse_apache_log($1, $6, $7, $9, $10) - print "APACHE: " result -} -``` +### Mixed Code +Mix and match awk and rawk code, -### CSV Processing ```rawk -# Process employee data with validation -$is_valid_email = (email) -> { - at_pos = index(email, "@") - if (at_pos == 0) return 0 - dot_pos = index(substr(email, at_pos + 1), ".") - return dot_pos > 0 -}; - -$format_employee = (name, email, age, salary, department) -> { - email_status = is_valid_email(email) ? "VALID" : "INVALID" - return name " (" department ") - " email_status " email, $" salary -}; - BEGIN { FS = "," } -NR > 1 { - result = format_employee($1, $2, $3, $4, $5) - print "EMPLOYEE: " result -} -``` - -### Data Processing -```rawk -$filter_positive = (arr, result, i, count) -> { - count = 0 - for (i in arr) { - if (arr[i] > 0) { - result[++count] = arr[i] - } - } - return result -}; - -$sum_array = (arr, sum, i) -> { - sum = 0 - for (i in arr) { - sum += arr[i] - } - return sum -}; - -BEGIN { - data[1] = 10 - data[2] = -5 - data[3] = 20 - data[4] = -3 - data[5] = 15 - - positive = filter_positive(data) - total = sum_array(positive) - print "Sum of positive numbers:", total -} -``` - -### Data Format Detection -```rawk -$process_data_line = (line) -> { - if (is_hex(line)) { - return "Hexadecimal: " line - } else if (is_csv(line)) { - return "CSV data: " line - } else if (is_tsv(line)) { - return "TSV data: " line - } else { - return "Unknown format: " line - } -}; - -$validate_uuid = (uuid) -> { - if (is_uuid(uuid)) { - return "Valid UUID: " uuid - } else { - return "Invalid UUID: " uuid - } -}; - -BEGIN { - test_data[1] = "FF00AA" - test_data[2] = "name,age,city" - test_data[3] = "id\tname\tvalue" - test_data[4] = "plain_text" - test_data[5] = "123e4567-e89b-12d3-a456-426614174000" - test_data[6] = "123e4567e89b12d3a456426614174000" - test_data[7] = "urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6" - - for (i in test_data) { - result = process_data_line(test_data[i]) - print result - } - - print "" - print "UUID Validation Examples:" - print validate_uuid("123e4567-e89b-12d3-a456-426614174000") - print validate_uuid("123e4567e89b12d3a456426614174000") - print validate_uuid("urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6") - print validate_uuid("invalid-uuid") - - print "" - print "Enhanced Predicate Examples:" - print "Email validation:" - print " user@domain.com -> " (is_email("user@domain.com") ? "VALID" : "INVALID") - print " user name@domain.com -> " (is_email("user name@domain.com") ? "VALID" : "INVALID") - print " user@@domain.com -> " (is_email("user@@domain.com") ? "VALID" : "INVALID") - - print "URL validation:" - print " https://example.com -> " (is_url("https://example.com") ? "VALID" : "INVALID") - print " ftp://example.com -> " (is_url("ftp://example.com") ? "VALID" : "INVALID") - print " mailto:user@example.com -> " (is_url("mailto:user@example.com") ? "VALID" : "INVALID") - - print "Hex validation:" - print " 0xDEADBEEF -> " (is_hex("0xDEADBEEF") ? "VALID" : "INVALID") - print " #ff0000 -> " (is_hex("#ff0000") ? "VALID" : "INVALID") - print " deadbeef -> " (is_hex("deadbeef") ? "VALID" : "INVALID") -} - -### Functional Programming -```rawk -$double = (x) -> x * 2; -$add = (x, y) -> x + y; -$square = (x) -> x * x; -$add_one = (x) -> x + 1; - -BEGIN { - # Create test data - numbers[1] = 1 - numbers[2] = 2 - numbers[3] = 3 - numbers[4] = 4 - numbers[5] = 5 - - # Map: Apply function to each element - doubled_count = map("double", numbers, doubled) - print "Doubled numbers:" - for (i = 1; i <= doubled_count; i++) { - print " " doubled[i] - } - - # Reduce: Sum all numbers - sum = reduce("add", numbers) - print "Sum of numbers:", sum - - # Pipe: Single function pipeline - result = pipe(5, "square") - print "5 squared:", result - - # Pipe_multi: Multiple function pipeline - func_names[1] = "double" - func_names[2] = "add_one" - result = pipe_multi(5, func_names) - print "5 doubled then +1:", result - - # Complex composition: Sum of squares - squared_count = map("square", numbers, squared) - sum_of_squares = reduce("add", squared) - print "Sum of squares:", sum_of_squares -} - -### Enhanced Array Utilities -```rawk -$is_positive = (x) -> x > 0; -$is_even = (x) -> x % 2 == 0; -$is_valid_email = (email) -> is_email(email); -BEGIN { - # Test data - numbers[1] = -1 - numbers[2] = 0 - numbers[3] = 1 - numbers[4] = -5 - numbers[5] = 10 - numbers[6] = -3 - numbers[7] = 7 - - emails[1] = "user@example.com" - emails[2] = "invalid-email" - emails[3] = "another@domain.org" - emails[4] = "not-an-email" - - # Filter positive numbers - positive_count = filter("is_positive", numbers, positive_numbers) - print "Positive numbers (count:", positive_count, "):" - for (i = 1; i <= positive_count; i++) { - print " " positive_numbers[i] - } - - # Find first even number - first_even = find("is_even", numbers) - print "First even number:", first_even - - # Find index of first negative number - first_negative_index = findIndex("is_negative", numbers) - print "First negative at index:", first_negative_index - - # Filter valid emails - valid_emails_count = filter("is_valid_email", emails, valid_emails) - print "Valid emails (count:", valid_emails_count, "):" - for (i = 1; i <= valid_emails_count; i++) { - print " " valid_emails[i] - } - - # Integration: Filter then map - filtered_count = filter("is_positive", numbers, filtered) - doubled_count = map("double", filtered, doubled_filtered) - print "Doubled positive numbers (count:", doubled_count, "):" - for (i = 1; i <= doubled_count; i++) { - print " " doubled_filtered[i] - } +RAWK { + $process = (field) -> { + return "Processed: " field; + }; } -### Advanced Array Transformation -```rawk -$split_words = (text, result) -> { - split(text, result, " ") - return length(result) -}; - -$double = (x) -> x * 2; - -BEGIN { - # Test data - texts[1] = "hello world" - texts[2] = "functional programming" - texts[3] = "awk is awesome" - - numbers[1] = 1 - numbers[2] = 2 - numbers[3] = 3 - numbers[4] = 4 - numbers[5] = 5 - - # flatMap: Extract all words from texts - words_count = flatMap("split_words", texts, all_words) - print "All words (count:", words_count, "):" - for (i = 1; i <= words_count; i++) { - print " " all_words[i] - } - - # take: Get first 3 numbers - first_three_count = take(3, numbers, first_three) - print "First 3 numbers (count:", first_three_count, "):" - for (i = 1; i <= first_three_count; i++) { - print " " first_three[i] - } - - # drop: Remove first 2 numbers - remaining_count = drop(2, numbers, remaining) - print "Remaining numbers (count:", remaining_count, "):" - for (i = 1; i <= remaining_count; i++) { - print " " remaining[i] - } - - # Complex composition: flatMap -> take -> map - all_words_count = flatMap("split_words", texts, all_words) - first_five_count = take(5, all_words, first_five_words) - doubled_count = map("double", first_five_words, doubled_words) - print "Doubled first 5 words (count:", doubled_count, "):" - for (i = 1; i <= doubled_count; i++) { - print " " doubled_words[i] +{ + if ($1 != "") { + print process($1); } } ``` -``` -``` -``` - -## Test Files -The project includes a comprehensive test suite organized in the `tests/` directory: +## Standard Library +Rawk boasts a rather large standard library. -### Directory Structure -``` -tests/ -├── core/ # Core language features -├── real_world/ # Practical examples -├── stdlib/ # Standard library tests -├── data/ # Test data files -└── README.md # Test documentation +### Testing +```rawk +expect_equal(add(2, 3), 5, "Addition should work"); +expect_true(is_positive(5), "5 should be positive"); ``` -### Core Language Tests (`tests/core/`) -- `test_suite.rawk`: Comprehensive test suite with 15+ test cases -- `test_basic.rawk`: Basic function definitions and calls -- `test_multiline.rawk`: Multi-line function definitions -- `test_edge_cases.rawk`: Edge cases and error conditions -- `test_recursive.rawk`: Recursive function support -- `test_array_fix.rawk`: Array handling and utilities -- `test_failure.rawk`: Demonstrates failing assertions - -### Real-World Examples (`tests/real_world/`) -- `test_system_monitor.rawk`: System monitoring (df, ps, ls output) -- `test_log_parser.rawk`: Log parsing (Apache, syslog format) -- `test_csv_processor.rawk`: CSV data processing with validation -- `test_data_processing.rawk`: General data processing scenarios -- `test_mixed.rawk`: Mixed awk and rawk code - -### Standard Library Tests (`tests/stdlib/`) -- `test_stdlib_simple.rawk`: Tests for built-in functions -- `test_functional.rawk`: Tests for functional programming features -- `test_enhanced_utilities_simple.rawk`: Tests for enhanced array utilities (Phase 1) -- `test_phase2_utilities.rawk`: Tests for advanced array transformation (Phase 2) - -### Test Data (`tests/data/`) -- `test_data.txt`: Simulated system command outputs -- `test_logs.txt`: Sample Apache and syslog entries -- `test_employees.csv`: Sample employee data -- `test_input.txt`: Simple input data for mixed tests - -Run tests with: -```bash -# Run the comprehensive test suite -awk -f rawk.awk tests/core/test_suite.rawk | awk -f - - -# Run real-world examples -awk -f rawk.awk tests/real_world/test_system_monitor.rawk | awk -f - tests/data/test_data.txt -awk -f rawk.awk tests/real_world/test_log_parser.rawk | awk -f - tests/data/test_logs.txt -awk -f rawk.awk tests/real_world/test_csv_processor.rawk | awk -f - tests/data/test_employees.csv - -# Run individual core tests -awk -f rawk.awk tests/core/test_basic.rawk | awk -f - +### Type Checking Predicates +```rawk +if (is_number(value)) { ... } +if (is_string(value)) { ... } ``` -### Writing Tests - -rawk includes a built-in testing framework with assertion functions: - +### Varuius Validation Predicates ```rawk -$add = (x, y) -> x + y; - -BEGIN { - # Test basic functionality - result = add(2, 3) - expect_equal(result, 5, "add(2, 3) should return 5") - - # Test edge cases - result = add(0, 0) - expect_equal(result, 0, "add(0, 0) should return 0") - - # Test boolean conditions - expect_true(add(2, 2) == 4, "2 + 2 should equal 4") - expect_false(add(2, 2) == 5, "2 + 2 should not equal 5") - - print "All tests passed!" -} +if (is_email(email)) { ... } +if (is_url(url)) { ... } ``` -## Compilation Process - -1. **Parse**: rawk function definitions are parsed using `split` on the `->` symbol -2. **Generate**: Internal awk functions are generated with unique names (`__lambda_0`, `__lambda_1`, etc.) -3. **Dispatch**: A dispatch table maps public function names to internal names -4. **Replace**: Function calls are replaced with internal names during compilation -5. **Output**: Standard library functions are prepended to the final awk script - -## Limitations +### Functional Programming Patterns +```rawk +# Transform array elements +count = map("double", numbers, doubled); -- **Function Names**: Must be valid awk identifiers (letters, digits, underscores) -- **Array Returns**: Functions cannot return arrays (use pass-by-reference instead) -- **Array Order**: AWK doesn't guarantee array iteration order in `for (i in array)` -- **Dynamic Dispatch**: Limited to functions defined at compile time -- **Argument Count**: Maximum 5 arguments per function (dispatch table limitation) -- **Function Count**: No practical limit, but large numbers may impact performance +# Filter array elements +count = filter("is_positive", numbers, positive); -## Error Handling +# Reduce array to single value +sum = reduce("add", numbers); +``` -The compiler provides helpful error messages for: -- **Syntax Errors**: Invalid function definition syntax, missing `->` symbols -- **Argument Errors**: Malformed argument lists, too many arguments -- **Function Errors**: Missing functions, argument count mismatches -- **Runtime Errors**: Array access issues, type conversion problems +## Testing -### Common Error Messages +Run the test suite, ```bash -# Missing function -Error: Function 'my_function' not found - -# Argument count mismatch -Error: Invalid argument count for function 'add' - -# Syntax error -Error: Invalid function definition syntax at line 5 +cd tests && ./test_runner.sh ``` -### Debugging Tips - -1. **Check function names**: Ensure they're valid awk identifiers -2. **Verify argument counts**: Match function definition with calls -3. **Use testing framework**: Add assertions to catch issues early -4. **Test incrementally**: Add functions one at a time - -## Performance and Best Practices - -### Performance Considerations -- **Function Count**: Large numbers of functions may impact compilation time -- **Array Operations**: Use `keys()` and `values()` for efficient array counting -- **Predicate Functions**: Use built-in predicates for better performance -- **Memory Usage**: Large arrays should be processed in chunks - -### Best Practices -1. **Function Naming**: Use descriptive names that indicate purpose -2. **Error Handling**: Always validate inputs with predicate functions -3. **Testing**: Write tests for edge cases and error conditions -4. **Documentation**: Add comments to complex functions -5. **Modularity**: Break large programs into logical function groups - -### Optimization Tips -- Use single-line functions for simple operations -- Minimize array copying in loops -- Leverage built-in predicates instead of custom validation -- Use `filter()` and `map()` for bulk operations +## Requirements -## Portability - -- **Target**: Standard awk (nawk, BSD awk) -- **Avoids**: gawk-specific features -- **Uses**: Only standard awk constructs and functions -- **Compatibility**: Works on any POSIX-compliant system - -## Contributing - -1. Add test cases for new features -2. Ensure compatibility with standard awk -3. Update documentation for new functionality -4. Test on multiple awk implementations +- Any awk implementation (gawk, mawk, nawk, etc.) +- No additional dependencies, strives to work with any POSIX awk ## License -This project is open source. Feel free to use, modify, and distribute as needed. - -## Acknowledgments - -Inspired by the need for a more expressive syntax for awk programming while maintaining the portability and simplicity that makes awk so powerful. \ No newline at end of file +Public Domain \ No newline at end of file |