diff --git a/.cursorrules b/.cursorrules index f83debf..9028c9b 100644 --- a/.cursorrules +++ b/.cursorrules @@ -1,267 +1,146 @@ -# KU Programming Language - Cursor AI Rules - -## Project Overview -This is the KU programming language - a compiled systems programming language built from scratch using Node.js. The project includes a complete compiler toolchain, interpreter (deprecated), standard library, and VS Code extension. - -## OS/System Support -- **Primary Target**: Linux only (x86 32-bit) -- **Build Dependencies**: - - Node.js (for bootstrap compiler) - - NASM (Netwide Assembler) - - ld (GNU linker) - - Standard Linux development tools -- **Architecture**: Compiles to x86 32-bit assembly (ELF format) -- **System Calls**: Direct Linux syscall interface through `@syscall` built-in - -## Language Capabilities - -### Core Features -- **Static typing** with type annotations (num, str, bol, chr, dec) -- **Manual memory management** with `mmap`/`munmap` syscalls -- **Function definitions** with return type annotations -- **Control flow**: if/else, while loops, for loops, break/continue -- **Variable scoping** (function-local and global) -- **Include system** for modular code -- **Array support** with pointer arithmetic -- **String manipulation** and concatenation -- **Type casting** between basic types - -### Syntax Highlights -```ku -# Variable declaration with type -:variable_name/type = value - -# Function definition -function_name:/return_type param1 type1, param2 type2 { - # function body - ret return_value -} - -# Function calls -@function_name arg1, arg2 - -# Control structures -if condition { - # code -} else if condition { - # code -} else { - # code -} - -for :i/num = 0, i < 10, i++ { - # loop body -} - -while condition { - # loop body -} -``` - -### Data Types -- `num`: 32-bit integers -- `str`: String literals (memory addresses) -- `bol`: Boolean values (true/false) -- `chr`: Single characters -- `dec`: Decimal/floating point numbers -- Arrays: `type[]` (e.g., `num[]`, `str[]`) - -### Built-in Operations -- **Arithmetic**: `+`, `-`, `*`, `/`, `%` -- **Comparison**: `==`, `!=`, `<`, `>`, `<=`, `>=` -- **Logical**: `&&`, `||`, `!` -- **Bitwise**: `&`, `|`, `^` -- **Assignment**: `=` -- **Increment/Decrement**: `++`, `--` (prefix and postfix) -- **Type casting**: `!type value`, `?type value`, `/type` -- **Memory access**: `+pointer` (dereference), `&variable` (address) - -### Standard Library (`libstd/std.ku`) -Essential functions include: -- **I/O**: `out`, `outln`, `rkey`, `rline` -- **String operations**: `strlen`, `strcmp`, `strcut`, `chr2str` -- **Type conversions**: `num2str`, `str2num`, `bol2str`, etc. -- **Memory management**: `mmap`, `munmap`, `mremap` -- **System operations**: `syscall`, `sleep`, `exit` -- **Terminal control**: `clear`, `hide_cursor`, `show_cursor` -- **Random numbers**: `random` - -## Testing Strategy - -### Test Structure -- Located in `testing/tests/` directory -- Each test has a subdirectory with: - - `source.ku`: Test source code - - `expect.log`: Expected output -- Test runner: `testing/tests/index.js` - -### Test Categories -1. **assign**: Variable assignment and scoping -2. **call**: Function calls and nested functions -3. **conditions**: if/else conditional statements -4. **define**: Variable and function definitions -5. **function**: Function definition and return values -6. **loop**: For/while loops with break/continue -7. **prefix_postfix**: Increment/decrement operators - -### Running Tests +# KU Programming Language - Cursor AI Assistant Rules + +## Project Context +This is the KU programming language repository - a complete systems programming language that compiles to x86 32-bit Linux binaries. The project includes a bootstrap compiler (Node.js), standard library, examples, tests, and VS Code extension. + +## Context-Specific Rules +Depending on your current task, refer to these specialized rule files: + +### ๐Ÿงช Testing Context +**File**: `.cursorrules-testing` +**When to use**: Writing tests, debugging test failures, test development +- Compiler testing procedures (`./test.sh -c`) +- Test structure and organization +- Platform-specific testing (Linux/macOS) +- Memory management testing +- CRITICAL: Simulator is deprecated, only use compiler mode + +### ๐Ÿš€ Running Context +**File**: `.cursorrules-running` +**When to use**: Compiling programs, execution issues, runtime debugging +- Compilation workflow (`./kulang.sh`) +- Platform differences (Linux native vs macOS Docker) +- Memory management and syscalls +- Interactive application development +- Performance optimization + +### ๐Ÿ”„ Workflow Context +**File**: `.cursorrules-workflow` +**When to use**: Repository management, contributions, code organization +- Git workflow and branching strategy +- Code quality standards +- File organization guidelines +- Pull request and issue management +- Platform compatibility guidelines + +## Quick Reference + +### Essential Commands ```bash -# Run compiler tests (Linux only) -./test.sh -c +# Compile and run (Linux) +./kulang.sh program.ku -c -o output && ./output -# NOTE: Simulator/interpreter is DEPRECATED and NON-FUNCTIONAL -# Do not use: ./test.sh -s -``` - -### macOS Compatibility -Since KU targets Linux x86 32-bit, it cannot run natively on macOS. However, **full support is available via Docker with Rosetta 2 emulation**. - -**Requirements for macOS:** -1. **Apple Silicon Mac** (M1/M2/M3) - recommended for best performance -2. **Rosetta 2**: `softwareupdate --install-rosetta --agree-to-license` -3. **Docker Desktop** with "Use Rosetta for x86/amd64 emulation" enabled - -**Running KU on macOS:** - -**Use the simple wrapper scripts (works exactly like Linux):** -```bash -# Use kulang-macos.sh instead of kulang.sh -./kulang-macos.sh examples/helloworld.ku -c -o hello +# Compile and run (macOS) +./kulang-macos.sh program.ku -c -o output -# Use test-macos.sh instead of test.sh -./test-macos.sh -c +# Run tests +./test.sh -c # Linux +./test-macos.sh -c # macOS -# Games work automatically with interactive terminal -./kulang-macos.sh examples/snake.ku -c -o snake -./kulang-macos.sh examples/tetris.ku -c -o tetris +# Debug compilation +./kulang.sh program.ku -a # Show AST +./kulang.sh program.ku -c -o program -m # Show assembly ``` -**Why This Works:** -- Rosetta 2 provides near-native x86_64 emulation on Apple Silicon -- Docker provides the required Linux environment with proper syscall support -- The combination allows full KU compilation and execution on macOS - -## Project Guidelines - -### File Structure -- `bootstrap/`: Core compiler implementation (Node.js) - - `index.js`: Main entry point - - `reader.js`: Input lexer - - `tokenizer.js`: Token generation - - `parser.js`: AST generation (727 lines) - - `compile.js`: Assembly code generation (2483 lines) - - `simulate.js`: Interpreter (deprecated) - - `cmd.js`: CLI argument parsing -- `libstd/`: Standard library implementation -- `examples/`: Sample programs (helloworld, snake, tetris) -- `testing/`: Test suite and runner -- `kulang-vscode-extension/`: VS Code syntax highlighting - -### Compilation Process -1. **Lexical Analysis**: `reader.js` โ†’ `tokenizer.js` -2. **Parsing**: `parser.js` creates AST -3. **Code Generation**: `compile.js` generates x86 assembly -4. **Assembly**: NASM assembles to object file -5. **Linking**: GNU ld creates executable +### KU Language Essentials +```ku +include "libstd/std.ku" -### Development Workflow -```bash -# Install dependencies -./install.sh +# Variable declaration +:name/type = value -# Compile and run a program -./kulang.sh path/to/file.ku -c -o output_program -./output_program +# Function definition +function_name:/return_type param1 type1 { + ret value +} -# View AST -./kulang.sh path/to/file.ku -a +# Function call +@function_name arg1, arg2 -# View generated assembly -./kulang.sh path/to/file.ku -c -o program -m +# Basic I/O +@outln "Hello World" +:input/str = @rline ``` -### Code Style -- Use descriptive variable names with type suffixes -- Functions should have clear return type annotations -- Include `libstd/std.ku` for standard functionality -- Use consistent indentation (appears to be 4 spaces) -- Comments use `#` for single-line, `# ... #` for blocks - -### Memory Management -- Strings are heap-allocated and require manual management -- Use `mmap` for dynamic allocation -- Use `munmap` to free allocated memory -- Be careful with string concatenation (creates new allocations) - -### System Integration -- Direct syscall interface for system operations -- Terminal manipulation for interactive programs -- Non-blocking I/O support for real-time applications -- Raw terminal mode for games/interactive apps - -### Limitations & Considerations -- Linux-only due to syscall dependencies -- 32-bit x86 architecture limitation -- No garbage collection (manual memory management) -- Limited error handling capabilities -- No standard library beyond basic operations -- Primarily designed for educational/demonstration purposes - -### VS Code Extension -- Syntax highlighting for `.ku` files -- Language configuration in `kulang-vscode-extension/` -- Install: `cp -r ./kulang-vscode-extension ~/.vscode/extensions` - -## AI Assistant Guidelines -When working with KU code: -1. Always include `libstd/std.ku` for standard functions -2. Use proper type annotations for all variables and functions -3. Remember manual memory management requirements -4. **IMPORTANT**: Only test with compiler mode (`-c`), simulator is broken and deprecated -5. Follow the established syntax patterns from examples -6. Consider Linux syscall limitations when suggesting system operations -7. Be aware this is primarily an educational/experimental language -8. For macOS users, use `./kulang-macos.sh` and `./test-macos.sh` (transparent Docker wrappers) -9. Rosetta 2 + Docker provides full KU language support on Apple Silicon Macs - -## Compiler Architecture Details - -### Bootstrap Compiler Components -- **Reader** (`reader.js`): Character-level input processing with position tracking -- **Tokenizer** (`tokenizer.js`): Converts characters to tokens (keywords, operators, literals) -- **Parser** (`parser.js`): Builds Abstract Syntax Tree with precedence handling -- **Compiler** (`compile.js`): Generates x86 assembly with stack management and syscalls -- **Simulator** (`simulate.js`): JavaScript-based interpreter (DEPRECATED - NON-FUNCTIONAL) - -### Token Types -- `kw`: Keywords (if, else, while, for, ret, break, continue, num, str, bol, chr, dec, include) -- `var`: Variable names and identifiers -- `str`: String literals (double quotes) -- `chr`: Character literals (single quotes) -- `num`: Integer literals -- `dec`: Decimal/float literals -- `punc`: Punctuation (:,(){}[]@$) -- `op`: Operators (+-*/%=&|<>!?^) - -### AST Node Types -- `prog`: Program root with array of statements -- `func`: Function definition with parameters and body -- `var`: Variable declaration/assignment -- `call`: Function call with arguments -- `if`: Conditional statement with optional else -- `for`: For loop with initialization, condition, increment -- `while`: While loop with condition -- `binary`: Binary operations (arithmetic, comparison, logical) -- `assign`: Assignment operations -- `postfix`/`prefix`: Increment/decrement operations -- `ret`: Return statement -- `include`: File inclusion directive - -### Assembly Generation -- **Target**: x86 32-bit ELF format -- **Calling Convention**: Custom stack-based with EBP frame pointer -- **Memory Layout**: - - Data section for string literals and global variables - - Text section for executable code - - Stack for local variables and function calls -- **System Integration**: Direct Linux syscalls via `int 0x80` +## Critical Guidelines + +### โš ๏ธ NEVER Use Simulator +- **DEPRECATED**: `./test.sh -s` and simulator mode +- **ONLY USE**: Compiler mode with `-c` flag +- The interpreter/simulator is broken and non-functional + +### ๐Ÿ–ฅ๏ธ Platform Support +- **Primary**: Linux x86 32-bit (native execution) +- **Secondary**: macOS via Docker + Rosetta 2 (full compatibility) +- **Use**: `kulang-macos.sh` and `test-macos.sh` on macOS + +### ๐Ÿ“ File Management +- **Track**: `.ku` source files, documentation, tests +- **Ignore**: Compiled binaries, temporary files +- **Examples**: Should demonstrate language features progressively + +### ๐Ÿง  Memory Management +- Manual allocation/deallocation required +- String concatenation creates new allocations +- Use mmap/munmap for dynamic memory +- Check for memory leaks in long-running programs + +## AI Assistant Priorities + +### When Writing KU Code +1. Always include `libstd/std.ku` +2. Use proper type annotations +3. Follow manual memory management principles +4. Test compilation before considering complete +5. Provide working, executable examples + +### When Debugging +1. Check compilation first (`-c` mode) +2. Use AST view (`-a`) for syntax issues +3. Use assembly view (`-m`) for generation issues +4. Verify platform-specific execution paths + +### When Contributing +1. Create appropriate tests for new features +2. Follow existing code organization patterns +3. Document new functionality clearly +4. Verify cross-platform compatibility +5. Use descriptive commit messages and PR descriptions + +## Emergency Procedures + +### Broken Compilation +1. Check for syntax errors in KU code +2. Verify all includes are accessible +3. Check bootstrap compiler (Node.js dependencies) +4. Verify system dependencies (NASM, ld) + +### Failed Tests +1. Run individual failing test +2. Check expected vs actual output +3. Verify platform compatibility +4. Check for recent changes that might affect test + +### Performance Issues +1. Profile memory usage patterns +2. Check for inefficient string operations +3. Review algorithm complexity +4. Consider 32-bit integer limitations + +## Project Philosophy +KU is designed as an educational systems programming language that provides: +- Direct hardware/OS interaction via syscalls +- Manual memory management experience +- Compilation to native machine code +- Minimal abstractions for learning +- Cross-platform development (Linux + macOS via Docker) \ No newline at end of file diff --git a/.cursorrules-running b/.cursorrules-running new file mode 100644 index 0000000..1532b0b --- /dev/null +++ b/.cursorrules-running @@ -0,0 +1,217 @@ +# KU Programming Language - Running Context Rules + +## Project Overview +You are working with the KU programming language - a compiled systems programming language that targets Linux x86 32-bit. Focus on execution, compilation, and runtime behavior. + +## Compilation & Execution + +### Standard Workflow +```bash +# Compile a KU program +./kulang.sh path/to/program.ku -c -o output_name + +# Run the compiled program +./output_name + +# macOS users (via Docker + Rosetta 2) +./kulang-macos.sh path/to/program.ku -c -o output_name +``` + +### Compilation Flags +- **`-c`**: Compile mode (REQUIRED - simulator is deprecated) +- **`-o name`**: Output executable name +- **`-a`**: Show Abstract Syntax Tree (debug) +- **`-m`**: Show generated assembly code (debug) + +## Runtime Environment + +### Target Platform +- **Architecture**: x86 32-bit +- **Format**: ELF (Executable and Linkable Format) +- **OS**: Linux syscall interface +- **Memory Model**: Manual management via mmap/munmap + +### System Dependencies +- **NASM**: Netwide Assembler for assembly compilation +- **GNU ld**: Linker for creating executables +- **Linux syscalls**: Direct system interface via `int 0x80` + +## Memory Management + +### Manual Allocation +```ku +# Allocate memory +:ptr/num = @mmap 0, size, 3, 34, -1, 0 + +# Free memory +@munmap ptr, size +``` + +### String Handling +- Strings are heap-allocated and require manual management +- String concatenation creates new allocations +- Always free concatenated strings when done + +### Common Memory Patterns +```ku +# Safe string concatenation pattern +:result/str = str1 + str2 +# ... use result ... +@munmap result, @strlen result +``` + +## Standard Library Usage + +### Essential Functions (`libstd/std.ku`) +```ku +include "libstd/std.ku" + +# I/O Operations +@out "Hello" # Print without newline +@outln "Hello World" # Print with newline +:input/str = @rline # Read line from user +:key/chr = @rkey # Read single key + +# String Operations +:len/num = @strlen str +:cmp/num = @strcmp str1, str2 +:substr/str = @strcut str, start, length + +# Type Conversions +:num_val/num = @str2num str_input +:str_val/str = @num2str number +``` + +## Interactive Applications + +### Terminal Control +```ku +@clear # Clear screen +@hide_cursor # Hide cursor for games +@show_cursor # Show cursor +@sleep milliseconds # Pause execution +``` + +### Game Development Patterns +```ku +# Game loop structure +while game_running { + @clear + @render_game_state + :input/chr = @rkey + @process_input input + @update_game_state + @sleep 16 # ~60 FPS +} +``` + +## Error Handling & Debugging + +### Runtime Errors +- Segmentation faults indicate memory access issues +- Invalid syscall parameters cause program termination +- Check array bounds manually (no automatic checking) + +### Debugging Techniques +```bash +# View generated assembly for debugging +./kulang.sh program.ku -c -o debug -m + +# Check AST structure +./kulang.sh program.ku -a + +# Use strace for syscall debugging (Linux) +strace ./program +``` + +### Common Runtime Issues +1. **Stack overflow**: Deep recursion or large local variables +2. **Memory leaks**: Forgetting to munmap allocated memory +3. **Invalid pointers**: Accessing freed or uninitialized memory +4. **Syscall errors**: Wrong parameters to system calls + +## Performance Considerations + +### Optimization Tips +- Minimize string concatenations (expensive) +- Reuse allocated memory when possible +- Use efficient algorithms for array operations +- Avoid unnecessary syscalls in loops + +### Memory Efficiency +- 32-bit integers only (no 64-bit support) +- Manual stack management for function calls +- Direct memory addressing for performance + +## Platform-Specific Execution + +### Linux (Native) +- Direct syscall execution +- Full performance +- Complete KU feature support + +### macOS (Docker + Rosetta 2) +- Transparent Docker wrapper via `kulang-macos.sh` +- Near-native performance through Rosetta 2 emulation +- Full KU language compatibility +- Automatic container cleanup + +### Execution Environment +- **Working Directory**: Preserved inside container (macOS) +- **File Access**: Current directory mounted automatically +- **Interactive Input**: Full terminal passthrough +- **Signal Handling**: Ctrl+C and other signals work correctly + +## AI Assistant Running Guidelines + +1. **Always use compiler mode** (`-c`) - simulator is broken +2. **Prefer kulang-macos.sh on macOS** for seamless experience +3. **Include libstd/std.ku** for standard functionality +4. **Test interactive programs** to ensure proper I/O handling +5. **Verify memory cleanup** in long-running programs +6. **Check syscall return values** for error handling +7. **Use appropriate data types** (32-bit limitations) +8. **Test both simple and complex programs** to verify functionality + +## Common Execution Patterns + +### Simple Programs +```bash +./kulang.sh examples/helloworld.ku -c -o hello +./hello +``` + +### Interactive Programs +```bash +./kulang.sh examples/snake.ku -c -o snake +./snake # Full terminal interaction works +``` + +### Batch Processing +```bash +# Compile multiple programs +for file in examples/*.ku; do + name=$(basename "$file" .ku) + ./kulang.sh "$file" -c -o "$name" +done +``` + +## Troubleshooting Runtime Issues + +### Compilation Fails +1. Check syntax against KU language rules +2. Verify all included files exist +3. Check function signatures and type annotations +4. Review variable declarations and scoping + +### Runtime Crashes +1. Check memory allocation/deallocation balance +2. Verify array bounds access +3. Check pointer arithmetic +4. Review syscall parameters + +### Performance Issues +1. Profile memory usage patterns +2. Check for unnecessary string operations +3. Review algorithm complexity +4. Monitor syscall frequency in loops diff --git a/.cursorrules-testing b/.cursorrules-testing new file mode 100644 index 0000000..e9f9ee3 --- /dev/null +++ b/.cursorrules-testing @@ -0,0 +1,129 @@ +# KU Programming Language - Testing Context Rules + +## Project Overview +You are working with the KU programming language - a compiled systems programming language that targets Linux x86 32-bit. The project includes a complete compiler toolchain built with Node.js. + +## Testing Environment Setup + +### Target Platform +- **Primary**: Linux x86 32-bit (ELF format) +- **macOS Support**: Via Docker + Rosetta 2 emulation +- **Required Tools**: Node.js, NASM, GNU ld + +### Test Structure +- **Location**: `testing/tests/` directory +- **Format**: Each test has subdirectory with `source.ku` and `expect.log` +- **Runner**: `testing/tests/index.js` +- **Categories**: assign, call, conditions, define, function, loop, prefix_postfix, arrays, etc. + +## Testing Commands + +### Compiler Testing (Primary) +```bash +# Run all compiler tests +./test.sh -c + +# Run on macOS (via Docker) +./test-macos.sh -c +``` + +### Individual Program Testing +```bash +# Compile and test a single program +./kulang.sh path/to/file.ku -c -o output_program +./output_program + +# macOS version +./kulang-macos.sh path/to/file.ku -c -o output_program +``` + +## CRITICAL: Simulator is DEPRECATED +- **NEVER use**: `./test.sh -s` or simulator mode +- **Only use**: Compiler mode (`-c`) for testing +- The interpreter/simulator is broken and non-functional + +## Test Development Guidelines + +### Creating New Tests +1. Create directory in `testing/tests/category_name/` +2. Add `source.ku` with test program +3. Add `expect.log` with expected output +4. Use standard library: `include "libstd/std.ku"` + +### Test Code Standards +```ku +# Always include standard library +include "libstd/std.ku" + +# Use proper type annotations +:variable/type = value + +# Test specific language features +function test_feature:/num { + # test implementation + ret 0 +} + +# Use standard I/O functions +@outln "Test result: " + result +``` + +### Common Test Patterns +- **Variable assignment**: Testing scoping and type system +- **Function calls**: Parameter passing and return values +- **Control flow**: if/else, loops, break/continue +- **Arrays**: Multi-dimensional array manipulation +- **Memory**: mmap/munmap operations +- **System calls**: @syscall functionality + +### Debug Information +```bash +# View AST for debugging +./kulang.sh source.ku -a + +# View generated assembly +./kulang.sh source.ku -c -o program -m + +# Check compilation without execution +./kulang.sh source.ku -c -o program +``` + +## Memory Management Testing +- Test manual memory allocation/deallocation +- Verify string concatenation creates new allocations +- Check pointer arithmetic and dereferencing +- Test mmap/munmap syscall usage + +## Error Handling +- KU has limited error handling capabilities +- Test boundary conditions carefully +- Verify syscall return values +- Check array bounds (no automatic bounds checking) + +## Performance Considerations +- Tests should complete quickly (< 1 second each) +- Avoid infinite loops in test code +- Memory leaks are possible - test cleanup +- Consider 32-bit integer limits in calculations + +## Platform-Specific Notes +- **Linux**: Direct execution of compiled binaries +- **macOS**: All execution happens inside Docker container +- **Docker overhead**: Slight performance impact on macOS +- **File paths**: Use relative paths in test programs + +## AI Assistant Testing Guidelines +1. Always verify compilation with `-c` flag before considering test complete +2. Check expected output matches actual output exactly +3. Test both successful cases and edge cases +4. Remember manual memory management requirements +5. Use descriptive test names that indicate what's being tested +6. Include comments in test source explaining the test purpose +7. Verify tests work on both Linux and macOS (via Docker) + +## Debugging Failed Tests +1. Compile with `-m` to see generated assembly +2. Check AST with `-a` to verify parsing +3. Review tokenization if syntax errors occur +4. Compare expected vs actual output character by character +5. Check for platform-specific differences (line endings, etc.) diff --git a/.cursorrules-workflow b/.cursorrules-workflow new file mode 100644 index 0000000..8406b38 --- /dev/null +++ b/.cursorrules-workflow @@ -0,0 +1,235 @@ +# KU Programming Language - Repository Workflow Rules + +## Project Overview +You are working with the KU programming language repository - a complete systems programming language implementation. Follow these workflow guidelines for effective development and contribution. + +## Repository Structure & File Management + +### Core Directories +- **`bootstrap/`**: Core compiler implementation (Node.js) + - `index.js`: Main entry point + - `parser.js`: AST generation (727 lines) + - `compile.js`: Assembly generation (2483 lines) + - Other core modules: reader, tokenizer, simulator (deprecated) +- **`libstd/`**: Standard library (`std.ku`) +- **`examples/`**: Sample programs and tutorials +- **`testing/`**: Test suite and runner +- **`kulang-vscode-extension/`**: VS Code language support + +### File Types & Handling +- **`.ku` files**: KU source code (track in git) +- **Compiled binaries**: Add to `.gitignore`, never commit +- **Test outputs**: Temporary, don't track +- **Documentation**: Markdown files for project docs + +## Development Workflow + +### Branch Strategy +```bash +# Feature development +git checkout -b feature/description +# Work on changes +git add relevant-files.ku +git commit -m "Descriptive commit message" +git push origin feature/description +# Create PR via GitHub +``` + +### Commit Guidelines +- **Include**: Source `.ku` files, documentation, tests +- **Exclude**: Compiled binaries, temporary files, IDE configs +- **Message format**: Clear description of changes and impact +- **Scope**: Related changes together, atomic commits + +### Pull Request Process +1. Create feature branch +2. Implement changes with tests +3. Verify compilation on target platform +4. Write descriptive PR description +5. Include examples of new functionality + +## Code Quality Standards + +### KU Code Standards +```ku +# Include standard library +include "libstd/std.ku" + +# Proper type annotations +:variable_name/type = value + +# Function documentation +# Purpose: Calculate factorial of n +factorial:/num n num { + if n <= 1 { + ret 1 + } + ret n * @factorial n - 1 +} + +# Clear variable naming +:user_input/str = @rline +:parsed_number/num = @str2num user_input +``` + +### Testing Requirements +- Every new feature needs corresponding tests +- Tests must pass on both Linux and macOS (Docker) +- Include edge cases and error conditions +- Use descriptive test names and documentation + +### Documentation Standards +- Update README for significant changes +- Comment complex algorithms in examples +- Include usage examples for new features +- Document any platform-specific behavior + +## File Organization Guidelines + +### Examples Directory +- **Simple examples**: Basic language feature demonstrations +- **Complex examples**: Games, algorithms, real applications +- **Educational progression**: Start simple, build complexity +- **Naming convention**: Descriptive, lowercase with underscores + +### Testing Organization +``` +testing/tests/ +โ”œโ”€โ”€ feature_name/ +โ”‚ โ”œโ”€โ”€ source.ku # Test program +โ”‚ โ””โ”€โ”€ expect.log # Expected output +โ””โ”€โ”€ index.js # Test runner +``` + +### Code Organization Within Files +- Standard library inclusion first +- Type definitions and constants +- Helper functions before main logic +- Main program flow at bottom +- Clear separation of concerns + +## Platform Compatibility + +### Linux (Primary Target) +- Native compilation and execution +- Full syscall support +- Direct binary execution +- Complete feature set + +### macOS Support (Docker) +- Use `kulang-macos.sh` and `test-macos.sh` +- Transparent Docker integration +- Rosetta 2 emulation required +- Full compatibility maintained + +### Development Environment +```bash +# Check platform and setup +uname -a # Verify platform +./install.sh # Install dependencies + +# Platform-specific testing +if [[ "$OSTYPE" == "darwin"* ]]; then + ./test-macos.sh -c +else + ./test.sh -c +fi +``` + +## Contribution Workflow + +### Before Starting +1. Check existing issues and PRs +2. Understand project scope and limitations +3. Set up development environment +4. Run existing tests to verify setup + +### Development Process +1. **Plan**: Break down feature into testable components +2. **Implement**: Write KU code following project standards +3. **Test**: Create comprehensive test cases +4. **Document**: Update relevant documentation +5. **Review**: Self-review for code quality and completeness + +### Quality Checklist +- [ ] Code compiles without errors +- [ ] All tests pass (compiler mode only) +- [ ] New features have corresponding tests +- [ ] Documentation updated as needed +- [ ] Examples work on both platforms +- [ ] Memory management is correct +- [ ] No compiled binaries committed + +## Issue & PR Management + +### Issue Creation +- Clear problem description +- Steps to reproduce (if bug) +- Expected vs actual behavior +- Platform information +- Code examples where relevant + +### PR Requirements +- Descriptive title and description +- Link to related issues +- Test results included +- Breaking changes highlighted +- Examples of new functionality + +### Code Review Focus +- Correctness of KU syntax and semantics +- Memory management safety +- Test coverage adequacy +- Cross-platform compatibility +- Performance implications + +## AI Assistant Workflow Guidelines + +### When Adding Features +1. Understand existing codebase architecture +2. Follow established patterns and conventions +3. Create comprehensive tests first (TDD approach) +4. Verify compilation and execution +5. Document new functionality clearly + +### When Fixing Bugs +1. Reproduce the issue first +2. Create test case that fails +3. Implement fix +4. Verify test now passes +5. Check for regression in existing tests + +### When Refactoring +1. Ensure all existing tests pass first +2. Make changes incrementally +3. Test after each significant change +4. Update documentation to match changes +5. Consider performance implications + +## Repository Maintenance + +### Regular Tasks +- Run full test suite periodically +- Check for dependency updates (Node.js, NASM) +- Verify examples still work +- Update documentation for accuracy +- Clean up temporary files and binaries + +### Version Management +- Use semantic versioning for releases +- Tag important milestones +- Maintain changelog for significant changes +- Consider backward compatibility impact + +### Community Guidelines +- Welcome contributions from newcomers +- Provide helpful feedback in reviews +- Maintain project scope and focus +- Document design decisions clearly + +## Security Considerations +- KU programs run with full system access +- Review system call usage carefully +- Be cautious with memory operations +- Validate user input in interactive programs +- Consider security implications of examples diff --git a/examples/add_numbers.ku b/examples/add_numbers.ku new file mode 100644 index 0000000..b6d935b --- /dev/null +++ b/examples/add_numbers.ku @@ -0,0 +1,16 @@ +include "../libstd/std.ku" + +# Simple program to add two numbers from stdin +@out "Enter first number: " +:first_input/str = @rline +:first_number/num = @str2num first_input + +@out "Enter second number: " +:second_input/str = @rline +:second_number/num = @str2num second_input + +:sum/num = first_number + second_number +:result/str = @num2str sum + +@out "The sum is: " +@outln result diff --git a/examples/sudoku.ku b/examples/sudoku.ku new file mode 100644 index 0000000..ac439c8 --- /dev/null +++ b/examples/sudoku.ku @@ -0,0 +1,164 @@ +include "../libstd/std.ku" + +# Convert 2D coordinates to 1D index for 9x9 grid +get_index:/num row num, col num { + ret row * 9 + col +} + +# Check if placing a number in a position is valid +is_valid:/bol board num[], row num, col num, number num { + # Check row + for :i/num = 0, i < 9, i++ { + :idx/num = @get_index row, i + if board[idx] == number { + ret false + } + } + + # Check column + for :j/num = 0, j < 9, j++ { + :idx/num = @get_index j, col + if board[idx] == number { + ret false + } + } + + # Check 3x3 subbox + :start_row/num = (row / 3) * 3 + :start_col/num = (col / 3) * 3 + + for :i/num = start_row, i < start_row + 3, i++ { + for :j/num = start_col, j < start_col + 3, j++ { + :idx/num = @get_index i, j + if board[idx] == number { + ret false + } + } + } + + ret true +} + +# Find next empty cell (value 0), returns true if found +find_empty:/bol board num[], row_ptr num, col_ptr num { + for :i/num = 0, i < 9, i++ { + for :j/num = 0, j < 9, j++ { + :idx/num = @get_index i, j + if board[idx] == 0 { + # Store found position in provided addresses + ::row_ptr /num = i + ::col_ptr /num = j + ret true + } + } + } + ret false +} + +# Solve sudoku using backtracking algorithm +solve:/bol board num[] { + # Allocate memory for row and column pointers + :row_addr/num = @mmap $num + :col_addr/num = @mmap $num + + # Find next empty cell + if (@find_empty board, row_addr, col_addr) == false { + # Clean up memory and return true (puzzle solved) + @munmap row_addr, $num + @munmap col_addr, $num + ret true + } + + # Get row and column values + :row/num = ?num row_addr + :col/num = ?num col_addr + + # Try numbers 1-9 + for :number/num = 1, number <= 9, number++ { + if @is_valid board, row, col, number { + # Place number + :idx/num = @get_index row, col + board[idx] = number + + # Recursively solve + if @solve board { + # Clean up memory and return true + @munmap row_addr, $num + @munmap col_addr, $num + ret true + } + + # Backtrack - remove number + board[idx] = 0 + } + } + + # Clean up memory and return false + @munmap row_addr, $num + @munmap col_addr, $num + ret false +} + +# Print the sudoku board +print_board:/bol board num[] { + for :i/num = 0, i < 9, i++ { + if i % 3 == 0 && i != 0 { + @outln "------+-------+------" + } + for :j/num = 0, j < 9, j++ { + if j % 3 == 0 && j != 0 { + @out "| " + } + :idx/num = @get_index i, j + :val/num = board[idx] + if val == 0 { + @out ". " + } else { + @out @num2str val + @out " " + } + } + @outln "" + } +} + +# Main program +main:/bol { + @outln "Sudoku Solver" + @outln "=============" + @outln "" + + # Initialize the board with the example puzzle + # 0 represents empty cells (instead of '.') + :board/num[] = [ + 5, 3, 0, 0, 7, 0, 0, 0, 0, + 6, 0, 0, 1, 9, 5, 0, 0, 0, + 0, 9, 8, 0, 0, 0, 0, 6, 0, + 8, 0, 0, 0, 6, 0, 0, 0, 3, + 4, 0, 0, 8, 0, 3, 0, 0, 1, + 7, 0, 0, 0, 2, 0, 0, 0, 6, + 0, 6, 0, 0, 0, 0, 2, 8, 0, + 0, 0, 0, 4, 1, 9, 0, 0, 5, + 0, 0, 0, 0, 8, 0, 0, 7, 9 + ] + + @outln "Original puzzle:" + @print_board board + @outln "" + + @outln "Solving..." + + if @solve board { + @outln "Solved puzzle:" + @print_board board + @outln "" + @outln "Solution found!" + } else { + @outln "No solution exists for this puzzle." + } + + ret true +} + +# Call the main function +@main diff --git a/examples/sudoku_game.ku b/examples/sudoku_game.ku new file mode 100644 index 0000000..bb85bf3 --- /dev/null +++ b/examples/sudoku_game.ku @@ -0,0 +1,550 @@ +include "../libstd/std.ku" + +# Game constants +:BOARD_SIZE/num = 9 +:TOTAL_CELLS/num = 81 + +# Cell states +:CELL_EMPTY/num = 0 +:CELL_GIVEN/num = 1 # Original puzzle numbers +:CELL_PLAYER/num = 2 # Player-entered numbers + +# Game state (initialized in main function) + +# Convert 2D coordinates to 1D index +get_index:/num row num, col num { + ret row * 9 + col +} + +# Check if placing a number is valid +is_move_valid:/bol board num[], row num, col num, number num { + if number < 1 || number > 9 { + ret false + } + + # Check row + for :i/num = 0, i < 9, i++ { + if i != col { + :idx/num = @get_index row, i + if board[idx] == number { + ret false + } + } + } + + # Check column + for :j/num = 0, j < 9, j++ { + if j != row { + :idx/num = @get_index j, col + if board[idx] == number { + ret false + } + } + } + + # Check 3x3 subbox + :start_row/num = (row / 3) * 3 + :start_col/num = (col / 3) * 3 + + for :i/num = start_row, i < start_row + 3, i++ { + for :j/num = start_col, j < start_col + 3, j++ { + if (i != row || j != col) { + :idx/num = @get_index i, j + if board[idx] == number { + ret false + } + } + } + } + + ret true +} + +# Generate a complete valid Sudoku board (using predefined solution for now) +generate_complete_board:/bol board num[] { + # Manually set the solution values to avoid array literal issues + board[0] = 5 + board[1] = 3 + board[2] = 4 + board[3] = 6 + board[4] = 7 + board[5] = 8 + board[6] = 9 + board[7] = 1 + board[8] = 2 + board[9] = 6 + board[10] = 7 + board[11] = 2 + board[12] = 1 + board[13] = 9 + board[14] = 5 + board[15] = 3 + board[16] = 4 + board[17] = 8 + board[18] = 1 + board[19] = 9 + board[20] = 8 + board[21] = 3 + board[22] = 4 + board[23] = 2 + board[24] = 5 + board[25] = 6 + board[26] = 7 + board[27] = 8 + board[28] = 5 + board[29] = 9 + board[30] = 7 + board[31] = 6 + board[32] = 1 + board[33] = 4 + board[34] = 2 + board[35] = 3 + board[36] = 4 + board[37] = 2 + board[38] = 6 + board[39] = 8 + board[40] = 5 + board[41] = 3 + board[42] = 7 + board[43] = 9 + board[44] = 1 + board[45] = 7 + board[46] = 1 + board[47] = 3 + board[48] = 9 + board[49] = 2 + board[50] = 4 + board[51] = 8 + board[52] = 5 + board[53] = 6 + board[54] = 9 + board[55] = 6 + board[56] = 1 + board[57] = 5 + board[58] = 3 + board[59] = 7 + board[60] = 2 + board[61] = 8 + board[62] = 4 + board[63] = 2 + board[64] = 8 + board[65] = 7 + board[66] = 4 + board[67] = 1 + board[68] = 9 + board[69] = 6 + board[70] = 3 + board[71] = 5 + board[72] = 3 + board[73] = 4 + board[74] = 5 + board[75] = 2 + board[76] = 8 + board[77] = 6 + board[78] = 1 + board[79] = 7 + board[80] = 9 + + ret true +} + +# Create puzzle by removing numbers from complete board +create_puzzle:/bol board num[], cell_types num[] { + # First generate complete board + if (@generate_complete_board board) == false { + ret false + } + + # Initialize all as given numbers + for :i/num = 0, i < 81, i++ { + cell_types[i] = CELL_GIVEN + } + + # Remove numbers to create puzzle (manually set positions to avoid array literal issues) + # Clear specific positions to create a good puzzle + board[2] = 0 + cell_types[2] = CELL_EMPTY + board[3] = 0 + cell_types[3] = CELL_EMPTY + board[5] = 0 + cell_types[5] = CELL_EMPTY + board[6] = 0 + cell_types[6] = CELL_EMPTY + board[7] = 0 + cell_types[7] = CELL_EMPTY + board[8] = 0 + cell_types[8] = CELL_EMPTY + board[10] = 0 + cell_types[10] = CELL_EMPTY + board[11] = 0 + cell_types[11] = CELL_EMPTY + board[14] = 0 + cell_types[14] = CELL_EMPTY + board[15] = 0 + cell_types[15] = CELL_EMPTY + board[17] = 0 + cell_types[17] = CELL_EMPTY + board[19] = 0 + cell_types[19] = CELL_EMPTY + board[20] = 0 + cell_types[20] = CELL_EMPTY + board[23] = 0 + cell_types[23] = CELL_EMPTY + board[25] = 0 + cell_types[25] = CELL_EMPTY + board[26] = 0 + cell_types[26] = CELL_EMPTY + board[29] = 0 + cell_types[29] = CELL_EMPTY + board[30] = 0 + cell_types[30] = CELL_EMPTY + board[32] = 0 + cell_types[32] = CELL_EMPTY + board[33] = 0 + cell_types[33] = CELL_EMPTY + board[35] = 0 + cell_types[35] = CELL_EMPTY + board[37] = 0 + cell_types[37] = CELL_EMPTY + board[38] = 0 + cell_types[38] = CELL_EMPTY + board[41] = 0 + cell_types[41] = CELL_EMPTY + board[42] = 0 + cell_types[42] = CELL_EMPTY + board[45] = 0 + cell_types[45] = CELL_EMPTY + board[47] = 0 + cell_types[47] = CELL_EMPTY + board[48] = 0 + cell_types[48] = CELL_EMPTY + board[50] = 0 + cell_types[50] = CELL_EMPTY + board[51] = 0 + cell_types[51] = CELL_EMPTY + board[54] = 0 + cell_types[54] = CELL_EMPTY + board[55] = 0 + cell_types[55] = CELL_EMPTY + board[57] = 0 + cell_types[57] = CELL_EMPTY + board[60] = 0 + cell_types[60] = CELL_EMPTY + board[61] = 0 + cell_types[61] = CELL_EMPTY + board[63] = 0 + cell_types[63] = CELL_EMPTY + board[64] = 0 + cell_types[64] = CELL_EMPTY + board[66] = 0 + cell_types[66] = CELL_EMPTY + board[69] = 0 + cell_types[69] = CELL_EMPTY + board[70] = 0 + cell_types[70] = CELL_EMPTY + board[72] = 0 + cell_types[72] = CELL_EMPTY + board[73] = 0 + cell_types[73] = CELL_EMPTY + board[74] = 0 + cell_types[74] = CELL_EMPTY + board[75] = 0 + cell_types[75] = CELL_EMPTY + board[78] = 0 + cell_types[78] = CELL_EMPTY + + ret true +} + +# Clear screen and position cursor at top +clear_screen:/bol { + @clear + @out "\x1b[H" # Move cursor to home +} + +# Move cursor to specific position (1-based) +move_cursor:/bol row num, col num { + :row_str/str = @num2str row + :col_str/str = @num2str col + :escape_seq/str = "\x1b[" + row_str + ";" + col_str + "H" + @out escape_seq +} + +# Display the game board +display_board:/bol board num[], cell_types num[], highlight_row num, highlight_col num { + @clear_screen + + @outln "๐ŸŽฏ Interactive Sudoku Game" + @outln "=========================" + @outln "Use arrow keys to move, 1-9 to place numbers, 0/Del to clear" + @outln "ESC to quit" + @outln "" + + # Column headers + @out " " + for :j/num = 0, j < 9, j++ { + if j % 3 == 0 && j != 0 { + @out " " + } + @out @num2str (j + 1) + @out " " + } + @outln "" + + # Top border + @out " โ”Œโ”€" + for :j/num = 0, j < 9, j++ { + @out "โ”€โ”€" + if j == 2 || j == 5 { + @out "โ”ฌโ”€" + } else if j == 8 { + @out "โ”" + } else { + @out "โ”€" + } + } + @outln "" + + # Board rows + for :i/num = 0, i < 9, i++ { + # Row separator + if i == 3 || i == 6 { + @out " โ”œโ”€" + for :j/num = 0, j < 9, j++ { + @out "โ”€โ”€" + if j == 2 || j == 5 { + @out "โ”ผโ”€" + } else if j == 8 { + @out "โ”ค" + } else { + @out "โ”€" + } + } + @outln "" + } + + # Row number and data + @out @num2str (i + 1) + @out " โ”‚ " + + for :j/num = 0, j < 9, j++ { + # Highlight current cursor position + if i == highlight_row && j == highlight_col { + @out "\x1b[7m" # Reverse video + } + + :idx/num = @get_index i, j + :val/num = board[idx] + :cell_type/num = cell_types[idx] + + if val == 0 { + @out ". " + } else { + # Color code: given numbers vs player numbers + if cell_type == CELL_GIVEN { + @out "\x1b[1m" # Bold for given numbers + @out @num2str val + @out "\x1b[0m" # Reset + } else { + @out "\x1b[34m" # Blue for player numbers + @out @num2str val + @out "\x1b[0m" # Reset + } + @out " " + } + + if i == highlight_row && j == highlight_col { + @out "\x1b[0m" # Reset reverse video + } + + if j == 2 || j == 5 { + @out "โ”‚ " + } + } + @out "โ”‚" + @outln "" + } + + # Bottom border + @out " โ””โ”€" + for :j/num = 0, j < 9, j++ { + @out "โ”€โ”€" + if j == 2 || j == 5 { + @out "โ”ดโ”€" + } else if j == 8 { + @out "โ”˜" + } else { + @out "โ”€" + } + } + @outln "" + @outln "" +} + +# Check if puzzle is complete and valid +is_puzzle_complete:/bol board num[] { + # Check if all cells are filled + for :i/num = 0, i < 81, i++ { + if board[i] == 0 { + ret false + } + } + + # Check if all constraints are satisfied + for :i/num = 0, i < 9, i++ { + for :j/num = 0, j < 9, j++ { + :idx/num = @get_index i, j + :val/num = board[idx] + if (@is_move_valid board, i, j, val) == false { + ret false + } + } + } + + ret true +} + +# Show error message temporarily +show_error:/bol message str { + @out "\x1b[31m" # Red color + @outln message + @out "\x1b[0m" # Reset color + @sleep 1000 # Show for 1 second +} + +# Main game loop +game_loop:/bol board num[], cell_types num[] { + :game_running/bol = true + :cursor_row/num = 0 + :cursor_col/num = 0 + + while game_running == true { + @display_board board, cell_types, cursor_row, cursor_col + + # Check for completion + if @is_puzzle_complete board { + @outln "๐ŸŽ‰ Congratulations! You solved the puzzle!" + @outln "Press any key to exit..." + @rkey true + ret true + } + + :row_display/str = @num2str (cursor_row + 1) + :col_display/str = @num2str (cursor_col + 1) + :position_msg/str = "Position: (" + row_display + "," + col_display + ")" + @outln position_msg + + :key/chr = @rkey true + :key_num/num = !num key + + # Handle arrow keys (ANSI escape sequences) + if key_num == 27 { # ESC key + :next_key/chr = @rkey true + if (!num next_key) == 91 { # '[' + :arrow_key/chr = @rkey true + :arrow_num/num = !num arrow_key + + if arrow_num == 65 { # Up arrow + if cursor_row > 0 { + cursor_row-- + } + } else if arrow_num == 66 { # Down arrow + if cursor_row < 8 { + cursor_row++ + } + } else if arrow_num == 67 { # Right arrow + if cursor_col < 8 { + cursor_col++ + } + } else if arrow_num == 68 { # Left arrow + if cursor_col > 0 { + cursor_col-- + } + } + } else { + # ESC pressed alone - quit game + game_running = false + } + } + # Handle number keys (1-9) + else if key_num >= 49 && key_num <= 57 { # '1' to '9' + :number/num = key_num - 48 + :idx/num = @get_index cursor_row, cursor_col + + # Can only modify empty cells or player-entered cells + if cell_types[idx] != CELL_GIVEN { + if @is_move_valid board, cursor_row, cursor_col, number { + board[idx] = number + cell_types[idx] = CELL_PLAYER + } else { + @show_error "โŒ Invalid move! Number conflicts with Sudoku rules." + } + } else { + @show_error "โŒ Cannot modify given numbers!" + } + } + # Handle clear (0 or Delete/Backspace) + else if key_num == 48 || key_num == 127 || key_num == 8 { # '0' or DEL or BS + :idx/num = @get_index cursor_row, cursor_col + if cell_types[idx] == CELL_PLAYER { + board[idx] = 0 + cell_types[idx] = CELL_EMPTY + } else if cell_types[idx] == CELL_GIVEN { + @show_error "โŒ Cannot clear given numbers!" + } + } + # Handle WASD movement (alternative) + else if key == 'w' || key == 'W' { + if cursor_row > 0 { cursor_row-- } + } + else if key == 's' || key == 'S' { + if cursor_row < 8 { cursor_row++ } + } + else if key == 'a' || key == 'A' { + if cursor_col > 0 { cursor_col-- } + } + else if key == 'd' || key == 'D' { + if cursor_col < 8 { cursor_col++ } + } + else if key == 'q' || key == 'Q' { + game_running = false + } + } + + ret true +} + +# Initialize and start the game +main:/bol { + # Allocate memory for game state + :board/num[] = !num[] @mmap (81 * $num) + :cell_types/num[] = !num[] @mmap (81 * $num) + + @outln "๐ŸŽฏ Generating random Sudoku puzzle..." + @outln "Please wait..." + + if (@create_puzzle board, cell_types) == false { + @outln "โŒ Failed to generate puzzle!" + ret false + } + + @outln "โœ… Puzzle created successfully!" + @outln "๐ŸŽฎ Starting game..." + + # Hide cursor commented out for now to avoid potential issues + # @hide_cursor + @game_loop board, cell_types + # @show_cursor + + @clear_screen + @outln "Thanks for playing Sudoku! ๐Ÿ‘‹" + + # Clean up memory + @munmap ?num &board, (81 * $num) + @munmap ?num &cell_types, (81 * $num) + + ret true +} + +# Start the game +@main