Full Code of multikernel/kernelscript for AI

main 82279e5cd1d9 cached
196 files
2.8 MB
751.6k tokens
32 symbols
1 requests
Download .txt
Showing preview only (3,007K chars total). Download the full file or copy to clipboard to get everything.
Repository: multikernel/kernelscript
Branch: main
Commit: 82279e5cd1d9
Files: 196
Total size: 2.8 MB

Directory structure:
gitextract_4pa0mdxk/

├── .github/
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── BUILTINS.md
├── LICENSE
├── README.md
├── SPEC.md
├── dune-project
├── examples/
│   ├── basic_match.ks
│   ├── break_continue_unbound.ks
│   ├── common_kfuncs.kh
│   ├── dynptr.ks
│   ├── error_handling_demo.ks
│   ├── extern_kfunc_demo.ks
│   ├── functions.ks
│   ├── import/
│   │   ├── network_utils.py
│   │   └── simple_utils.ks
│   ├── import_demo.ks
│   ├── include_demo.ks
│   ├── local_global_vars.ks
│   ├── map_operations_demo.ks
│   ├── maps_demo.ks
│   ├── multi_programs.ks
│   ├── named_return.ks
│   ├── object_allocation.ks
│   ├── packet_filter.ks
│   ├── packet_matching.ks
│   ├── pattern_test.ks
│   ├── pointer_simple.ks
│   ├── print_demo.ks
│   ├── private_kfunc.ks
│   ├── probe.kh
│   ├── probe_do_exit.ks
│   ├── python_demo.py
│   ├── rate_limiter.ks
│   ├── ringbuf_demo.ks
│   ├── ringbuf_on_event_demo.ks
│   ├── safety_demo.ks
│   ├── sched_ext_ops.kh
│   ├── sched_ext_simple.ks
│   ├── simple_gfp_test.ks
│   ├── simple_program_lifecycle.ks
│   ├── string_test.ks
│   ├── struct_ops_simple.ks
│   ├── symbols.ks
│   ├── tail_call.ks
│   ├── tc.kh
│   ├── tcp_congestion_ops.kh
│   ├── test_config.ks
│   ├── test_error_handling.ks
│   ├── test_exec.ks
│   ├── test_functions.ks
│   ├── tracepoint.kh
│   ├── tracepoint_sched_switch.ks
│   ├── type_alias.ks
│   ├── type_checking.ks
│   ├── types_demo.ks
│   ├── userspace_example.ks
│   ├── xdp.kh
│   └── xdp_kfuncs.kh
├── kernelscript.opam
├── src/
│   ├── ast.ml
│   ├── btf_binary_parser.ml
│   ├── btf_binary_parser.mli
│   ├── btf_parser.ml
│   ├── btf_parser.mli
│   ├── btf_stubs.c
│   ├── codegen_common.ml
│   ├── context/
│   │   ├── context_codegen.ml
│   │   ├── context_codegen.mli
│   │   ├── dune
│   │   ├── fprobe_codegen.ml
│   │   ├── kprobe_codegen.ml
│   │   ├── tc_codegen.ml
│   │   ├── tracepoint_codegen.ml
│   │   └── xdp_codegen.ml
│   ├── dune
│   ├── dynptr_bridge.ml
│   ├── ebpf_c_codegen.ml
│   ├── evaluator.ml
│   ├── import_resolver.ml
│   ├── include_resolver.ml
│   ├── ir.ml
│   ├── ir_analysis.ml
│   ├── ir_function_system.ml
│   ├── ir_generator.ml
│   ├── kernel_module_codegen.ml
│   ├── kernel_module_codegen.mli
│   ├── kernelscript_bridge.ml
│   ├── lexer.mll
│   ├── loop_analysis.ml
│   ├── main.ml
│   ├── map_assignment.ml
│   ├── map_operations.ml
│   ├── maps.ml
│   ├── multi_program_analyzer.ml
│   ├── multi_program_ir_optimizer.ml
│   ├── parse.ml
│   ├── parser.mly
│   ├── python_bridge.ml
│   ├── safety_checker.ml
│   ├── stdlib.ml
│   ├── struct_ops_registry.ml
│   ├── struct_ops_registry.mli
│   ├── symbol_table.ml
│   ├── tail_call_analyzer.ml
│   ├── test_codegen.ml
│   ├── type_checker.ml
│   └── userspace_codegen.ml
└── tests/
    ├── dune
    ├── test_address_of_user_types.ml
    ├── test_all_examples.sh
    ├── test_array_init.ml
    ├── test_array_literals.ml
    ├── test_ast.ml
    ├── test_bpf_loop_callbacks.ml
    ├── test_break_continue.ml
    ├── test_btf_binary_parser.ml
    ├── test_comment_positions.ml
    ├── test_compound_index_assignment.ml
    ├── test_config.ml
    ├── test_config_struct_generation.ml
    ├── test_config_validation.ml
    ├── test_const_variables.ml
    ├── test_context_field_types.ml
    ├── test_definition_order.ml
    ├── test_detach_api.ml
    ├── test_dynptr_bridge.ml
    ├── test_ebpf_c_codegen.ml
    ├── test_ebpf_string_generation.ml
    ├── test_enum.ml
    ├── test_error_handling.ml
    ├── test_evaluator.ml
    ├── test_exec.ml
    ├── test_extern.ml
    ├── test_for_statements.ml
    ├── test_function_generation.ml
    ├── test_function_pointers.ml
    ├── test_function_scope.ml
    ├── test_function_validation.ml
    ├── test_global_var.ml
    ├── test_global_var_ordering.ml
    ├── test_iflet.ml
    ├── test_import_system.ml
    ├── test_include.ml
    ├── test_integer_literal.ml
    ├── test_ir.ml
    ├── test_ir_analysis.ml
    ├── test_ir_function_system.ml
    ├── test_ir_patterns.ml
    ├── test_kfunc_attribute.ml
    ├── test_lexer.ml
    ├── test_map_assignment.ml
    ├── test_map_flags.ml
    ├── test_map_integration.ml
    ├── test_map_operations.ml
    ├── test_map_syntax.ml
    ├── test_maps.ml
    ├── test_match.ml
    ├── test_named_returns.ml
    ├── test_nested_if_codegen.ml
    ├── test_object_allocation.ml
    ├── test_parser.ml
    ├── test_pinned_globals.ml
    ├── test_pointer_syntax.ml
    ├── test_private_attribute.ml
    ├── test_probe.ml
    ├── test_program_ref.ml
    ├── test_return_path_analysis.ml
    ├── test_return_value_propagation.ml
    ├── test_ringbuf.ml
    ├── test_safety_checker.ml
    ├── test_stdlib.ml
    ├── test_string_codegen.ml
    ├── test_string_literal_bugs.ml
    ├── test_string_struct_fixes.ml
    ├── test_string_to_array_unification.ml
    ├── test_string_type.ml
    ├── test_struct_field_access.ml
    ├── test_struct_initialization.ml
    ├── test_struct_ops.ml
    ├── test_symbol_table.ml
    ├── test_tail_call.ml
    ├── test_tc.ml
    ├── test_test_attribute.ml
    ├── test_tracepoint.ml
    ├── test_truthy_falsy.ml
    ├── test_type_alias.ml
    ├── test_type_checker.ml
    ├── test_userspace.ml
    ├── test_userspace_for_codegen.ml
    ├── test_userspace_maps.ml
    ├── test_userspace_skeleton_header.ml
    ├── test_userspace_statements.ml
    ├── test_userspace_struct_flexibility.ml
    ├── test_utils.ml
    └── test_void_functions.ml

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
        ocaml-compiler:
          - "4.13.x"

    runs-on: ${{ matrix.os }}

    steps:
    - name: Checkout tree
      uses: actions/checkout@v4

    - name: Set-up OCaml ${{ matrix.ocaml-compiler }}
      uses: ocaml/setup-ocaml@v3
      with:
        ocaml-compiler: ${{ matrix.ocaml-compiler }}
        opam-repositories: |
          default: https://github.com/ocaml/opam-repository.git

    - name: Install system dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y libelf-dev zlib1g-dev libbpf-dev

    - name: Install dependencies
      run: |
        opam install dune menhir alcotest
        opam install . --deps-only

    - name: Build project
      run: eval $(opam env) && dune build

    - name: Run tests
      run: eval $(opam env) && dune build @tests

    - name: Run example tests
      run: eval $(opam env) && bash tests/test_all_examples.sh || true
      continue-on-error: true



================================================
FILE: .gitignore
================================================
# Build directories
_build/
*.install

# Cursor editor files
.cursor/

# OCaml build artifacts
*.cmi
*.cmo
*.cmx
*.cma
*.cmxa
*.a
*.o
*.so
*.exe

# Dune artifacts
.merlin
*.opam.locked

# Editor and IDE files
.vscode/
.idea/
*.swp
*.swo
*~


================================================
FILE: BUILTINS.md
================================================
# KernelScript Builtin Functions Reference

This document provides a comprehensive reference for all builtin functions available in KernelScript. These functions are context-aware and translate differently depending on the execution environment (eBPF, userspace, or kernel module).

## Overview

KernelScript builtin functions provide essential functionality across different execution contexts:
- **eBPF Context**: Functions available within eBPF programs running in kernel space
- **Userspace Context**: Functions available in userspace programs that manage eBPF programs
- **Kernel Module Context**: Functions available when compiling to kernel modules

## Builtin Functions by Category

### 1. Input/Output Functions

#### `print(...)`
**Signature:** `print(...) -> u32`
**Variadic:** Yes (accepts any number of arguments)
**Context:** All contexts

**Description:** Print formatted output to the appropriate output stream based on context.

**Context-specific implementations:**
- **eBPF:** Uses `bpf_printk` to write to kernel trace log (limited to format string + 3 arguments)
- **Userspace:** Uses `printf` to write to console/stdout
- **Kernel Module:** Uses `printk` to write to kernel log

**Parameters:**
- Variable number of arguments of any type
- First argument typically used as format string in userspace/kernel contexts

**Return Value:**
- Returns `0` on success (like standard printf family)
- Returns error code on failure

**Examples:**
```kernelscript
print("Hello, world!")
print("Value:", 42)
print("Multiple values:", x, y, z)
```

**Notes:**
- In eBPF context, limited to 4 total arguments due to `bpf_printk` restrictions
- Automatically handles type conversion for different contexts

---

### 2. Program Lifecycle Management

#### `load(function)`
**Signature:** `load(function) -> ProgramHandle`
**Variadic:** No
**Context:** Userspace only

**Description:** Load an eBPF program function and return a handle for subsequent operations.

**Parameters:**
- `function`: Any function with eBPF attributes (`@xdp`, `@kprobe`, `@tracepoint`, etc.)

**Return Value:**
- Returns a `ProgramHandle` that can be used with `attach()` and `detach()`
- Handle represents the loaded eBPF program file descriptor

**Examples:**
```kernelscript
@xdp
fn my_xdp_program(ctx: *xdp_md) -> xdp_action {
    return XDP_PASS
}

fn main() -> i32 {
    var prog = load(my_xdp_program)
    // Use prog with attach()
    return 0
}
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `bpf_prog_load` system call
- **Kernel Module:** Not available

---

#### `attach(handle, target, flags)`
**Signature:** `attach(handle: ProgramHandle, target: str(128), flags: u32) -> u32`
**Variadic:** No
**Context:** Userspace only

**Description:** Attach a loaded eBPF program to a target interface or attachment point.

**Parameters:**
- `handle`: Program handle returned from `load()`
- `target`: Target interface name (e.g., "eth0", "lo") or attachment point
- `flags`: Attachment flags (context-dependent)

**Return Value:**
- Returns `0` on success
- Returns error code on failure

**Examples:**
```kernelscript
var prog = load(my_xdp_program)
var result = attach(prog, "eth0", 0)
if (result != 0) {
    print("Failed to attach program")
}
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `bpf_prog_attach` system call
- **Kernel Module:** Not available

---

#### `detach(handle)`
**Signature:** `detach(handle: ProgramHandle) -> void`
**Variadic:** No
**Context:** Userspace only

**Description:** Detach a loaded eBPF program from its current attachment point.

**Parameters:**
- `handle`: Program handle returned from `load()`

**Return Value:**
- No return value (void)

**Examples:**
```kernelscript
var prog = load(my_xdp_program)
attach(prog, "eth0", 0)
// ... program runs ...
detach(prog)  // Clean up
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `detach_bpf_program_by_fd` function
- **Kernel Module:** Not available

---

### 3. Struct Operations (struct_ops)

#### `register(impl_instance)`
**Signature:** `register(impl_instance) -> u32`
**Variadic:** No
**Context:** Userspace only

**Description:** Register an implementation block instance with the kernel for struct_ops programs.

**Parameters:**
- `impl_instance`: Instance of a struct with `@struct_ops` attribute

**Return Value:**
- Returns `0` on success
- Returns error code on failure

**Validation:**
- Only accepts impl block instances with `@struct_ops` attribute
- Validates that the struct_ops type is known to the kernel
- Must be used with properly attributed implementation blocks

**Examples:**
```kernelscript
@struct_ops("tcp_congestion_ops")
impl TcpCongestion {
    // Implementation methods here
}

fn main() -> i32 {
    var tcp_impl = TcpCongestion {}
    var result = register(tcp_impl)
    return result
}
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `IRStructOpsRegister` instruction
- **Kernel Module:** Not available

---

### 4. Testing and Development

#### `test(program, test_data)`
**Signature:** `test(program, test_data) -> u32`
**Variadic:** No
**Context:** Userspace only (from `@test` functions only)

**Description:** Execute an eBPF program with test data and return the program's return value.

**Parameters:**
- `program`: eBPF program to test
- `test_data`: Test input data for the program

**Return Value:**
- Returns the program's return value
- Can be used to verify program behavior in tests

**Restrictions:**
- Can only be called from functions with the `@test` attribute
- Used for unit testing eBPF programs

**Examples:**
```kernelscript
@test
fn test_my_program() -> i32 {
    var result = test(my_xdp_program, test_packet_data)
    // Assert result == expected_value
    return result
}
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `bpf_prog_test_run` system call
- **Kernel Module:** Not available

---

### 5. Event Processing

#### `dispatch(...)`
**Signature:** `dispatch(ringbuf1, ringbuf2, ...) -> i32`
**Variadic:** Yes (accepts multiple ring buffer arguments)
**Context:** Userspace only

**Description:** Poll multiple ring buffers for events and dispatch them to their registered callbacks.

**Parameters:**
- Variable number of ring buffer arguments (RingbufRef or Ringbuf types)
- Each ring buffer should have associated event callbacks

**Return Value:**
- Returns `0` on success
- Returns error code on failure

**Validation:**
- All arguments must be ring buffer types
- Requires at least one ring buffer argument

**Examples:**
```kernelscript
var rb1: ringbuf<u32>(1024)
var rb2: ringbuf<u64>(2048)

fn main() -> i32 {
    // Poll both ring buffers for events
    var result = dispatch(rb1, rb2)
    return result
}
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `ring_buffer__poll` from libbpf
- **Kernel Module:** Not available

---

### 6. Process Management

#### `daemon()`
**Signature:** `daemon() -> void`
**Variadic:** No
**Context:** Userspace only

**Description:** Become a daemon process by detaching from the terminal and running in the background.

**Parameters:**
- No parameters

**Return Value:**
- Never returns in practice (process becomes daemon)
- Type system requires void return type

**Examples:**
```kernelscript
fn main() -> i32 {
    print("Starting daemon...")
    daemon()  // Process detaches from terminal
    // Code here runs as daemon
    return 0
}
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `daemon_builtin` custom implementation
- **Kernel Module:** Not available

---

#### `exec(python_script)`
**Signature:** `exec(python_script: str(256)) -> void`
**Variadic:** No
**Context:** Userspace only

**Description:** Replace the current process with a Python script, inheriting all eBPF maps and file descriptors.

**Parameters:**
- `python_script`: Path to Python script file (must have .py extension)

**Return Value:**
- Never returns (replaces current process)
- Type system requires void return type

**Validation:**
- Script path must be a string
- File suffix validation occurs during code generation
- Python script inherits eBPF program state

**Examples:**
```kernelscript
fn main() -> i32 {
    // Set up eBPF programs and maps
    var prog = load(my_program)
    attach(prog, "eth0", 0)
    
    // Hand off to Python for advanced processing
    exec("advanced_analysis.py")  // Never returns
}
```

**Context-specific implementations:**
- **eBPF:** Not available
- **Userspace:** Uses `exec_builtin` custom implementation
- **Kernel Module:** Not available

---

## Context Availability Summary

| Function | eBPF | Userspace | Kernel Module | Notes |
|----------|------|-----------|---------------|-------|
| `print()` | ✅ | ✅ | ✅ | Different output destinations |
| `load()` | ❌ | ✅ | ❌ | Program management only |
| `attach()` | ❌ | ✅ | ❌ | Program management only |
| `detach()` | ❌ | ✅ | ❌ | Program management only |
| `register()` | ❌ | ✅ | ❌ | struct_ops registration |
| `test()` | ❌ | ✅ | ❌ | Testing framework only |
| `dispatch()` | ❌ | ✅ | ❌ | Event processing only |
| `daemon()` | ❌ | ✅ | ❌ | Process management only |
| `exec()` | ❌ | ✅ | ❌ | Process replacement only |

## Related Concepts

### Helper Functions vs. Builtin Functions

- **Builtin Functions**: Defined by KernelScript, context-aware, part of the language
- **Helper Functions**: User-defined functions with `@helper` attribute, compiled as eBPF helpers
- **Kernel Functions (kfuncs)**: External kernel functions declared with `extern` or `@kfunc`

### External Functions

KernelScript also supports external kernel functions that can be declared and called:

```kernelscript
// External eBPF helper functions
extern bpf_ktime_get_ns() -> u64
extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32
extern bpf_get_current_pid_tgid() -> u64

// Usage in eBPF programs
@xdp
fn my_program(ctx: *xdp_md) -> xdp_action {
    var timestamp = bpf_ktime_get_ns()
    return XDP_PASS
}
```

### Error Handling

Most builtin functions return error codes where appropriate:
- `0`: Success
- Non-zero: Error (specific meaning depends on function)

Always check return values for functions that can fail:

```kernelscript
var result = attach(prog, "eth0", 0)
if (result != 0) {
    print("Failed to attach program, error:", result)
    return result
}
```

## See Also

- **SPEC.md**: Language specification and features
- **examples/**: Example programs demonstrating builtin function usage

================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright 2025 Cong Wang

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
![KernelScript Logo](logo.png)

# KernelScript

> **⚠️ Beta Version Notice**
> KernelScript is currently in beta development. The language syntax, APIs, and features are subject to change at any time without backward compatibility guarantees. This software is intended for experimental use and early feedback. Production use is not recommended at this time.

**A Domain-Specific Programming Language for eBPF-Centric Development**

KernelScript is a modern, type-safe, domain-specific programming language that unifies eBPF, userspace, and kernelspace development in a single codebase. Built with an eBPF-centric approach, it provides a clean, readable syntax while generating efficient C code for eBPF programs, coordinated userspace programs, and seamless kernel module (kfunc) integration.

KernelScript aims to become the programming language for Linux kernel customization and application-specific optimization. By leveraging kfunc and eBPF capabilities, it provides a modern alternative to traditional kernel module interfaces such as procfs and debugfs.

## Why KernelScript?

### The Problem with Current eBPF Development

Writing eBPF programs today is challenging and error-prone:

- **Raw C + libbpf**: Requires deep eBPF knowledge, extensive boilerplate code for multiple program types
- **Kernel development complexity**: Understanding eBPF verifier constraints, BPF helper functions, and kernel context
- **Kernel version compatibility**: Managing different kernel APIs, struct layouts, and available kfuncs across kernel versions
- **Complex tail call management**: Manual program array setup, explicit `bpf_tail_call()` invocation, and error handling for failed tail calls
- **Intricate dynptr APIs**: Manual management of `bpf_ringbuf_reserve_dynptr()`, `bpf_dynptr_data()`, `bpf_dynptr_write()`, and proper cleanup sequences
- **Complex struct_ops implementation**: Manual function pointer setup, intricate BTF type registration, kernel interface compliance, and lifecycle management
- **Complex kfunc implementation**: Manual kernel module creation, BTF symbol registration, export management, and module loading coordination
- **Userspace coordination**: Manually writing loaders, map management, and program lifecycle management of different kinds
- **Multiple programming paradigms**: Developers must master userspace application development, eBPF kernel programming, and kernel module (kfunc) programming

### Why Not Existing Tools?

**Why not Rust?**
- **Mixed compilation targets**: Rust's crate-wide, single-target compilation model cannot emit both eBPF bytecode and userspace binaries from one source file. KernelScript's `@xdp`, `@tc`, and regular functions compile to different targets automatically
- **No first-class eBPF program values**: Rust lacks compile-time reflection to treat functions as values with load/attach lifecycle guarantees. KernelScript's type system prevents calling `attach()` before `load()` succeeds
- **Cross-domain shared maps**: Rust's visibility and orphan rules conflict with KernelScript's implicit map sharing across programs. Safe userspace APIs for BPF maps require complex build-time generation in Rust
- **Verifier-incompatible features**: Rust's generics and complex type system often produce code rejected by the eBPF verifier. KernelScript uses fixed-width arrays (`u8[64]`) and simplified types designed for verifier compatibility
- **Error handling mismatch**: Rust's `Result<T,E>` model doesn't align with eBPF's C-style integer error codes. KernelScript's throw/catch works seamlessly in both userspace and eBPF contexts
- **Missing eBPF-specific codegen**: Rust/LLVM cannot automatically generate BPF tail calls or kernel module code for `@kfunc` attributes - features that require deep compiler integration

**Why not bpftrace?**
- Domain-specific for tracing only (no XDP, TC, etc.)
- Limited programming constructs (no complex data structures, functions)
- Interpreted at runtime rather than compiled
- No support for multi-program coordination

**Why not Python/Go eBPF libraries?**
- Still require writing eBPF programs in C
- Only handle userspace coordination, not the eBPF programs themselves
- Complex build systems and dependency management

### KernelScript's Solution

KernelScript addresses these problems through revolutionary language features:

✅ **Single-file multi-target compilation** - Write userspace, eBPF, and kernel module code in one file. The compiler automatically targets each function correctly based on attributes (`@xdp`, `@helper`, `@kfunc`, and regular userspace functions)

✅ **Automatic tail call orchestration** - Simply write `return other_xdp_func(ctx)` and the compiler handles program arrays, `bpf_tail_call()` generation, and error handling automatically

✅ **Transparent dynptr integration** - Use simple pointer operations (`ringbuffer.reserve()`, `some_map[key]`) while the compiler automatically uses complex dynptr APIs (`bpf_ringbuf_reserve_dynptr`, `bpf_dynptr_write`) behind the scenes

✅ **First-class program lifecycle safety** - Programs are typed values with compile-time guarantees that prevent calling `attach()` before `load()` succeeds

✅ **Zero-boilerplate shared state** - Maps are automatically accessible across all programs as regular global variables in a programming language

✅ **Ergonomic map idioms** - Declaration-as-condition (`if (var s = m[k]) { s.field = ... }`) and compound assignment on map indices (`m[k].count += 1`) compile down to a single presence-checked lookup with in-place mutation, no manual write-back

✅ **Builtin kfunc support** - Define full-privilege kernel functions that eBPF programs can call directly, automatically generating kernel modules and BTF registrations

✅ **Unified error handling** - C-style integer throw/catch works seamlessly in both eBPF and userspace contexts, unlike complex Result types

✅ **Verifier-optimized type system** - Fixed-size arrays (`u8[64]`), simple type aliases, and no complex generics that confuse the eBPF verifier

✅ **Complete automated toolchain** - Generate ready-to-use projects with Makefiles, userspace loaders, kernel modules (if kfunc is defined) and build systems from a single source file  

✅ **Automatic BTF extraction** - Seamlessly extract available kfuncs and kernel struct definitions from specified BTF files during project initialization


### Why Choose KernelScript?

| Feature | Raw C + libbpf | Rust eBPF | bpftrace | **KernelScript** |
|---------|---------------|-----------|----------|------------------|
| **Syntax** | Complex C | Complex Rust | Simple but limited | Clean & readable |
| **Type Safety** | Manual | Yes | Limited | Yes |
| **Multi-program** | Manual | Manual | No | Automatic |
| **Build System** | Manual Makefiles | Cargo complexity | N/A | Generated |
| **Userspace Code** | Manual | Manual | N/A | Generated |
| **Learning Curve** | Steep | Steep | Easy but limited | Moderate |
| **Program Types** | All | Most | Tracing only | All |

KernelScript combines the power of low-level eBPF programming with the productivity of modern programming languages, making eBPF development accessible to a broader audience while maintaining the performance and flexibility that makes eBPF powerful.

## Language Overview

### Program Types and Contexts

KernelScript supports all major eBPF program types with typed contexts:

```kernelscript
// XDP program for packet processing
@xdp fn packet_filter(ctx: *xdp_md) -> xdp_action {
    var packet_size = ctx->data_end - ctx->data
    var timestamp = get_current_timestamp()  // Call our custom kfunc
    
    if (packet_size > 1500) {
        return XDP_DROP
    }
    return XDP_PASS
}

// TC program for traffic control
@tc("ingress")
fn traffic_shaper(ctx: *__sk_buff) -> i32 {
    if (ctx->len > 1000) {
        return TC_ACT_SHOT  // Drop large packets
    }
    return TC_ACT_OK
}

// Probe for kernel function tracing
@probe fn trace_syscall(ctx: *pt_regs) -> i32 {
    // Trace system call entry
    return 0
}
```

### Type System

KernelScript has a rich type system designed for systems programming:

```kernelscript
// Type aliases for clarity
type IpAddress = u32
type Counter = u64
type PacketSize = u16

// Struct definitions
struct PacketInfo {
    src_ip: IpAddress,
    dst_ip: IpAddress,
    protocol: u8,
    size: PacketSize
}

// Enums for constants
enum FilterAction {
    ALLOW = 0,
    BLOCK = 1,
    LOG = 2
}
```

### Maps and Data Structures

Built-in support for all eBPF map types:

```kernelscript
// Pinned maps persist across program restarts
pin var connection_count : hash<IpAddress, Counter>(1024)

// Per-CPU maps for better performance
var cpu_stats : percpu_array<u32, u64>(256)

// LRU maps for automatic eviction
var recent_packets : lru_hash<IpAddress, PacketInfo>(1000)

```

### Functions and Helpers

Clean function syntax with helper function support:

```kernelscript
// Custom kernel function - runs in kernel space with full privileges
@kfunc
fn get_current_timestamp() -> u64 {
    // Access kernel-only functionality using kernel APIs
    return ktime_get_ns()  // Direct kernel API call
}

// Helper functions for eBPF programs
@helper
fn extract_src_ip(ctx: *xdp_md) -> IpAddress {
    // Packet parsing logic
    return 0x7f000001  // 127.0.0.1
}

// Regular userspace functions
fn update_stats(ip: IpAddress, size: PacketSize) {
    connection_count[ip] = connection_count[ip] + 1
}

// Function pointers for callbacks
type PacketHandler = fn(PacketInfo) -> FilterAction

fn process_packet(info: PacketInfo, handler: PacketHandler) -> FilterAction {
    return handler(info)
}
```

### Pattern Matching and Control Flow

Modern control flow with pattern matching:

```kernelscript
// Pattern matching on enums
fn handle_action(action: FilterAction) -> xdp_action {
    return match (action) {
        ALLOW: XDP_PASS,
        BLOCK: XDP_DROP,
        LOG: {
            // Log and allow
            event_log[0] = 1
            XDP_PASS
        }
    }
}

// Map lookup and update patterns — declaration-as-condition binds
// `count` only inside the truthy branch; one map lookup, no extra
// presence-check variable.
fn lookup_or_create(ip: IpAddress) -> Counter {
    if (var count = connection_count[ip]) {
        return count  // Entry exists
    } else {
        connection_count[ip] = 1  // Create new entry
        return 1
    }
}

// Declaration-as-condition: bind only inside the truthy branch.
// For struct-valued maps, the bound name is the lookup pointer, so
// field access auto-derefs and the generated eBPF performs in-place
// mutation against the underlying entry — no write-back needed.
pin var ip_stats : hash<IpAddress, PacketInfo>(1024)

@helper
fn record_packet(ip: IpAddress, size: PacketSize) {
    if (var stats = ip_stats[ip]) {
        stats.size = size
    } else {
        ip_stats[ip] = PacketInfo { src_ip: ip, dst_ip: 0, protocol: 0, size: size }
    }
}

// Compound assignment indexes into struct-valued maps directly:
@helper
fn bump_size(ip: IpAddress, delta: PacketSize) {
    ip_stats[ip].size += delta   // emits a presence-checked ptr->size += delta
}
```

### Multi-Program Coordination

Cordination between multiple eBPF programs is just natural:

```kernelscript
// Shared map between programs
pin var shared_counter : hash<u32, u32>(1024)

// XDP program increments counter
@xdp fn packet_counter(ctx: *xdp_md) -> xdp_action {
    shared_counter[1] = shared_counter[1] + 1
    return XDP_PASS
}

// TC program reads counter
@tc("ingress")
fn packet_reader(ctx: *__sk_buff) -> int {
    var count = shared_counter[1]
    if (count > 1000) {
        return TC_ACT_SHOT  // Rate limiting
    }
    return TC_ACT_OK
}

// Userspace coordination
fn main() -> i32 {
    var xdp_prog = load(packet_counter)
    var tc_prog = load(packet_reader)
    
    attach(xdp_prog, "eth0", 0)
    attach(tc_prog, "eth0", 0)
    
    return 0
}
```

📖 **For detailed language specification, syntax reference, and advanced features, please read [`SPEC.md`](SPEC.md).**

🔧 **For complete builtin functions reference, see [`BUILTINS.md`](BUILTINS.md).**

## Command Line Usage

### Initialize a New Project

Create a new KernelScript project with template code:

```bash
# Create XDP project
kernelscript init xdp my_packet_filter

# Create TC project  
kernelscript init tc/egress my_traffic_shaper

# Create probe project
kernelscript init probe/sys_read my_tracer

# Create project with custom BTF path
kernelscript init --btf-vmlinux-path /custom/path/vmlinux xdp my_project

# Create XDP project with kfuncs extracted
kernelscript init --kfuncs xdp my_packet_filter

# Create struct_ops project
kernelscript init tcp_congestion_ops my_congestion_control
```

After initialization, you get:

```
my_project/
├── my_project.ks          # Generated KernelScript source without user code
└── README.md              # Usage instructions
```

**Available program types:**
- `xdp` - XDP programs for packet processing
- `tc` - Traffic control programs  
- `probe` - Kernel function probing
- `tracepoint` - Kernel tracepoint programs

**Available struct_ops:**
- `tcp_congestion_ops` - TCP congestion control


### Compile KernelScript Programs

Compile `.ks` files to eBPF C code and userspace programs:

```bash
# Basic compilation
kernelscript compile my_project/my_project.ks

# Specify output directory
kernelscript compile my_project/my_project.ks -o my_output_dir
kernelscript compile my_project/my_project.ks --output my_output_dir

# Verbose compilation
kernelscript compile my_project/my_project.ks -v
kernelscript compile my_project/my_project.ks --verbose

# Don't generate Makefile
kernelscript compile my_project/my_project.ks --no-makefile

# Also generates tests and only @test functions become main
kernelscript compile --test my_project/my_project.ks

# Custom BTF path
kernelscript compile my_project/my_project.ks --btf-vmlinux-path /custom/path/vmlinux
```

### Complete Project Structure

After compilation, you get a complete project:

```
my_project/
├── my_project.ks          # KernelScript source
├── my_project.c           # Generated userspace program
├── my_project.ebpf.c      # Generated eBPF C code
├── my_project.mod.c       # Generated kernel module (when any kfunc exists)
├── my_project.test.c      # Generated test run code (when using --test mode)
├── Makefile               # Build system
└── README.md              # Usage instructions
```

### Build and Run

```bash
cd my_project/
make                       # Build both eBPF and userspace programs
sudo ./my_project          # Run the program
```

## Getting Started

1. **Install system dependencies (Debian/Ubuntu):**
   ```bash
   sudo apt update
   sudo apt install libbpf-dev libelf-dev zlib1g-dev opam bpftool
   ```

2. **Install KernelScript:**
   ```bash
   git clone https://github.com/multikernel/kernelscript.git
   cd kernelscript
   opam init
   opam install . --deps-only --with-test
   eval $(opam env) && dune build && dune install
   ```

3. **Create your first project:**
   ```bash
   kernelscript init xdp hello_world
   cd hello_world/
   ```

4. **Edit the generated code:**
   ```bash
   # Edit hello_world.ks with your logic
   vim hello_world.ks
   ```

5. **Compile and run:**
   ```bash
   kernelscript compile hello_world/hello_world.ks
   cd hello_world/
   make
   sudo ./hello_world
   ```

## Examples

The `examples/` directory contains comprehensive examples:

- `packet_filter.ks` - Basic XDP packet filtering
- `multi_programs.ks` - Multiple coordinated programs
- `maps_demo.ks` - All map types and operations
- `functions.ks` - Function definitions and calls
- `types_demo.ks` - Type system features
- `error_handling_demo.ks` - Error handling patterns

## License

Copyright 2025 Multikernel Technologies, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

## Contributing

By contributing to this project, you agree that your contributions will be licensed under the Apache License 2.0.


================================================
FILE: SPEC.md
================================================
# KernelScript Language Format Specification v1.0

## 1. Design Philosophy and Scope

### 1.1 Core Principles
- **Simplicity over generality**: Avoid complex template systems that burden the compiler
- **Explicit over implicit**: Clear, readable syntax with minimal magic
- **Safety by construction**: Type system prevents common eBPF errors
- **Seamless kernel-userspace integration**: First-class support for bidirectional communication
- **Explicit program lifecycle control**: Programs are first-class values with explicit loading and attachment phases
- **Intuitive scoping model**: Clear separation between kernel and userspace code with shared resources

### 1.2 Simplified Type System
Instead of complex templates, KernelScript uses **simple type aliases** and **fixed-size types**:

```kernelscript
// Simple type aliases for common patterns
type IpAddress = u32
type Port = u16
type PacketBuffer = u8[1500]
type SmallBuffer = u8[256]

// Fixed-size arrays (no complex bounds)
u8[64]                 // 64-byte buffer
u32[16]                // 16 u32 values

// Simple map declarations
var counters : array<u32, u64>(256)
var flows : hash<IpAddress, PacketStats>(1024)

// No complex template metaprogramming - just practical, concrete types
```

### 1.3 Intuitive Scoping Model
KernelScript uses a simple and clear scoping model that eliminates ambiguity:

- **`@helper` functions**: Kernel-shared functions - accessible by all eBPF programs, compile to eBPF bytecode
- **Attributed functions** (e.g., `@xdp`, `@tc`, `@tracepoint`): eBPF program entry points - compile to eBPF bytecode
- **Regular functions**: User space - functions and data structures compile to native executable
- **Maps and global configs**: Shared resources accessible from both kernel and user space
- **No wrapper syntax**: Direct, flat structure without unnecessary nesting

```kernelscript
// Shared resources (accessible by both kernel and userspace)
config system { debug: bool = false }
var counters : array<u32, u64>(256)

// Kernel-shared functions (accessible by all eBPF programs)
@helper
fn update_counters(index: u32) {
    counters[index] += 1
}

@helper
fn should_log() -> bool {
    return system.debug
}

// eBPF program functions with attributes
@xdp
fn monitor(ctx: *xdp_md) -> xdp_action {
    update_counters(0)  // Call kernel-shared function
    
    if (should_log()) {  // Call another kernel-shared function
        print("Processing packet")
    }
    
    return XDP_PASS
}

@tc("ingress")
fn analyzer(ctx: *__sk_buff) -> i32 {
    update_counters(1)  // Same kernel-shared function
    return 0  // TC_ACT_OK
}

// User space (regular functions)
struct Args { interface: str(16) }
fn main(args: Args) -> i32 {
    // Cannot call update_counters() here - it's kernel-only
    
    var monitor_handle = load(monitor)
    var analyzer_handle = load(analyzer)
    
    attach(monitor_handle, args.interface, 0)
    attach(analyzer_handle, args.interface, 1)
    
    return 0
}
```

### 1.4 Unified Import and Include System

KernelScript supports both importing modules and including headers using distinct keywords for different use cases:

```kernelscript
// Import KernelScript modules (.ks files)
import utils from "./common/utils.ks"           // Functions, types, maps, configs
import packet_helpers from "../net/helpers.ks"  // Shared across eBPF and userspace

// Import Python modules (.py files) - userspace only
import ml_analysis from "./ml/threat_analysis.py"
import data_processor from "./analytics/stats.py"

// Usage is identical regardless of source language
@xdp
fn intelligent_filter(ctx: *xdp_md) -> xdp_action {
    // Use KernelScript imported functions
    var protocol = utils.extract_protocol(ctx)
    
    // Use Python imported functions (FFI bridge in userspace)
    var packet_data = ctx->data
    var packet_len = ctx->data_end - ctx->data
    var threat_score = ml_analysis.compute_threat_score(packet_data, packet_len)
    
    if (threat_score > 0.8) {
        return XDP_DROP
    }
    return XDP_PASS
}

fn main() -> i32 {
    // Both KernelScript and Python functions work seamlessly in userspace
    var is_valid = utils.validate_config()
    var model_stats = ml_analysis.get_model_statistics()
    
    print("Config valid: %d, Model accuracy: %f", is_valid, model_stats.accuracy)
    
    var prog = load(intelligent_filter)
    attach(prog, "eth0", 0)
    return 0
}
```

#### Include System for Headers (.kh files)

```kernelscript
// Include KernelScript headers (.kh files) - declarations only, flattened into global namespace
include "generated/common_kfuncs.kh"           // extern kfunc declarations
include "generated/xdp_kfuncs.kh"              // XDP-specific kfuncs  
include "types/networking.kh"                  // Type definitions

@xdp
fn packet_processor(ctx: *xdp_md) -> xdp_action {
    // Direct access to included extern kfuncs (no namespace)
    var timestamp = bpf_ktime_get_ns()          // From common_kfuncs.kh
    bpf_xdp_adjust_head(ctx, -14)               // From xdp_kfuncs.kh
    
    return XDP_PASS
}
```

**Key Distinctions:**
- **`import name from "file"`**: Creates namespace, works with full implementations (.ks/.py files)
- **`include "file"`**: Flattens into global namespace, works with headers only (.kh files)
- **Use cases**: Import for libraries/modules, include for extern declarations and types
- **Validation**: Include validates that .kh files contain only declarations (no function bodies)

## 2. Lexical Structure

### 2.1 Keywords
```
fn          var         const       config      local       for
pin         type        struct      enum        if          else
while       loop        break       continue    return      import
pub         priv        impl        true        false       null
try         catch       throw       defer       delete      match
extern      include
```

**Note**: The `pin` keyword is used for both maps and global variables to enable filesystem persistence.

### 2.2 Identifiers
```ebnf
identifier = letter { letter | digit | "_" } 
letter = "a"..."z" | "A"..."Z" 
digit = "0"..."9" 
```

### 2.3 Literals
```ebnf
integer_literal = decimal_literal | hex_literal | octal_literal | binary_literal 
decimal_literal = digit { digit } 
hex_literal = "0x" hex_digit { hex_digit } 
octal_literal = "0o" octal_digit { octal_digit } 
binary_literal = "0b" binary_digit { binary_digit } 

string_literal = '"' { string_char } '"' 
char_literal = "'" char "'" 

boolean_literal = "true" | "false" 
```

## 3. Program Structure

### 3.1 eBPF Program Function Declaration
```ebnf
ebpf_program = attribute_list "fn" identifier "(" parameter_list ")" "->" return_type "{" statement_list "}"

attribute_list = attribute { attribute }
attribute = "@" attribute_name [ "(" attribute_args ")" ]
attribute_name = "xdp" | "tc" | "probe" | "tracepoint" |
                 "struct_ops" | "kfunc" | "private" | "helper" | "test"
attribute_args = string_literal | identifier

parameter_list = parameter { "," parameter }
parameter = identifier ":" type_annotation
return_type = type_annotation
```

**Note:** eBPF programs are now simple attributed functions. All configuration is done through global named config blocks.

#### 3.1.1 Advanced Probe Functions with BTF Signature Extraction and Intelligent Probe Type Selection

KernelScript automatically extracts kernel function signatures from BTF (BPF Type Format) for probe functions and intelligently chooses between fprobe (function entrance) and kprobe (arbitrary address) based on the target specification.

```kernelscript
// Function entrance probe (uses fprobe)
@probe("sys_read")
fn function_entrance(fd: u32, buf: *u8, count: size_t) -> i32 {
    // Direct access to function parameters with correct types
    // Compiler automatically extracts signature from BTF:
    // long sys_read(unsigned int fd, char __user *buf, size_t count)
    // Uses fprobe for better performance at function entrance
    
    print("Reading %d bytes from fd %d", count, fd)
    return 0
}

// Arbitrary address probe (uses kprobe)  
@probe("vfs_read+109")
fn arbitrary_address() -> i32 {
    // Probes specific instruction offset within vfs_read
    // Uses kprobe for arbitrary address probing
    // No direct parameters available at arbitrary addresses
    
    print("Probing vfs_read at offset +109")
    return 0
}
```

**Key Benefits:**
- **Intelligent Probe Selection**: Automatically chooses fprobe for function entrance (better performance) or kprobe for arbitrary addresses
- **Type Safety**: Function entrance probes have correct types extracted from kernel BTF information

**Return Type Constraint:**
- **All probe functions must return `i32`** due to eBPF's `BPF_PROG()` macro constraint
- The return value controls execution flow: `0` = continue normally, non-zero = may alter behavior
- This applies regardless of the target kernel function's actual return type (which may be `void`, pointers, etc.)
- BTF function signature extraction automatically converts all return types to `i32` for consistency

#### 3.1.2 Traffic Control (TC) Programs with Direction Support

TC programs must specify traffic direction for proper kernel attachment point selection.

```kernelscript
// Ingress traffic control (packets entering the interface)
@tc("ingress")
fn ingress_filter(ctx: *__sk_buff) -> i32 {
    var packet_size = ctx->len
    
    // Drop oversized packets at ingress
    if (packet_size > 1500) {
        return TC_ACT_SHOT  // Drop packet
    }
    
    return TC_ACT_OK  // Allow packet
}

// Egress traffic control (packets leaving the interface)  
@tc("egress")
fn egress_shaper(ctx: *__sk_buff) -> i32 {
    var protocol = ctx->protocol
    
    // Shape traffic based on protocol at egress
    if (protocol == ETH_P_IP) {
        // Apply rate limiting logic
        return TC_ACT_PIPE  // Continue processing
    }
    
    return TC_ACT_OK  // Allow packet
}
```

**TC Direction Specification:**
- **@tc("ingress")**: Attaches to ingress hook (packets entering interface)
- **@tc("egress")**: Attaches to egress hook (packets leaving interface)
- Direction parameter is **required** - no default direction is assumed

**Key Benefits:**
- **Explicit Direction Control**: Clear specification of traffic direction for precise attachment
- **Type Safety**: All TC programs use standard __sk_buff context with compile-time validation
- **Kernel Integration**: Direct mapping to kernel TC ingress/egress hooks

**Probe Type Selection:**
- `@probe("function_name")` → Uses **fprobe** for function entrance with direct parameter access
- `@probe("function_name+offset")` → Uses **kprobe** for arbitrary address probing

**BTF Signature Mapping for Function Entrance:**
```kernelscript
// Kernel function: long sys_openat(int dfd, const char __user *filename, int flags, umode_t mode)
@probe("sys_openat")
fn trace_openat(dfd: i32, filename: *u8, flags: i32, mode: u16) -> i32 {
    // Direct parameter access with fprobe (no PT_REGS needed)
    print("Opening file with flags %d", flags)
    return 0
}

// For arbitrary address probing:
@probe("sys_write+50")  
fn trace_write_offset() -> i32 {
    // Uses kprobe for arbitrary offset - no direct parameters available
    print("Probing sys_write at offset +50")
    return 0
}

    }
    return 0
}
```

**Compiler Implementation:**
- Automatically queries BTF information for the target kernel function
- Generates parameter mappings to `PT_REGS_PARM*` macros
- Validates parameter count (maximum 6 on x86_64)
- Provides meaningful error messages for unknown functions

#### 3.1.2 Tracepoint Functions with BTF Event Structure Extraction

KernelScript automatically extracts tracepoint event structures from BTF (BPF Type Format) for tracepoint functions, providing type-safe access to tracepoint event data through the appropriate `trace_event_raw_*` structures.

```kernelscript
@tracepoint("sched/sched_switch")
fn sched_switch_handler(ctx: *trace_event_raw_sched_switch) -> i32 {
    // Direct access to tracepoint event fields with correct types
    // Compiler automatically extracts structure from BTF:
    // struct trace_event_raw_sched_switch {
    //     struct trace_entry ent;
    //     char prev_comm[16];
    //     pid_t prev_pid;
    //     int prev_prio;
    //     long prev_state;
    //     char next_comm[16];
    //     pid_t next_pid;
    //     int next_prio;
    //     ...
    // }
    
    print("Task switch: %s[%d] -> %s[%d]", 
          ctx.prev_comm, ctx.prev_pid, 
          ctx.next_comm, ctx.next_pid)
    return 0
}

@tracepoint("syscalls/sys_enter_read")
fn sys_enter_read_handler(ctx: *trace_event_raw_sys_enter) -> i32 {
    // Syscall tracepoints use generic sys_enter structure
    // struct trace_event_raw_sys_enter {
    //     struct trace_entry ent;
    //     long id;
    //     unsigned long args[6];
    // }
    
    var fd = ctx.args[0]
    var count = ctx.args[2]
    print("sys_read: fd=%d, count=%d", fd, count)
    return 0
}

@tracepoint("net/netif_rx") 
fn netif_rx_handler(ctx: *trace_event_raw_netif_rx) -> i32 {
    // Network tracepoint with packet information
    print("Network packet received")
    return 0
}
```

**Key Benefits:**
- **Event Structure Access**: Direct access to tracepoint event fields with correct types
- **Category/Event Organization**: Clear separation using `category/event` format
- **BTF Integration**: Automatic extraction of `trace_event_raw_*` structures from kernel BTF
- **Compile-Time Safety**: Type checking for tracepoint context structures
- **Flexible Event Types**: Support for scheduler, syscall, network, and custom tracepoints

**BTF Structure Mapping:**
```kernelscript
// Scheduler tracepoints: trace_event_raw_<event_name>
@tracepoint("sched/sched_wakeup")
fn wakeup_handler(ctx: *trace_event_raw_sched_wakeup) -> i32 {
    // Access scheduler-specific fields
    print("Waking up PID %d", ctx.pid)
    return 0
}

// Syscall enter tracepoints: trace_event_raw_sys_enter (generic)
@tracepoint("syscalls/sys_enter_open") 
fn open_handler(ctx: *trace_event_raw_sys_enter) -> i32 {
    // Access syscall arguments through args array
    var filename_ptr = ctx.args[0]
    var flags = ctx.args[1]
    print("Opening file with flags %d", flags)
    return 0
}

// Syscall exit tracepoints: trace_event_raw_sys_exit (generic)
@tracepoint("syscalls/sys_exit_read")
fn read_exit_handler(ctx: *trace_event_raw_sys_exit) -> i32 {
    // Access return value
    print("sys_read returned %d", ctx.ret)
    return 0
}

// Custom subsystem tracepoints: trace_event_raw_<event_name>
@tracepoint("block/block_rq_complete")
fn block_complete_handler(ctx: *trace_event_raw_block_rq_complete) -> i32 {
    // Access block layer specific fields
    return 0
}
```

**Compiler Implementation:**
- Automatically determines BTF structure name based on category/event:
  - `syscalls/sys_enter_*` → `trace_event_raw_sys_enter` 
  - `syscalls/sys_exit_*` → `trace_event_raw_sys_exit`
  - `<category>/<event>` → `trace_event_raw_<event>`
- Extracts tracepoint structure definitions from kernel BTF information
- Generates appropriate `SEC("tracepoint")` section for eBPF programs
- Validates tracepoint context parameter types at compile time
- Provides meaningful error messages for unknown tracepoints

**Project Initialization:**
```bash
# Initialize project with specific tracepoint
kernelscript init tracepoint/sched/sched_switch my_scheduler_tracer

# Initialize project with syscall tracepoint  
kernelscript init tracepoint/syscalls/sys_enter_read my_syscall_tracer

# The init command automatically extracts BTF structures and generates
# appropriate KernelScript templates with correct context types
```

### 3.2 Named Configuration Blocks
```kernelscript
// Named configuration blocks - globally accessible
config network {
    enable_logging: bool = true,
    max_packet_size: u32 = 1500,
    blocked_ports: u16[5] = [22, 23, 135, 445, 3389],
    rate_limit: u64 = 1000000,
}

config security {
    threat_threshold: u32 = 100,
    current_threat_level: u32 = 0,
    enable_strict_mode: bool = false,
}

@xdp
fn network_monitor(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    
    // Use named configuration values
    if (packet.size > network.max_packet_size) {
        if (network.enable_logging) {
            print("Packet too large: %d", packet.size)
        }
        return XDP_DROP
    }
    
    // Check blocked ports from network config
    if (packet.is_tcp()) {
        var tcp = packet.tcp_header()
        for (i in 0..5) {
            if (tcp.dst_port == network.blocked_ports[i]) {
                return XDP_DROP
            }
        }
    }
    
    // Use security config for additional checks
    if (security.enable_strict_mode && security.current_threat_level > security.threat_threshold) {
        return XDP_DROP
    }
    
    return XDP_PASS
}
```

### 3.3 Global Variables

KernelScript supports global variable declarations at the top level that are accessible from both kernel and userspace contexts. Global variables provide a simple way to declare shared state without the complexity of full map declarations.

#### 3.3.1 Global Variable Declaration Syntax

Global variables support three forms of declaration, with optional `pin` keyword for persistence:

```kernelscript
// Form 1: Full declaration with type and initial value
var global_counter: u32 = 0
var global_string: str(256) = "default_value"
var global_flag: bool = true

// Form 2: Type-only declaration (uninitialized)
var uninitialized_counter: u32
var uninitialized_buffer: str(128)

// Form 3: Value-only declaration (type inferred)
var inferred_int = 42           // Type: u32 (default for integer literals)
var inferred_string = "hello"   // Type: str(6) (inferred from string length)
var inferred_bool = false       // Type: bool
var inferred_char = 'a'         // Type: char

// Pinned global variables - persisted to filesystem
pin var persistent_counter: u64 = 0
pin var persistent_config: str(64) = "default_config"
pin var persistent_flag: bool = false
pin var persistent_buffer: [u8; 256] = [0; 256]
```

#### 3.3.2 Type Inference Rules

When no explicit type is provided, KernelScript infers the type based on the initial value:

| Literal Type | Inferred Type | Example |
|-------------|---------------|---------|
| `IntLit` | `u32` | `var x = 42` → `u32` |
| `StringLit` | `str(N)` | `var s = "hello"` → `str(6)` |
| `BoolLit` | `bool` | `var b = true` → `bool` |
| `CharLit` | `char` | `var c = 'a'` → `char` |
| `NullLit` | `*u8` | `var p = null` → `*u8` |
| `ArrayLit` | `[u32; 1]` | `var a = [1, 2, 3]` → `[u32; 3]` |

#### 3.3.3 Global Variable Usage

Global variables are accessible from both kernel and userspace contexts:

```kernelscript
// Global variables - accessible from both contexts
var packet_count: u64 = 0
var enable_logging: bool = true
var max_packet_size: u32 = 1500

// eBPF program using global variables
@xdp
fn packet_monitor(ctx: *xdp_md) -> xdp_action {
    packet_count += 1  // Access global variable
    
    var packet = ctx.packet()
    if (packet.size > max_packet_size) {
        if (enable_logging) {
            print("Packet too large: %d", packet.size)
        }
        return XDP_DROP
    }
    
    return XDP_PASS
}

// Userspace program using global variables
struct Args {
    interface: str(16),
    debug: bool,
}

fn main(args: Args) -> i32 {
    // Configure global variables based on command line
    enable_logging = args.debug
    
    var prog_handle = load(packet_monitor)
    attach(prog_handle, args.interface, 0)
    
    // Monitor global state
    while (true) {
        print("Total packets processed: ", packet_count)
        sleep(1000)
    }
    
    return 0
}
```

#### 3.3.4 Global Variable Scoping and Pinning

KernelScript provides explicit control over global variable visibility between kernel and userspace, with optional persistence:

```kernelscript
// Shared variables (default) - accessible from both kernel and userspace
var packet_count: u64 = 0
var enable_logging: bool = true
var shared_buffer: str(256) = "default"

// Pinned shared variables - persisted to filesystem and shared
pin var persistent_packet_count: u64 = 0
pin var persistent_config: str(128) = "default_config"
pin var persistent_state: bool = false

// Local variables - kernel-only, not exposed to userspace
local var crypto_nonce: u64 = 0x123456789ABCDEF0
local var internal_debug_flags: u32 = 0
local var temp_calculation_buffer: [u8; 1024] = [0; 1024]

// ❌ COMPILATION ERROR: Cannot pin local variables
// pin local var invalid_pinned_local: u32 = 0

// eBPF program using shared, pinned, and local variables
@xdp
fn secure_packet_filter(ctx: *xdp_md) -> xdp_action {
    packet_count += 1                    // Shared: accessible via skeleton
    persistent_packet_count += 1         // Pinned: persisted and accessible
    crypto_nonce += 1                    // Local: kernel-only, not in skeleton
    
    if (enable_logging) {                // Shared: configurable from userspace
        internal_debug_flags |= 0x1      // Local: internal state only
        print("Processing packet")
    }
    
    // Use pinned configuration
    if (persistent_state) {
        print("Persistent mode enabled")
    }
    
    return XDP_PASS
}

// Userspace program accessing shared and pinned variables
fn main() -> i32 {
    // Can access shared variables via skeleton
    enable_logging = true
    
    // Can access pinned variables (persisted across program restarts)
    persistent_state = true
    
    while (true) {
        print("Packets processed: ", packet_count)             // Via skeleton
        print("Total packets: ", persistent_packet_count)      // Via pinned map
        print("Config: ", persistent_config)                   // Via pinned map
        // Cannot access crypto_nonce or internal_debug_flags
        sleep(1000)
    }
    
    return 0
}
```

**Scoping Rules:**
- **Shared variables** (`var`): Accessible from both kernel and userspace via libbpf skeleton
- **Pinned shared variables** (`pin var`): Accessible from both kernel and userspace, persisted to filesystem
- **Local variables** (`local var`): Kernel-only, hidden from userspace, not included in skeleton generation

**Pinning Rules:**
- Only shared variables can be pinned (not `local var`)
- Pinned variables are persisted to `/sys/fs/bpf/<PROJECT_NAME>/globals/pinned_globals`
- Compilation error if attempting to pin local variables: `pin local var` is invalid

**Security Benefits:**
- Sensitive data like cryptographic nonces remain kernel-only
- Internal debugging state isn't exposed to userspace
- Clear separation between public API and internal implementation
- Pinned variables provide persistent state across program restarts

#### 3.3.5 Pinned Global Variables Implementation

Since eBPF doesn't support pinning global variables directly, the compiler implements pinned global variables using a transparent map-based approach:

**Compiler Implementation Strategy:**
1. **Collect all pinned global variables** in order of declaration
2. **Generate a struct** containing all pinned variables with their original types
3. **Create a single-entry map** to store and pin this struct
4. **Generate access wrappers** to maintain the original variable access syntax

```kernelscript
// User writes this:
pin var packet_count: u64 = 0
pin var config_string: str(64) = "default"
pin var enable_feature: bool = false

// Compiler generates (conceptually):
struct PinnedGlobals {
    packet_count: u64,
    config_string: str(64),
    enable_feature: bool,
}

// Single-entry pinned map
@flags(BPF_F_NO_PREALLOC)
pin var __pinned_globals : array<u32, PinnedGlobals>(1)

// Access wrappers (transparent to user):
// packet_count access becomes: __pinned_globals[0].packet_count
// config_string access becomes: __pinned_globals[0].config_string
// enable_feature access becomes: __pinned_globals[0].enable_feature
```

**Filesystem Location:**
- Pinned globals map is stored at: `/sys/fs/bpf/<PROJECT_NAME>/globals/pinned_globals`
- Multiple programs can share the same pinned globals if they have the same project name

**Initialization Behavior:**
- On first program load, the map is created and initialized with default values
- On subsequent loads, existing values are preserved from the filesystem
- Default values are only used when no pinned map exists

**Example Usage:**
```kernelscript
// Declaration - user syntax remains clean
pin var session_counter: u64 = 0
pin var last_interface: str(16) = "eth0"
pin var debug_mode: bool = false

@xdp
fn persistent_monitor(ctx: *xdp_md) -> xdp_action {
    // Compiler transparently converts to map access
    session_counter += 1  // Becomes: __pinned_globals[0].session_counter += 1
    
    if (debug_mode) {     // Becomes: if (__pinned_globals[0].debug_mode) {
        print("Session: ", session_counter, " Interface: ", last_interface)
    }
    
    return XDP_PASS
}

// Userspace access - same transparent conversion
fn main() -> i32 {
    // Values persist across program restarts
    print("Previous session count: ", session_counter)
    
    // Configure for this session
    last_interface = "eth1"
    debug_mode = true
    
    var prog_handle = load(persistent_monitor)
    attach(prog_handle, last_interface, 0)
    
    return 0
}
```

#### 3.3.6 Global Variables vs Maps and Configs

| Feature | Global Variables | Pinned Global Variables | Maps | Configs |
|---------|------------------|-------------------------|------|---------|
| **Syntax** | `var name: type = value` | `pin var name: type = value` | `[pin] [@flags(...)] var name : Type<K,V>(size)` | `config name { field: type = value }` |
| **Use Case** | Simple shared state | Persistent simple state | Complex data structures | Structured configuration |
| **Access** | Direct variable access | Direct variable access | Key-value lookup | Dotted field access |
| **Performance** | Fastest | Fast (single map lookup) | Medium | Fastest |
| **Flexibility** | Limited | Limited | High | Medium |
| **Scoping** | Shared or local | Always shared | Always shared | Always shared |
| **Persistence** | No | Yes (filesystem) | Optional (if pinned) | No |

### 3.4 Kernel-Userspace Scoping Model

KernelScript uses a simple and intuitive scoping model:
- **Attributed functions** (e.g., `@xdp`, `@tc`, `@tracepoint`): Kernel space (eBPF) - compiles to eBPF bytecode
- **`@kfunc` functions**: Kernel modules (full privileges) - exposed to eBPF programs via BTF
- **`@private` functions**: Kernel modules (full privileges) - internal helpers for kfuncs
- **Regular functions**: User space - compiles to native executable
- **Maps, global configs, and global variables**: Shared between both kernel and user space

```kernelscript
// Shared configuration and maps (accessible by both kernel and userspace)
config monitoring {
    enable_stats: bool = true,
    sample_rate: u32 = 100,
    packets_processed: u64 = 0,
}

var global_stats : hash<u32, PacketStats>(1024)

// Userspace types
struct PacketStats {
    packets: u64,
    bytes: u64,
    drops: u64,
}

struct Args {
    interface_id: u32,
    enable_verbose: u32,
}

// Kernel-shared functions (accessible by all eBPF programs)
@helper
fn update_stats(ctx: *xdp_md) {
    var key = ctx.hash() % 1024
    global_stats[key].packets += 1
}

// eBPF program functions with attributes
@xdp
fn packet_analyzer(ctx: *xdp_md) -> xdp_action {
    if (monitoring.enable_stats) {
        // Process packet and update statistics
        monitoring.packets_processed += 1
        update_stats(ctx)
    }
    return XDP_PASS
}

@tc("ingress")
fn flow_tracker(ctx: *__sk_buff) -> i32 {
    // Track flow information using shared config
    if (monitoring.enable_stats && (ctx.hash() % monitoring.sample_rate == 0)) {
        // Sample this flow
        var key = ctx.hash() % 1024
        global_stats[key].bytes += ctx.packet_size()
    }
    return 0  // TC_ACT_OK
}

// Userspace coordination (regular functions)
fn main(args: Args) -> i32 {
    // Command line arguments automatically parsed
    // Usage: program --interface-id=1 --enable-verbose=1
    
    var interface_index = args.interface_id
    
    // Load and coordinate multiple programs
    var analyzer_handle = load(packet_analyzer)
    var tracker_handle = load(flow_tracker)
    
    attach(analyzer_handle, interface_index, 0)
    attach(tracker_handle, interface_index, 1)
    
    if (args.enable_verbose == 1) {
        print("Multi-program system started on interface: ", interface_index)
    }
    
    while (true) {
        var stats = get_combined_stats()
        print("Total packets: ", stats.packets)
        print("Total bytes: ", stats.bytes)
        sleep(1000)
    }
    
    return 0
}

// Userspace helper functions
fn get_combined_stats() -> PacketStats {
    var total = PacketStats { packets: 0, bytes: 0, drops: 0 }
    for (i in 0..1024) {
        total.packets += global_stats[i].packets
        total.bytes += global_stats[i].bytes
        total.drops += global_stats[i].drops
    }
    return total
}

fn on_packet_event(event: PacketEvent) {
    // Handle events from eBPF programs
}
```

### 3.5 Explicit Program Lifecycle Management

KernelScript supports explicit control over eBPF program loading and attachment through function references and built-in lifecycle functions. This enables advanced use cases like parameter configuration between loading and attachment phases.

#### 3.5.1 Program Function References and Safety

eBPF program functions are first-class values that can be referenced by name and passed to lifecycle functions. The interface enforces safety by requiring programs to be loaded before attachment:

```kernelscript
@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    return XDP_PASS
}

@tc("ingress")
fn flow_monitor(ctx: *__sk_buff) -> i32 {
    return 0  // TC_ACT_OK
}

// Userspace program coordination
fn main() -> i32 {
    // Program functions can be referenced by name
    var xdp_prog = packet_filter  // Type: FunctionRef
    var tc_prog = flow_monitor    // Type: FunctionRef
    
    // Explicit loading and attachment
    var prog_handle = load(xdp_prog)
    var result = attach(prog_handle, "eth0", 0)
    
    return 0
}
```

#### 3.5.2 Lifecycle Functions

**`load(function_ref: FunctionRef) -> ProgramHandle`**
- Loads the specified eBPF program function into the kernel
- Returns a program handle that abstracts the underlying implementation
- Must be called before attachment
- Enables configuration of program parameters before attachment

**`attach(handle: ProgramHandle, target: string, flags: u32) -> u32`**
- Attaches the loaded program to the specified target using its handle
- First parameter must be a ProgramHandle returned from load()
- Target and flags interpretation depends on program type:
  - **XDP**: target = interface name ("eth0"), flags = XDP attachment flags
  - **TC**: target = interface name ("eth0"), direction determined from @tc("ingress"/"egress") attribute
  - **Kprobe**: target = function name ("sys_read"), flags = unused (0)
  - **Cgroup**: target = cgroup path ("/sys/fs/cgroup/test"), flags = unused (0)
- Returns 0 on success, negative error code on failure

**`detach(handle: ProgramHandle) -> void`**
- Detaches the program from its current attachment point using its handle
- Automatically determines the correct detachment method based on program type:
  - **XDP**: Uses `bpf_xdp_detach()` with stored interface and flags
  - **TC**: Uses `bpf_tc_detach()` with stored interface and direction
  - **Kprobe/Tracepoint**: Destroys the stored `bpf_link` handle
- No return value (void) - logs errors to stderr if detachment fails
- Safe to call multiple times on the same handle (no-op if already detached)
- Automatically cleans up internal attachment tracking

**Safety Benefits:**
- **Compile-time enforcement**: Cannot call `attach()` without first calling `load()` - the type system prevents this
- **Implementation abstraction**: Users work with `ProgramHandle` instead of raw file descriptors
- **Resource safety**: Program handles abstract away the underlying resource management
- **Automatic cleanup**: `detach()` handles all program types uniformly and cleans up tracking data
- **Idempotent operations**: Safe to call `detach()` multiple times without side effects

#### 3.5.3 Lifecycle Best Practices

**Proper Cleanup Patterns:**
```kernelscript
fn main() -> i32 {
    var prog1 = load(filter)
    var prog2 = load(monitor)
    
    // Attach programs
    var result1 = attach(prog1, "eth0", 0)
    var result2 = attach(prog2, "eth0", 1)
    
    // Error handling with partial cleanup
    if (result1 != 0 || result2 != 0) {
        // Clean up any successful attachments before returning
        if (result1 == 0) detach(prog1)
        if (result2 == 0) detach(prog2)
        return 1
    }
    
    // Normal operation...
    print("Programs running...")
    
    // Proper shutdown: detach in reverse order
    detach(prog2)  // Last attached, first detached
    detach(prog1)
    
    return 0
}
```

**Multi-Program Detachment Order:**
- Always detach programs in **reverse order** of attachment
- This ensures dependencies are cleaned up properly
- Example: if `filter` depends on `monitor`, detach `monitor` first

**Error Recovery:**
- Use conditional detachment for partial failure scenarios
- Safe to call `detach()` multiple times on the same handle
- Always clean up successful attachments before returning error codes

#### 3.5.4 Advanced Usage Patterns

**Configuration Between Load and Attach:**
```kernelscript
config network {
    enable_filtering: bool = false,
    max_packet_size: u32 = 1500,
}

@xdp
fn adaptive_filter(ctx: *xdp_md) -> xdp_action {
    if (network.enable_filtering && ctx.packet_size() > network.max_packet_size) {
        return XDP_DROP
    }
    return XDP_PASS
}

// Userspace coordination and CLI handling
struct Args {
    interface: str(16),
    strict_mode: bool,
}

fn main(args: Args) -> i32 {
    // Load program first
    var prog_handle = load(adaptive_filter)
    
    // Configure parameters based on command line
    network.enable_filtering = args.strict_mode
    if (args.strict_mode) {
        network.max_packet_size = 1000  // Stricter limit
    }
    
    // Now attach with configured parameters
    var result = attach(prog_handle, args.interface, 0)
    
    if (result == 0) {
        print("Filter attached successfully")
        
        // Simulate running the program (in real usage, this might be an event loop)
        print("Filter is processing packets...")
        
        // Proper cleanup when shutting down
        detach(prog_handle)
        print("Filter detached successfully")
    } else {
        print("Failed to attach filter")
        return 1
    }
    
    return 0
}
```

**Multi-Program Coordination:**
```kernelscript
@xdp
fn ingress_monitor(ctx: *xdp_md) -> xdp_action { return XDP_PASS }

@tc("egress")
fn egress_monitor(ctx: *__sk_buff) -> i32 { return 0 }  // TC_ACT_OK

// Struct_ops example using impl block approach
struct tcp_congestion_ops {
    init: fn(sk: *TcpSock) -> void,
    cong_avoid: fn(sk: *TcpSock, ack: u32, acked: u32) -> void,
    cong_control: fn(sk: *TcpSock, ack: u32, flag: u32, bytes_acked: u32) -> void,
    set_state: fn(sk: *TcpSock, new_state: u32) -> void,
    name: string,
}

@struct_ops("tcp_congestion_ops")
impl my_bbr {
    fn init(sk: *TcpSock) -> void {
        // Initialize BBR state
    }
    
    fn cong_avoid(sk: *TcpSock, ack: u32, acked: u32) -> void {
        // BBR congestion avoidance
    }
    
    fn cong_control(sk: *TcpSock, ack: u32, flag: u32, bytes_acked: u32) -> void {
        // BBR control logic
    }
    
    fn set_state(sk: *TcpSock, new_state: u32) -> void {
        // State transitions
    }
}
```

### 3.6 Custom Kernel Functions (kfunc)

KernelScript allows users to define custom kernel functions using the `@kfunc` attribute. These functions execute in kernel space with full privileges and can be called from eBPF programs. The compiler automatically generates a kernel module containing the kfunc implementation and loads it transparently when needed.

#### 3.6.1 kfunc Declaration and Usage

kfunc functions are declared using the `@kfunc` attribute and are registered with the same name as the function:

```kernelscript
// Custom kernel function - registered as "advanced_packet_analysis"
@kfunc
fn advanced_packet_analysis(data: *u8, len: u32) -> u32 {
    // Full kernel privileges - can access any kernel API
    var skb = alloc_skb(len, GFP_KERNEL)
    if (skb == null) {
        return 0
    }
    
    // Complex analysis using kernel subsystems
    var result = deep_packet_inspection(data, len)
    kfree_skb(skb)
    
    return result
}

// Rate limiting kernel function
@kfunc
fn rate_limit_flow(flow_id: u64, current_time: u64) -> bool {
    // Access kernel data structures directly
    var bucket = get_rate_limit_bucket(flow_id)
    if (bucket == null) {
        bucket = create_rate_limit_bucket(flow_id)
    }
    
    // Token bucket algorithm with kernel timers
    update_token_bucket(bucket, current_time)
    return consume_token(bucket)
}

// Crypto verification kernel function
@kfunc
fn verify_packet_signature(packet: *u8, len: u32, signature: *u8) -> i32 {
    // Use kernel crypto subsystem
    var tfm = crypto_alloc_shash("sha256", 0, 0)
    if (IS_ERR(tfm)) {
        return -ENOMEM
    }
    
    var result = crypto_verify_signature(tfm, packet, len, signature)
    crypto_free_shash(tfm)
    
    return result
}

// eBPF program calling kfuncs
@xdp
fn secure_packet_filter(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    if (packet == null) {
        return XDP_PASS
    }
    
    // Call custom kernel function using function name
    var analysis_result = advanced_packet_analysis(packet.data, packet.len)
    if (analysis_result == 0) {
        return XDP_DROP
    }
    
    // Call rate limiter kfunc using function name
    var flow_id = compute_flow_id(packet)
    if (!rate_limit_flow(flow_id, bpf_ktime_get_ns())) {
        return XDP_DROP
    }
    
    // Verify packet signature for critical flows
    if (packet.is_critical_flow()) {
        var signature = extract_signature(packet)
        if (verify_packet_signature(packet.data, packet.len, signature) != 0) {
            return XDP_DROP
        }
    }
    
    return XDP_PASS
}
```

#### 3.6.2 Automatic Kernel Module Generation

The compiler automatically generates a kernel module for each kfunc:

**Generated Module Components:**
- **Function implementation**: Full kernel privileges, access to all kernel APIs
- **Registration code**: Registers kfunc with eBPF subsystem using BTF
- **Module metadata**: Proper module init/exit, dependencies, licensing
- **BTF information**: Type signatures for eBPF verifier integration

**Transparent Loading Process:**
1. User calls `load(secure_packet_filter)` in userspace
2. Compiler detects kfunc dependencies in the eBPF program
3. Kernel module containing kfuncs is loaded automatically
4. kfuncs are registered and made available to eBPF programs
5. eBPF program is loaded and can call the kfuncs
6. Module remains loaded as long as eBPF programs reference it

#### 3.6.3 kfunc Registration

```kernelscript
// kfunc registered as "packet_decrypt"
@kfunc
fn packet_decrypt(data: *u8, len: u32, key: *u8) -> i32 {
    // Registered as "packet_decrypt" in eBPF subsystem
    return kernel_crypto_decrypt(data, len, key)
}

// kfunc registered as "optimized_checksum_calculation"
@kfunc
fn optimized_checksum_calculation(data: *u8, len: u32) -> u32 {
    // Registered as "optimized_checksum_calculation" in eBPF subsystem
    // Can use hardware acceleration, SIMD, etc.
    return hardware_accelerated_checksum(data, len)
}

// eBPF program usage
@xdp
fn data_processor(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    
    // Call using function names
    var checksum = optimized_checksum_calculation(packet.data, packet.len)
    var decrypt_result = packet_decrypt(packet.data, packet.len, get_key())
    
    return XDP_PASS
}
```

#### 3.6.4 kfunc vs Other Function Types

| Aspect | `@kfunc` | `@helper` | `@xdp/@tc/etc` | Regular `fn` |
|--------|----------|-------------|----------------|--------------|
| **Execution Context** | Kernel space (full privileges) | eBPF sandbox | eBPF sandbox | Userspace |
| **Compilation Target** | Kernel module | eBPF bytecode | eBPF bytecode | Native executable |
| **Callable From** | eBPF programs only | eBPF programs | N/A (entry points) | Userspace only |
| **Kernel API Access** | Full access | eBPF helpers only | eBPF helpers only | System calls only |
| **Resource Limits** | None | eBPF verifier limits | eBPF verifier limits | Process limits |
| **Loading** | Automatic module load | Part of eBPF program | Part of eBPF program | Part of executable |

#### 3.6.5 Advanced kfunc Examples

```kernelscript
// Network policy enforcement with kernel integration
@kfunc
fn enforce_network_policy(src_ip: u32, dst_ip: u32, port: u16, protocol: u8) -> i32 {
    // Access kernel network namespaces
    var ns = get_current_net_ns()
    var policy = lookup_network_policy(ns, src_ip, dst_ip, port)
    
    if (policy == null) {
        return -ENOENT  // No policy found
    }
    
    // Check with netfilter subsystem
    return netfilter_check_policy(policy, protocol)
}

// File system integration
@kfunc
fn check_file_access(path: *char, mode: u32) -> i32 {
    // Interact with VFS and security modules
    var dentry = kern_path_lookup(path)
    if (IS_ERR(dentry)) {
        return PTR_ERR(dentry)
    }
    
    var result = security_inode_permission(dentry.d_inode, mode)
    path_put(&dentry)
    
    return result
}

// Memory management integration
@kfunc
fn allocate_secure_buffer(size: u32) -> *u8 {
    // Use kernel memory allocators with security considerations
    var buffer = kzalloc(size, GFP_KERNEL | __GFP_ZERO)
    if (buffer != null) {
        // Mark as secure/encrypted region
        mark_buffer_secure(buffer, size)
    }
    
    return buffer
}

// Usage in complex eBPF program
@lsm("socket_connect")
fn advanced_security_monitor(ctx: LsmContext) -> i32 {
    var sock = ctx.socket()
    var addr = ctx.address()
    
    // Use kfunc for complex policy checking
    var policy_result = enforce_network_policy(
        sock.src_ip, addr.dst_ip, addr.port, sock.protocol
    )
    
    if (policy_result != 0) {
        return -EPERM
    }
    
    // Use kfunc for file access checks if connection involves file transfer
    if (is_file_transfer_protocol(addr.port)) {
        var file_check = check_file_access("/tmp/allowed_transfers", R_OK)
        if (file_check != 0) {
            return -EACCES
        }
    }
    
    return 0
}
```

### 3.7 External Kernel Functions (extern)

KernelScript supports importing existing kernel functions using the `extern` keyword. These are kernel functions that already exist in the running kernel (discovered via BTF) and can be called directly from eBPF programs without requiring custom kernel modules.

#### 3.7.1 extern Declaration and Usage

External kernel functions are declared using the `extern` keyword and provide type-safe access to kernel-provided kfuncs:

```kernelscript
// Import existing kernel functions via extern declarations
extern bpf_ktime_get_ns() -> u64
extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32
extern bpf_get_current_pid_tgid() -> u64
extern bpf_get_current_comm(buf: *u8, buf_size: u32) -> i32

// eBPF programs can call extern functions directly
@xdp
fn packet_tracer(ctx: *xdp_md) -> xdp_action {
    // Get current timestamp using extern kfunc
    var timestamp = bpf_ktime_get_ns()
    
    // Get current process ID using extern kfunc
    var pid_tgid = bpf_get_current_pid_tgid()
    var pid = (pid_tgid >> 32) as u32
    
    // Get process name
    var comm: u8[16]
    bpf_get_current_comm(&comm[0], 16)
    
    // Print debug information
    bpf_trace_printk(&"packet from pid %d\n"[0], 18)
    
    return XDP_PASS
}
```

#### 3.7.2 extern vs @kfunc Comparison

| Aspect | `extern` | `@kfunc` |
|--------|----------|----------|
| **Definition** | Declaration of existing kernel function | User-defined kernel function |
| **Implementation** | Already exists in kernel | Implemented in generated kernel module |
| **BTF Registration** | Already registered | Registered by compiler |
| **Compilation** | Declaration only | Full implementation + module |
| **Usage** | Import existing kernel APIs | Create custom kernel functionality |
| **Performance** | Direct kernel function call | BTF-mediated call to module |

#### 3.7.3 extern Declaration Rules

- **Declaration only**: `extern` functions must not have function bodies
- **Type safety**: Parameter and return types must match kernel BTF signatures
- **eBPF only**: `extern` functions can only be called from eBPF programs, not userspace
- **Kernel availability**: Functions must exist in the target kernel version

```kernelscript
// ✅ Valid extern declaration
extern bpf_ktime_get_ns() -> u64

// ❌ Invalid - extern cannot have function body
extern invalid_function() -> u32 {
    return 42  // Error: extern functions cannot have bodies
}

// ❌ Invalid - extern functions cannot be called from userspace
fn userspace_function() -> u64 {
    return bpf_ktime_get_ns()  // Error: extern kfuncs only callable from eBPF
}
```

#### 3.7.4 BTF Integration and Discovery

The compiler can automatically discover available kernel functions from BTF:

```bash
# Automatic extern generation from kernel BTF
kernelscript init --kfuncs xdp my_xdp

# Generated extern_kfuncs.ks would contain:
# extern bpf_ktime_get_ns() -> u64
# extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32
# extern bpf_get_current_pid_tgid() -> u64
# ... (all available kernel kfuncs)
```

#### 3.7.5 Common extern kfunc Examples

```kernelscript
extern bpf_ktime_get_ns() -> u64
extern bpf_get_current_pid_tgid() -> u64
extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32

@tc("ingress")
fn network_monitor(ctx: *__sk_buff) -> i32 {
    var timestamp = bpf_ktime_get_ns()
    var pid_tgid = bpf_get_current_pid_tgid()

    // Process monitoring logic here
    bpf_trace_printk("Processing packet at %llu from PID %d\n", 40)
    return 0  // TC_ACT_OK
}
```

### 3.8 Helper Functions (@helper)

KernelScript supports kernel-shared helper functions using the `@helper` attribute. These functions compile to eBPF bytecode and are shared across all eBPF programs within the same compilation unit, providing a way to reuse common logic without duplicating code.

#### 3.8.1 @helper Declaration and Usage

Helper functions are declared using the `@helper` attribute and can be called from any eBPF program:

```kernelscript
// Shared helper functions - accessible by all eBPF programs
@helper
fn validate_packet_size(size: u32) -> bool {
    return size >= 64 && size <= 1500
}

@helper
fn calculate_hash(src_ip: u32, dst_ip: u32) -> u32 {
    return src_ip ^ dst_ip ^ (src_ip >> 16) ^ (dst_ip >> 16)
}

@helper
fn update_packet_stats(proto: u8, size: u32) {
    var key = proto as u32
    if (packet_stats.contains_key(key)) {
        packet_stats[key].count += 1
        packet_stats[key].total_bytes += size
    }
}

// eBPF programs can call helper functions
@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    
    // Call shared helper
    if (!validate_packet_size(packet.len)) {
        return XDP_DROP
    }
    
    // Call another helper
    update_packet_stats(packet.protocol, packet.len)
    
    return XDP_PASS
}

@tc("ingress")
fn traffic_shaper(ctx: *__sk_buff) -> i32 {
    var packet = ctx.packet()
    
    // Reuse the same helpers
    if (!validate_packet_size(packet.len)) {
        return 2  // TC_ACT_SHOT
    }
    
    var hash = calculate_hash(packet.src_ip, packet.dst_ip)
    update_packet_stats(packet.protocol, packet.len)
    
    return 0  // TC_ACT_OK
}
```

#### 3.8.2 @helper vs Other Function Types

| Aspect | `@helper` | `@kfunc` | `@xdp/@tc/etc` | Regular `fn` |
|--------|-----------|----------|----------------|--------------|
| **Execution Context** | eBPF sandbox | Kernel space (full privileges) | eBPF sandbox | Userspace |
| **Callable From** | eBPF programs | eBPF programs | Not callable | Userspace functions |
| **Compilation Target** | eBPF bytecode | Kernel module | eBPF bytecode | Native executable |
| **Shared Across Programs** | Yes | Yes | No | No |
| **Memory Access** | eBPF-restricted | Unrestricted kernel | eBPF-restricted | Userspace-restricted |

#### 3.8.3 Code Organization Benefits

Using `@helper` functions provides several benefits:

**1. Code Reuse**
```kernelscript
@helper
fn extract_tcp_info(ctx: *xdp_md) -> option TcpInfo {
    var packet = ctx.packet()
    if (packet.protocol != IPPROTO_TCP) {
        return null
    }
    
    return TcpInfo {
        src_port: packet.tcp_header().src_port,
        dst_port: packet.tcp_header().dst_port,
        flags: packet.tcp_header().flags
    }
}

@xdp
fn ddos_protection(ctx: *xdp_md) -> xdp_action {
    var tcp_info = extract_tcp_info(ctx)
    if (tcp_info != null && tcp_info.flags & TCP_SYN) {
        // SYN flood protection logic
        return rate_limit_syn(tcp_info.dst_port) ? XDP_PASS : XDP_DROP
    }
    return XDP_PASS
}

@tc("ingress")
fn connection_tracker(ctx: *__sk_buff) -> i32 {
    if (var tcp_info = extract_tcp_info(ctx)) {  // Reuse same helper
        track_connection(tcp_info.src_port, tcp_info.dst_port)
    }
    return 0  // TC_ACT_OK
}
```

### 3.9 Private Kernel Module Functions (@private)

KernelScript supports private helper functions within kernel modules using the `@private` attribute. These functions execute in kernel space but are internal to the module - they cannot be called by eBPF programs and are not registered via BTF. They serve as utility functions for `@kfunc` implementations.

#### 3.9.1 @private Declaration and Usage

Private functions are declared using the `@private` attribute and can only be called by other functions within the same kernel module:

```kernelscript
// Private helper functions - internal to kernel module
@private
fn validate_ip_address(addr: u32) -> bool {
    // IP validation logic with full kernel privileges
    return addr != 0 && addr != 0xFFFFFFFF && !is_reserved_ip(addr)
}

@private
fn calculate_flow_hash(src_ip: u32, dst_ip: u32, src_port: u16, dst_port: u16) -> u64 {
    // Complex hashing algorithm using kernel crypto
    var hash_state = crypto_alloc_shash("xxhash64", 0, 0)
    if (IS_ERR(hash_state)) {
        return simple_hash(src_ip ^ dst_ip ^ (src_port << 16) ^ dst_port)
    }
    
    var result = crypto_hash_flow(hash_state, src_ip, dst_ip, src_port, dst_port)
    crypto_free_shash(hash_state)
    return result
}

@private  
fn check_rate_limit_bucket(flow_id: u64, current_time: u64) -> bool {
    // Token bucket implementation with kernel timers
    var bucket = find_bucket(flow_id)
    if (bucket == null) {
        bucket = create_bucket(flow_id, current_time)
    }
    
    update_bucket_tokens(bucket, current_time)
    return bucket.tokens > 0
}

// Public kfunc API that uses private helpers
@kfunc
fn advanced_flow_filter(src_ip: u32, dst_ip: u32, src_port: u16, dst_port: u16) -> i32 {
    // Validate inputs using private helper
    if (!validate_ip_address(src_ip) || !validate_ip_address(dst_ip)) {
        return -EINVAL
    }
    
    // Calculate flow hash using private helper
    var flow_id = calculate_flow_hash(src_ip, dst_ip, src_port, dst_port)
    
    // Check rate limiting using private helper
    if (!check_rate_limit_bucket(flow_id, bpf_ktime_get_ns())) {
        return -EAGAIN  // Rate limited
    }
    
    return 0  // Allow flow
}

// Another kfunc using the same private helpers
@kfunc
fn flow_statistics(src_ip: u32, dst_ip: u32, src_port: u16, dst_port: u16) -> u64 {
    if (!validate_ip_address(src_ip) || !validate_ip_address(dst_ip)) {
        return 0
    }
    
    // Reuse the same flow hash calculation
    return calculate_flow_hash(src_ip, dst_ip, src_port, dst_port)
}

// eBPF program that can call kfuncs but NOT private functions
@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    if (packet == null) {
        return XDP_PASS
    }
    
    // Can call public kfunc
    var filter_result = advanced_flow_filter(
        packet.src_ip, packet.dst_ip, packet.src_port, packet.dst_port
    )
    
    if (filter_result != 0) {
        return XDP_DROP
    }
    
    // ERROR: Cannot call private functions directly
    // var is_valid = validate_ip_address(packet.src_ip)  // Compilation error!
    
    return XDP_PASS
}
```

#### 3.9.2 Function Visibility and Call Hierarchy

```kernelscript
// Example showing function call hierarchy
@private
fn low_level_crypto(data: *u8, len: u32) -> u32 {
    // Low-level cryptographic operations
    return kernel_crypto_hash(data, len)
}

@private
fn mid_level_validation(packet: *u8, len: u32) -> bool {
    // Can call other private functions in same module
    var hash = low_level_crypto(packet, len)
    return hash != 0 && validate_packet_structure(packet, len)
}

@kfunc
fn high_level_filter(packet: *u8, len: u32) -> i32 {
    // Public API that orchestrates private functions
    if (!mid_level_validation(packet, len)) {
        return -EINVAL
    }
    
    var hash = low_level_crypto(packet, len)
    return store_packet_hash(hash)
}

// eBPF usage
@tc("ingress")
fn traffic_analyzer(ctx: *__sk_buff) -> i32 {
    var packet = ctx.packet()
    
    // Can only call the public kfunc
    var result = high_level_filter(packet.data, packet.len)
    
    return result == 0 ? TC_ACT_OK : TC_ACT_SHOT
}
```

#### 3.9.3 @private vs @kfunc Comparison

| Aspect | `@private` | `@kfunc` |
|--------|-----------|----------|
| **Visibility** | Internal to kernel module | Exposed to eBPF programs |
| **BTF Registration** | Not registered | Registered with BTF |
| **Callable From** | Other functions in same module | eBPF programs |
| **Compilation Target** | Kernel module only | Kernel module + BTF |
| **Use Case** | Internal implementation details | Public API functions |
| **Performance** | Direct function call | BTF-mediated call |

#### 3.9.4 Code Organization Benefits

Using `@private` functions provides several architectural benefits:

**1. Modularity**
```kernelscript
// Clean separation of concerns
@private fn parse_headers(packet: *u8) -> PacketHeaders { }
@private fn validate_headers(headers: PacketHeaders) -> bool { }
@private fn apply_policy(headers: PacketHeaders) -> PolicyResult { }

@kfunc
fn packet_policy_check(packet: *u8, len: u32) -> i32 {
    var headers = parse_headers(packet)
    if (!validate_headers(headers)) {
        return -EINVAL
    }
    
    var policy = apply_policy(headers)
    return policy.action
}
```

**2. Security**
```kernelscript
// Hide sensitive implementation details
@private fn decrypt_with_master_key(data: *u8, len: u32) -> bool {
    // Sensitive key operations not exposed to eBPF
    return crypto_decrypt_master(data, len, get_master_key())
}

@kfunc  
fn secure_packet_process(encrypted_packet: *u8, len: u32) -> i32 {
    // Only expose safe, validated interface
    if (!decrypt_with_master_key(encrypted_packet, len)) {
        return -EACCES
    }
    return 0
}
```

**3. Performance**
```kernelscript
// Optimize hot paths with private helpers
@private fn fast_checksum(data: *u8, len: u32) -> u32 {
    // Optimized assembly or SIMD operations
    return simd_checksum(data, len)
}

@private fn cache_lookup(key: u64) -> *CacheEntry {
    // Efficient kernel cache operations
    return rcu_dereference(cache_table[hash(key)])
}

@kfunc
fn optimized_packet_check(packet: *u8, len: u32) -> bool {
    var checksum = fast_checksum(packet, len)
    var cache_entry = cache_lookup(checksum)
    
    return cache_entry != null && cache_entry.is_valid
}
```

### 3.10 Struct_ops and Kernel Module Function Pointers

KernelScript supports eBPF struct_ops through clean impl block syntax that allows implementing kernel interfaces using eBPF programs.

#### 3.10.1 eBPF Struct_ops with Impl Blocks

eBPF struct_ops allow implementing kernel interfaces using eBPF programs. KernelScript uses impl blocks for a clean, intuitive syntax:

```kernelscript
// Define the struct_ops type (extracted from BTF)
struct tcp_congestion_ops {
    ssthresh: fn(arg: *u8) -> u32,
    cong_avoid: fn(arg: *u8, arg: u32, arg: u32) -> void,
    set_state: fn(arg: *u8, arg: u8) -> void,
    cwnd_event: fn(arg: *u8, arg: u32) -> void,
    in_ack_event: fn(arg: *u8, arg: u32) -> void,
    pkts_acked: fn(arg: *u8, arg: *u8) -> void,
    min_tso_segs: fn(arg: *u8) -> u32,
    cong_control: fn(arg: *u8, arg: u32, arg: u32, arg: *u8) -> void,
    undo_cwnd: fn(arg: *u8) -> u32,
    sndbuf_expand: fn(arg: *u8) -> u32,
    get_info: fn(arg: *u8, arg: u32, arg: *u8, arg: *u8) -> u64,
    name: u8[16],
    owner: *u8,
}

// Initialize shared state before registration
var connection_state : hash<u32, BbrState>(1024)

// Implement struct_ops using impl block syntax
@struct_ops("tcp_congestion_ops")
impl my_bbr_congestion_control {
    // Function implementations are directly defined in the impl block
    // These automatically become eBPF functions with SEC("struct_ops/function_name")
    
    fn ssthresh(sk: *u8) -> u32 {
        return 16
    }

    fn cong_avoid(sk: *u8, ack: u32, acked: u32) -> void {
        // eBPF congestion avoidance logic
        var state = connection_state[sk.id]
        // ... BBR logic with eBPF constraints
    }

    fn set_state(sk: *u8, new_state: u8) -> void {
        // eBPF state transition logic
        // In a real implementation, this would handle TCP state transitions
    }

    fn cwnd_event(sk: *u8, ev: u32) -> void {
        // eBPF congestion window event handler
        // Handle events like slow start, recovery, etc.
    }

    fn cong_control(sk: *u8, ack: u32, flag: u32, bytes_acked: *u8) -> void {
        // eBPF control logic
        var state = connection_state[sk.id]
        // ... Advanced BBR control logic
    }

    // Optional function implementations can be omitted
    // These would be null in the generated struct_ops map
}

// Register the impl block directly
register(my_bbr_congestion_control)
```

#### 3.10.2 Simplified Struct_ops Example

```kernelscript
// Minimal struct_ops implementation
@struct_ops("tcp_congestion_ops")
impl minimal_congestion_control {
    fn ssthresh(sk: *u8) -> u32 {
        return 16
    }

    fn cong_avoid(sk: *u8, ack: u32, acked: u32) -> void {
        // Minimal TCP congestion avoidance implementation
    }

    fn set_state(sk: *u8, new_state: u8) -> void {
        // Minimal state change handler
    }

    fn cwnd_event(sk: *u8, ev: u32) -> void {
        // Minimal congestion window event handler
    }

    // Optional functions can be omitted - they will be null in the struct_ops map
}

// Userspace registration
fn main() -> i32 {
    // Register the impl block directly - much cleaner than struct initialization
    var result = register(minimal_congestion_control)
    
    if (result == 0) {
        print("Congestion control algorithm registered successfully")
    } else {
        print("Failed to register congestion control algorithm")
    }
    
    return result
}
```

#### 3.10.3 Sched-ext Scheduler Implementation

KernelScript supports sched-ext (extensible scheduler) through the `sched_ext_ops` struct_ops:

```kernelscript
// Simple FIFO scheduler using sched-ext
@struct_ops("sched_ext_ops")
impl simple_fifo_scheduler {
    
    // Select CPU for a waking task
    fn select_cpu(p: *u8, prev_cpu: i32, wake_flags: u64) -> i32 {
        // Use default CPU selection with direct dispatch if idle core found
        var direct: bool = false
        var cpu = scx_bpf_select_cpu_dfl(p, prev_cpu, wake_flags, &direct)
        
        if (direct) {
            // Insert directly into local DSQ, skipping enqueue
            scx_bpf_dsq_insert(p, SCX_DSQ_LOCAL, SCX_SLICE_DFL, 0)
        }
        
        return cpu
    }
    
    // Enqueue task into global FIFO queue
    fn enqueue(p: *u8, enq_flags: u64) -> void {
        // Simple FIFO: insert all tasks into global DSQ
        scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags)
    }
    
    // Dispatch tasks from global queue to local CPU
    fn dispatch(cpu: i32, prev: *u8) -> void {
        // Try to consume a task from the global DSQ
        if (!scx_bpf_consume(SCX_DSQ_GLOBAL)) {
            // No tasks available, CPU will go idle
        }
    }
    
    // Initialize scheduler
    fn init() -> i32 {
        return 0  // Success
    }
    
    // Scheduler configuration
    name: "simple_fifo",
    timeout_ms: 0,  // No timeout
    flags: 0,       // Default flags
}

// Register the scheduler
fn main() -> i32 {
    var result = register(simple_fifo_scheduler)
    return result
}
```

#### 3.10.4 Registration Function

The `register()` function is type-aware and generates the appropriate registration code:

```kernelscript
fn register(ops) -> i32
```

- For `@struct_ops` impl blocks: Generates libbpf registration using `bpf_map__attach_struct_ops()`
- Returns 0 on success, negative error code on failure
- The compiler determines the registration method based on the impl block attribute
- Impl blocks provide a cleaner syntax compared to struct initialization


## 4. Type System

### 4.1 Primitive Types
```kernelscript
// Integer types with explicit bit widths
u8, u16, u32, u64      // Unsigned integers
i8, i16, i32, i64      // Signed integers
bool                   // Boolean
char                   // 8-bit character
null                   // Represents expected absence of value

// Fixed-size string types (same syntax for both kernel and userspace)
str(N)                 // Fixed-size string with capacity N characters (N can be any positive integer)

// Pointer types - unified syntax for all contexts
*T                     // Pointer to type T (e.g., *u8, *PacketHeader, *[u8])

// Function pointer types
fn(param_types) -> return_type  // Function pointer type (e.g., fn(i32, i32) -> i32)

// Program function reference types (for explicit program lifecycle control)
FunctionRef            // Reference to an eBPF program function for loading/attachment
ProgramHandle          // Handle returned by load() for safe attachment
```

### 4.1.1 Null Semantics and Usage Guidelines

KernelScript uses `null` to represent **expected absence** of values, not error conditions. The same null semantics apply uniformly across both eBPF and userspace code.

#### When to Use `null`:
```kernelscript
// ✅ Map key lookups - absence is expected and normal
var flow_data = global_flows[flow_key]
if (flow_data == null) {
    // Key doesn't exist - create new entry
    global_flows[flow_key] = FlowData::new()
}

// ✅ Optional function return values - when no data is available
var packet = ctx.packet()  // Returns null if no packet available
if (packet == null) {
    return XDP_PASS
}

// ✅ Event polling - when no events are available
var event = event_queue.read()  // Returns null if queue is empty
if (event == null) {
    // No events to process
    return
}

// ✅ Optional configuration values
var timeout = config.optional_timeout  // Could be null if not set
var actual_timeout = if (timeout == null) { 5000 } else { timeout }
```

#### When to Use `throw` (NOT `null`):
```kernelscript
// ✅ Parse errors - unexpected failure conditions
fn parse_ip_header(data: *u8, len: u32) -> IpHeader {
    if (len < 20) {
        throw PARSE_ERROR_TOO_SHORT  // Error, not absence
    }
    if (data[0] >> 4 != 4) {
        throw PARSE_ERROR_INVALID_VERSION  // Error, not absence
    }
    return cast_to_ip_header(data)
}

// ✅ Resource allocation failures
fn allocate_buffer(size: u32) -> *u8 {
    var buffer = bpf_malloc(size)
    if (buffer == null) {
        throw ALLOCATION_ERROR_OUT_OF_MEMORY  // Error, not absence
    }
    return buffer
}

// ✅ Invalid input or state violations
fn update_counter(index: u32) {
    if (index >= MAX_COUNTERS) {
        throw VALIDATION_ERROR_INDEX_OUT_OF_BOUNDS  // Error, not absence
    }
    counters[index] += 1
}
```

#### Unified Pattern Across eBPF and Userspace:
```kernelscript
// Same null handling works identically in both contexts

// eBPF program
program packet_filter : xdp {
    fn main(ctx: *xdp_md) -> xdp_action {
        var cached_decision = decision_cache[ctx.hash()]
        if (cached_decision == null) {
            // Cache miss - compute decision
            var decision = compute_decision(ctx)
            decision_cache[ctx.hash()] = decision
            return decision
        }
        return cached_decision  // Cache hit
    }
}

// Userspace code
fn load_config(path: string) -> Config {
    var cached_config = config_cache[path]
    if (cached_config == null) {
        // Cache miss - load from disk
        var loaded = read_config_file(path)  // May throw on file errors
        config_cache[path] = loaded
        return loaded
    }
    return cached_config  // Cache hit
}
```

### 4.2 Compound Types
```kernelscript
// Fixed-size arrays
u8[64]                 // Array of 64 bytes
u32[16]                // Array of 16 u32 values

// Structures
struct PacketHeader {
    src_ip: u32,
    dst_ip: u32,
    protocol: u8,
    flags: u16,
}

// Enumerations (C-style naming)
enum xdp_action {
    XDP_ABORTED = 0,
    XDP_DROP = 1,
    XDP_PASS = 2,
    XDP_TX = 3,
    XDP_REDIRECT = 4,
}

// Note: TC programs now return int values directly instead of TcAction enum
// Common TC return values:
// 0 = TC_ACT_OK, 1 = TC_ACT_RECLASSIFY, 2 = TC_ACT_SHOT, 3 = TC_ACT_PIPE, 
// 4 = TC_ACT_STOLEN, 5 = TC_ACT_QUEUED, 6 = TC_ACT_REPEAT, 7 = TC_ACT_REDIRECT
```

### 4.3 Function Pointers

KernelScript supports function pointers that allow storing and calling functions through variables. Function pointers work in both eBPF and userspace contexts.

#### 4.3.1 Function Pointer Types and Declaration

```kernelscript
// Function pointer type declaration
type BinaryOp = fn(i32, i32) -> i32
type UnaryOp = fn(u32) -> u32
type VoidCallback = fn() -> void
type ErrorHandler = fn(error_code: i32) -> bool

// Function pointer variable declaration
var operation: BinaryOp
var callback: VoidCallback
var handler: ErrorHandler

// Functions that can be assigned to function pointers
fn add_numbers(a: i32, b: i32) -> i32 {
    return a + b
}

fn multiply_numbers(a: i32, b: i32) -> i32 {
    return a * b
}

fn subtract_numbers(a: i32, b: i32) -> i32 {
    return a - b
}

// Assign functions to function pointers
operation = add_numbers
var mul_op: BinaryOp = multiply_numbers
var sub_op: BinaryOp = subtract_numbers
```

#### 4.3.2 Function Pointer Usage

```kernelscript
// Higher-order function with function pointer parameter
fn process_with_callback(x: i32, y: i32, callback: fn(i32, i32) -> i32) -> i32 {
    return callback(x, y)
}

fn main() -> i32 {
    // Assign functions to function pointers
    var add_op: BinaryOp = add_numbers
    var mul_op: BinaryOp = multiply_numbers
    
    // Call functions through function pointers
    var sum = add_op(10, 20)            // Result: 30
    var product = mul_op(5, 6)          // Result: 30
    
    // Pass function pointers as arguments
    var callback_result = process_with_callback(4, 7, add_numbers)      // Result: 11
    var callback_result2 = process_with_callback(4, 7, multiply_numbers) // Result: 28
    
    return 0
}
```

#### 4.3.3 Function Pointers in eBPF Context

```kernelscript
// Function pointer usage in eBPF programs
@helper
fn validate_packet(size: u32) -> bool {
    return size >= 64 && size <= 1500
}

@helper
fn log_packet(size: u32) -> bool {
    print("Packet size: %d", size)
    return true
}

type PacketValidator = fn(u32) -> bool

@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    if (packet == null) {
        return XDP_PASS
    }
    
    // Function pointer assignment in eBPF
    var validator: PacketValidator = validate_packet
    var logger: PacketValidator = log_packet
    
    // Call through function pointer
    if (!validator(packet.len)) {
        logger(packet.len)
        return XDP_DROP
    }
    
    return XDP_PASS
}
```

### 4.4 Type Aliases for Common Patterns
```kernelscript
// Simple type aliases without complex constraints
type IpAddress = u32
type Port = u16
type PacketSize = u16
type Timestamp = u64

// Buffer types with fixed sizes (no templates needed)
type EthBuffer = [u8 14]      // Ethernet header buffer
type IpBuffer = [u8 20]       // IP header buffer
type SmallBuffer = [u8 256];  // Small general buffer
type PacketBuffer = [u8 1500] // Maximum packet buffer

// String type aliases for common patterns
type ProcessName = str(16)     // Process name string
type IpAddressStr = str(16)    // IP address string ("255.255.255.255")
type FilePath = str(256)       // File path string
type LogMessage = str(128)     // Log message string
type ShortString = str(32)     // Short general-purpose string
type MediumString = str(128)   // Medium general-purpose string

// Function pointer type aliases
type BinaryOp = fn(i32, i32) -> i32     // Binary arithmetic operation
type UnaryOp = fn(u32) -> u32           // Unary operation
type PacketValidator = fn(u32) -> bool   // Packet validation function
type ErrorHandler = fn(error_code: i32) -> bool  // Error handling callback
```

### 4.5 String Operations
KernelScript supports fixed-size strings with `str(N)` syntax, where N can be any positive integer (e.g., `str(1)`, `str(10)`, `str(42)`, `str(1000)`). The following operations are supported:

```kernelscript
// String declaration and assignment (N can be any positive integer)
var name: str(16) = "John"
var surname: str(16) = "Doe"
var buffer: str(32) = "Hello"
var small_buffer: str(8) = "tiny"
var custom_size: str(42) = "custom"
var large_buffer: str(512) = "large text content"

// Assignment
buffer = name                  // Assignment (size must be compatible)

// Indexing (read-only character access)
var first_char: char = name[0] // Returns 'J'
var last_char: char = name[3]  // Returns 'n'

// String concatenation (explicit result size required)
var full_name: str(32) = name + surname  // "JohnDoe"
var greeting: str(20) = "Hello " + name  // "Hello John"
var custom_msg: str(100) = small_buffer + " and " + custom_size  // Arbitrary sizes work

// String comparison
if (name == "John") {             // Equality comparison
    print("Name matches")
}

if (surname != "Smith") {         // Inequality comparison
    print("Surname is not Smith")
}

// Examples with different contexts
struct PersonInfo {
    name: ProcessName,          // str(16)
    address: FilePath,          // str(256)
    status: ShortString,        // str(32)
}

// Kernel space usage - kprobe with BTF-extracted function signature
@probe("sys_open")
fn user_monitor(dfd: i32, filename: *u8, flags: i32, mode: u16) -> i32 {
    var process_name: ProcessName = get_current_process_name()
    var file_path: FilePath = get_file_path_from_filename(filename)
    
    // String operations work the same in kernel space
    if (process_name == "malware") {
        var log_msg: LogMessage = "Blocked process: " + process_name
        print(log_msg)
        return -1
    }
    
    return 0
}

// Userspace usage
struct Args {
    interface: str(16),
    config_file: str(256),
}

fn main(args: Args) -> i32 {
    // Same string operations in userspace
    if (args.interface == "eth0") {
        var status_msg: str(64) = "Using interface: " + args.interface
        print(status_msg)
    }
    
    return 0
}
```

### 4.6 Pointer Operations and Memory Access

KernelScript uses a unified pointer syntax `*T` for all pointer types, with the compiler transparently handling different pointer semantics based on context. This provides simplicity while maintaining safety and performance.

#### 4.6.1 Pointer Declaration and Basic Operations

```kernelscript
// Pointer declaration - unified syntax for all contexts
var data_ptr: *u8 = get_data_source()
var header_ptr: *PacketHeader = get_packet_header()
var buffer_ptr: *[u8] = allocate_buffer(1024)

// Address-of operator (&) - take address of a value
var value: u32 = 42
var value_ptr: *u32 = &value

// Dereference operator (*) - access value through pointer
var retrieved_value: u32 = *value_ptr

// Null checking - required before dereference
if (data_ptr != null) {
    var first_byte = *data_ptr
}
```

#### 4.6.2 Struct Field Access Through Pointers

```kernelscript
struct PacketHeader {
    version: u8,
    length: u16,
    protocol: u8,
    checksum: u32,
    src_ip: u32,
    dst_ip: u32,
}

// Arrow operator (->) for pointer-to-struct field access
@helper
fn process_packet_header(header_ptr: *PacketHeader) -> bool {
    // Null check required
    if (header_ptr == null) {
        return false
    }
    
    // Arrow operator for field access
    if (header_ptr->version != 4) {
        return false
    }
    
    // Field modification through pointer
    header_ptr->checksum = 0
    header_ptr->checksum = calculate_checksum(header_ptr)
    
    return header_ptr->protocol == TCP || header_ptr->protocol == UDP
}

// Alternative explicit dereference syntax (also supported)
@helper
fn explicit_dereference_style(header_ptr: *PacketHeader) {
    if (header_ptr != null) {
        var version = (*header_ptr).version    // Explicit dereference
        (*header_ptr).checksum = 0             // Explicit modification
    }
}
```

#### 4.6.3 Array Access Through Pointers

```kernelscript
struct DataBuffer {
    header: BufferHeader,
    data: [u8; 1500],
    metadata: [u32; 16],
}

@helper
fn process_buffer(buf_ptr: *DataBuffer) {
    if (buf_ptr == null) return
    
    // Array field access through pointer
    buf_ptr->data[0] = 0xFF                    // First data byte
    buf_ptr->metadata[0] = bpf_ktime_get_ns() as u32
    
    // Iterate over array field
    for (i in 0..16) {
        buf_ptr->metadata[i] = i as u32
    }
    
    // Get pointer to array element
    var data_start: *u8 = &buf_ptr->data[0]
    var metadata_ptr: *u32 = &buf_ptr->metadata[0]
    
    // Process with raw pointers
    process_raw_data(data_start, buf_ptr->header.length)
}
```

#### 4.6.4 Pointer Arithmetic

```kernelscript
@helper
fn pointer_arithmetic_examples(base_ptr: *u8, len: u32) {
    if (base_ptr == null) return
    
    // Pointer arithmetic - compiler inserts bounds checks
    var next_byte_ptr = base_ptr + 1           // Move to next byte
    var offset_ptr = base_ptr + 10             // Move by offset
    
    // Array-style indexing (preferred for readability)
    var first_byte = base_ptr[0]               // Equivalent to *base_ptr
    var tenth_byte = base_ptr[9]               // Equivalent to *(base_ptr + 9)
    
    // Pointer difference
    var byte_distance = next_byte_ptr - base_ptr  // Returns 1
}
```

#### 4.6.5 Context-Aware Pointer Semantics

```kernelscript
// eBPF Context - Automatic bounds checking and dynptr integration
@xdp
fn ebpf_pointer_usage(ctx: *xdp_md) -> xdp_action {
    // Context pointers - automatically bounded
    var packet_data: *u8 = ctx->data()          // Bounded by ctx->data_end()
    var packet_end: *u8 = ctx->data_end()       // End boundary
    
    // Compiler automatically inserts verifier-compliant bounds checks
    if (packet_data + 14 <= packet_end) {
        var eth_header = packet_data as *EthHeader
        if (eth_header->eth_type == ETH_P_IP) {
            // Safe access - bounds verified
            process_ethernet_header(eth_header)
        }
    }
    
    // Dynptr-backed pointers (transparent to user) — `log_buffer` is the
    // *u8 returned by reserve(), in scope only inside the truthy branch.
    if (var log_buffer = event_log.reserve(256)) {
        // Regular pointer operations - compiler uses dynptr API internally
        log_buffer[0] = EVENT_TYPE_PACKET
        write_packet_summary(log_buffer + 1, packet_data, 255)
        event_log.submit(log_buffer)
    }
    
    return XDP_PASS
}

// Userspace Context - Full pointer functionality
fn userspace_pointer_usage() -> i32 {
    // Dynamic allocation
    var buffer: *u8 = malloc(4096)
    if (buffer == null) {
        return -1
    }
    
    // Full pointer arithmetic
    var mid_ptr = buffer + 2048
    var end_ptr = buffer + 4096
    
    // Direct memory operations
    *buffer = 0xFF
    buffer[100] = 0xAA
    
    // Cleanup
    free(buffer)
    return 0
}
```

#### 4.6.6 Function Parameters with Pointers

```kernelscript
// Explicit parameter semantics - no transparent conversion

// Value semantics - always copy (compiler warns for large structs in eBPF)
fn process_by_value(data: PacketData) {
    data.packets += 1  // Modifies local copy only
}

// Pointer semantics - explicit reference
fn process_by_pointer(data: *PacketData) {
    if (data != null) {
        data->packets += 1  // Modifies original through pointer
    }
}

// Example with compiler guidance
@helper
fn ebpf_function_parameters() {
    var large_struct = LargePacketData { /* ... */ }
    
    // ⚠️ Compiler warning: "Large struct (1024 bytes) passed by value in eBPF context"
    // process_by_value(large_struct)  
    
    // ✅ Recommended: use pointer for large structs in eBPF
    process_by_pointer(&large_struct)
}
```

#### 4.6.7 Map Integration with Pointers

```kernelscript
var flow_map : hash<FlowKey, FlowData>(1024)

@helper
fn map_pointer_operations(flow_key: FlowKey) {
    // Declaration-as-condition: a single map lookup; `flow_data` is the
    // returned pointer, in scope only inside the truthy branch.
    if (var flow_data = flow_map[flow_key]) {
        // Direct modification through pointer
        flow_data->packet_count += 1
        flow_data->byte_count += packet_size
        flow_data->last_seen = bpf_ktime_get_ns()

        // Compiler tracks map value lifetime
        // flow_data becomes invalid after certain map operations
    }
}
```

#### 4.6.8 Safety Rules and Compiler Enforcement

```kernelscript
// Automatic null checking enforcement
@helper
fn null_safety_example(ptr: *u8) -> u8 {
    // ❌ Compilation error: potential null dereference
    // return *ptr
    
    // ✅ Required null check
    if (ptr != null) {
        return *ptr
    }
    return 0
}

// Bounds checking in eBPF context
@xdp
fn bounds_safety_example(ctx: *xdp_md) -> xdp_action {
    var data = ctx->data()
    var data_end = ctx->data_end()
    
    // Compiler automatically generates verifier-compliant bounds checks
    if (data + sizeof(EthHeader) <= data_end) {
        var eth = data as *EthHeader
        // Safe to access eth->fields
        return process_ethernet(eth)
    }
    
    return XDP_DROP
}
```

## 5. eBPF Maps and Global Sharing

### 5.1 Map Declaration Syntax
```ebnf
map_declaration = [ "pin" ] [ "@flags" "(" flag_expression ")" ] "var" identifier ":" map_type "<" key_type "," value_type ">" "(" map_config ")"

map_type = "hash" | "array" | "percpu_hash" | "percpu_array" | "lru_hash" 

map_config = max_entries [ "," additional_config ]
flag_expression = identifier | ( identifier { "|" identifier } )
```

### 5.1.1 Map Pinning

Maps declared with the `pin` keyword are automatically pinned to the BPF filesystem using standardized paths:

```
/sys/fs/bpf/<PROJECT_NAME>/maps/<MAP_NAME>
```

The project name is automatically determined from the package/executable name.

**Note**: The `pin` keyword is also used for global variables (see section 3.3.5), which are pinned to `/sys/fs/bpf/<PROJECT_NAME>/globals/pinned_globals`.

### 5.1.2 Map Flags

Map flags can be specified using the `@flags` attribute:

```kernelscript
// Map with flags
@flags(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU)
var dynamic_cache : hash<u32, PacketData>(1024)

// Pinned map with flags
@flags(BPF_F_NO_PREALLOC)
pin var persisted_flows : hash<u32, FlowData>(2048)
```

**Supported flags:**
- `BPF_F_NO_PREALLOC` - Disable preallocation of map elements
- `BPF_F_NO_COMMON_LRU` - Disable common LRU for LRU maps
- `BPF_F_NUMA_NODE` - Specify NUMA node for map allocation
- `BPF_F_RDONLY` - Map is read-only from program side
- `BPF_F_WRONLY` - Map is write-only from program side
- `BPF_F_RDONLY_PROG` - Map is read-only from program side
- `BPF_F_WRONLY_PROG` - Map is write-only from program side

### 5.2 Global Maps (Shared Across Programs)

Global maps are declared at the global scope and are automatically shared between all eBPF programs.

**Map Declaration Syntax:**
- `var name : Type<K,V>(size)` - Local map (program-specific)
- `pin var name : Type<K,V>(size)` - Pinned map (persisted to filesystem)
- `@flags(...) var name : Type<K,V>(size)` - Map with specific flags
- `@flags(...) pin var name : Type<K,V>(size)` - Pinned map with flags

**Automatic Path Generation:**
Pinned maps are automatically stored at `/sys/fs/bpf/<PROJECT_NAME>/maps/<MAP_NAME>`.

```kernelscript
// Global maps - automatically shared between all programs

// Pinned maps - persisted to filesystem (/sys/fs/bpf/<PROJECT>/maps/<NAME>)
pin var global_flows : hash<FlowKey, FlowStats>(10000)
pin var interface_stats : array<u32, InterfaceStats>(256)
pin var security_events : hash<SecurityEvent, u64>(1024)

// Non-pinned maps - shared during runtime but not persisted
var session_cache : hash<u32, TempData>(512)

// Maps with flags
@flags(BPF_F_NO_PREALLOC)
pin var global_config : array<ConfigKey, ConfigValue>(64)

// Program 1: Can access all global maps
@xdp
fn ingress_monitor(ctx: *xdp_md) -> xdp_action {
    var flow_key = extract_flow_key(ctx)?
    
    // Access global map directly
    if (global_flows[flow_key] == null) {
        global_flows[flow_key] = FlowStats::new()
    }
    global_flows[flow_key].ingress_packets += 1      // Compound assignment
    global_flows[flow_key].ingress_bytes += ctx.packet_size()  // Compound assignment
    
    // Update interface stats using compound assignment
    interface_stats[ctx.ingress_ifindex()].packets += 1
    
    return XDP_PASS
}

// Program 2: Automatically has access to the same global maps
@tc("egress")
fn egress_monitor(ctx: *__sk_buff) -> i32 {
    var flow_key = extract_flow_key(ctx)?
    
    // Same global map, no import needed - compound assignments work everywhere
    if (global_flows[flow_key] != null) {
        global_flows[flow_key].egress_packets += 1        // Compound assignment
        global_flows[flow_key].egress_bytes += ctx.packet_size()   // Compound assignment
    }
    
    // Check global configuration
    var enable_filtering = if (global_config[CONFIG_KEY_ENABLE_FILTERING] != null) {
        global_config[CONFIG_KEY_ENABLE_FILTERING]
    } else {
        CONFIG_VALUE_BOOL_FALSE
    }
    
    if (enable_filtering.as_bool() && should_drop(flow_key)) {
        // Log to global security events
        security_events.submit(SecurityEvent {
            event_type: EVENT_TYPE_PACKET_DROPPED,
            flow_key: flow_key,
            timestamp: bpf_ktime_get_ns(),
        })
        return 2  // TC_ACT_SHOT
    }
    
    return 0  // TC_ACT_OK
}

// Program 3: Security analyzer using the same global maps
@lsm("socket_connect")
fn security_analyzer(ctx: LsmContext) -> i32 {
    var flow_key = extract_flow_key_from_socket(ctx)?
    
    // Check global flow statistics — single lookup via IfLet
    if (var flow_stats = global_flows[flow_key]) {
        if (flow_stats.is_suspicious()) {
            security_events.submit(SecurityEvent {
                event_type: EVENT_TYPE_SUSPICIOUS_CONNECTION,
                flow_key: flow_key,
                timestamp: bpf_ktime_get_ns(),
            })
            return -EPERM  // Block connection
        }
    }

    return 0  // Allow connection
}
```

### 5.3 Global Map Access

```kernelscript
// Global maps - accessible by all eBPF programs
pin var global_counters : array<u32, GlobalCounter>(256)
pin var event_stream : hash<u32, Event>(1024)

@probe("sys_read")
fn producer(fd: u32, buf: *u8, count: size_t) -> i32 {
    var pid = bpf_get_current_pid_tgid() as u32
    
    // Update global counter (accessible by other programs)
    global_counters[pid % 256] += 1
    
    // Send event to global stream
    var event = Event {
        pid: pid,
        syscall: "read",
        fd: fd,
        bytes_requested: count,
        timestamp: bpf_ktime_get_ns(),
    }
    event_stream.submit(event)
    
    return 0
}

@probe("sys_write")
fn consumer(fd: u32, buf: *u8, count: size_t) -> i32 {
    var pid = bpf_get_current_pid_tgid() as u32
    
    // Access global counter (same map as producer program)
    var read_count = global_counters[pid % 256]
    
    // Process the write count data with actual parameters
    process_write_count(read_count, fd, count)
    
    return 0
}
```

### 5.4 Map Examples
```kernelscript
// Global maps accessible by all programs
pin var packet_stats : hash<u32, PacketStats>(1024)

pin var counters : percpu_array<u32, u64>(256)

pin var active_flows : lru_hash<FlowKey, FlowInfo>(10000)

pin var events : hash<u32, PacketEvent>(1024)

pin var config_map : array<ConfigKey, ConfigValue>(16)

@xdp
fn simple_monitor(ctx: *xdp_md) -> xdp_action {
    // Access global maps directly
    packet_stats[ctx.packet_type()] += 1
    counters[0] += 1
    
    // Process packet and update flow info
    var flow_key = extract_flow_key(ctx)
    active_flows[flow_key] = FlowInfo::new()
    
    return XDP_PASS
}
```

## 6. Assignment Operators

### 6.1 Simple Assignment
```kernelscript
var x: u32 = 10
x = 20  // Simple assignment
```

### 6.2 Compound Assignment Operators

KernelScript supports compound assignment operators that provide a concise way to perform arithmetic operations combined with assignment. These operators work identically to their C counterparts and are supported in both eBPF and userspace contexts.

#### 6.2.1 Supported Operators
```kernelscript
// Compound assignment operators
x += y   // Equivalent to: x = x + y
x -= y   // Equivalent to: x = x - y  
x *= y   // Equivalent to: x = x * y
x /= y   // Equivalent to: x = x / y
x %= y   // Equivalent to: x = x % y
```

#### 6.2.2 Type Requirements and Safety

Compound assignment operators enforce type safety and const variable protection:

```kernelscript
// Valid usage with compatible types
var counter: u32 = 0
var increment: u32 = 5

counter += increment    // ✅ Both u32 - valid
counter *= 2           // ✅ u32 with literal - valid
counter %= 10          // ✅ Modulo with u32 - valid

// Type restrictions
const MAX_VALUE: u32 = 1000
// MAX_VALUE += 1      // ❌ Compilation error: cannot assign to const

var float_val: f32 = 3.14
// counter += float_val  // ❌ Compilation error: type mismatch

// Operator restrictions - only arithmetic types support arithmetic operators
var flag: bool = true
// flag += true         // ❌ Compilation error: operator not supported for bool
```

#### 6.2.3 Usage in eBPF Programs

Compound assignments work seamlessly in eBPF programs with automatic bounds checking:

```kernelscript
// Global counters using compound assignment
var packet_count: u64 = 0
var total_bytes: u64 = 0

@xdp
fn packet_counter(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    if (packet == null) {
        return XDP_PASS
    }
    
    // Compound assignments in eBPF context
    packet_count += 1                    // Increment packet counter
    total_bytes += packet.len            // Add packet size to total
    
    var processing_time = measure_time()
    processing_time *= 2                 // Double the processing time
    processing_time /= 1000              // Convert to milliseconds
    
    return XDP_PASS
}

// Map operations with compound assignment
var flow_stats : hash<u32, FlowStats>(1024)

@helper
fn update_flow_stats(flow_id: u32, packet_size: u32) {
    // Compound assignment on a struct-field of a map value emits a single
    // presence-checked map lookup and mutates in place; see §6.2.5.
    flow_stats[flow_id].packet_count += 1
    flow_stats[flow_id].total_bytes  += packet_size
}
```

#### 6.2.4 Usage in Userspace Programs

Compound assignments work identically in userspace code:

```kernelscript
struct Statistics {
    processed: u64,
    errors: u32,
    total_time: u64,
}

fn process_batch(stats: *Statistics, batch_size: u32, processing_time: u64) {
    // Compound assignment with struct fields
    stats->processed += batch_size
    stats->total_time += processing_time
    
    // Local variable compound assignment
    var error_rate: u32 = stats->errors * 100
    error_rate /= stats->processed as u32
    
    if (error_rate > 5) {
        stats->errors += 1
    }
}

fn main() -> i32 {
    var stats = Statistics { processed: 0, errors: 0, total_time: 0 }
    var batch_count: u32 = 0
    var total_items: u64 = 0
    
    for (i in 0..100) {
        batch_count += 1
        total_items += 50    // Process 50 items per batch
        
        process_batch(&stats, 50, measure_batch_time())
    }
    
    // Final calculations using compound assignment
    stats.total_time /= 1000000  // Convert nanoseconds to milliseconds
    
    print("Processed %d items in %d batches", total_items, batch_count)
    print("Total time: %d ms", stats.total_time)
    
    return 0
}
```

#### 6.2.5 Compound Assignment with Map Indexing

KernelScript extends compound assignment to map index expressions, so a
counter update against a map value can be written without an intermediate
variable or an explicit write-back.

##### 6.2.5.1 Scalar map values

When the map's value type is an integer, `m[k] op= rhs` reads the current
entry, applies `op`, and writes the result back. If the entry is absent
the read yields zero, so the operation creates the entry on first use.

```kernelscript
var packet_counts : hash<u32, u64>(1024)

@xdp
fn rate_limiter(ctx: *xdp_md) -> xdp_action {
    var src_ip = extract_src_ip(ctx)
    packet_counts[src_ip] += 1   // read-modify-write; creates entry if absent
    return XDP_PASS
}
```

The supported operators are `+=`, `-=`, `*=`, `/=`, `%=`. The map's value
type must be one of the integer primitives.

##### 6.2.5.2 Struct-field map values

When the map's value type is a struct, `m[k].field op= rhs` mutates a
single field of an existing entry in place. The compiler lowers the form
to a presence-checked pointer mutation:

```kernelscript
struct PacketStats {
    count: u64,
    total_bytes: u64,
}

var ip_stats : hash<u32, PacketStats>(1024)

@xdp
fn observe(ctx: *xdp_md) -> xdp_action {
    var ip = extract_src_ip(ctx)
    var len = packet_len(ctx)
    ip_stats[ip].count       += 1
    ip_stats[ip].total_bytes += len
    return XDP_PASS
}
```

Semantics:

- **Map identifier required.** The left-hand side must be `IDENT[expr].field op= rhs`;
  arbitrary LHS expressions are not allowed.
- **Value type must be a struct.** `field` is resolved against the map's value
  struct definition; an unknown field is a compile-time error.
- **Field type drives `op`.** The named field must be one of the integer
  primitives; the right-hand side must be assignment-compatible with the field type.
- **Presence check, no creation.** If the entry is absent the statement is a
  no-op — unlike scalar `m[k] op= rhs`, the struct-field form does *not*
  create a default entry. To handle the missing case, pair it with an
  explicit `else` using the declaration-as-condition form (see §7.5.1).
- **Single map lookup.** Generated code performs one `bpf_map_lookup_elem`,
  guards on the returned pointer, and writes through it
  (`if (p) { p->field = p->field op rhs; }`); there is no separate write-back.

#### 6.2.6 Performance and Code Generation

Compound assignments generate efficient code in both contexts:

**eBPF bytecode**: Optimized to minimize instruction count
**Userspace C**: Direct compound assignment operators (`x += y`)

```c
// Generated C code for userspace
total_bytes = (total_bytes + packet_size);  // From: total_bytes += packet_size
counter = (counter * 2);                    // From: counter *= 2
value = (value % modulus);                  // From: value %= modulus
```

## 7. Functions and Control Flow

### 7.1 Function Declaration Overview

KernelScript functions support both traditional unnamed return types and modern named return values. The complete grammar is defined in Section 15 (Complete Formal Grammar).

Key function types:
- **eBPF program functions**: Attributed with `@xdp`, `@tc`, `@tracepoint`, etc. - compile to eBPF bytecode
- **Helper functions**: Attributed with `@helper` - shared across all eBPF programs
- **Userspace functions**: No attributes - compile to native executable

### 7.2 eBPF Program Functions
```kernelscript
// eBPF program function with attribute - entry point
@xdp
fn simple_xdp(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()?
    
    if packet.is_tcp() {
        return XDP_PASS
    }
    
    return XDP_DROP
}
```

### 7.3 Named Return Values

KernelScript supports both unnamed and named return values following Go's syntax pattern:

- **Unnamed returns** (backward compatible): `fn name() -> type`
- **Named returns** (new): `fn name() -> var_name: type`

Named return values automatically declare a local variable with the specified name and type. This variable can be used throughout the function, and naked returns (`return` without a value) will return the current value of the named variable.

#### 7.3.1 Named Return Syntax Examples

```kernelscript
// Backward compatible unnamed return (unchanged)
fn add_numbers(a: i32, b: i32) -> i32 {
    return a + b
}

// Named return value - 'sum' becomes a local variable
fn add_numbers_named(a: i32, b: i32) -> sum: i32 {
    sum = a + b    // Named variable is automatically declared
    return         // Naked return - returns current value of 'sum'
}

// Using named return in complex logic
fn calculate_hash(data: *u8, len: u32) -> hash_value: u64 {
    hash_value = 0  // Named return variable is available immediately
    
    for (i in 0..len) {
        hash_value = hash_value * 31 + data[i]  // Modify throughout function
    }
    
    return          // Naked return with computed hash_value
}

// Mixing named variables with explicit returns
fn validate_packet(data: *u8, len: u32) -> is_valid: bool {
    is_valid = false  // Start with default value
    
    if (len == 0) {
        return        // Early naked return with is_valid = false
    }
    
    if (data == null) {
        return false  // Explicit return still works
    }
    
    is_valid = true   // Set to true if all checks pass
    return            // Final naked return
}
```

#### 7.3.2 Named Returns in Different Contexts

Named return values work consistently across all function types:

```kernelscript
// eBPF helper functions with named returns
@helper
fn extract_ip_header(ctx: *xdp_md) -> ip_hdr: *iphdr {
    var data = ctx->data
    var data_end = ctx->data_end
    
    if (data + 14 + 20 > data_end) {
        ip_hdr = null
        return  // Naked return with null
    }
    
    ip_hdr = (iphdr*)(data + 14)
    return  // Naked return with pointer
}

// eBPF program functions with named returns
@xdp
fn packet_filter(ctx: *xdp_md) -> action: xdp_action {
    action = XDP_PASS  // Default action
    
    var size = ctx->data_end - ctx->data
    if (size < 64) {
        action = XDP_DROP
        return  // Naked return with XDP_DROP
    }
    
    return  // Naked return with XDP_PASS
}

// Userspace functions with named returns
fn lookup_counter(ip: u32) -> counter_ptr: *u64 {
    if (counters[ip] == null) {
        counters[ip] = 0
    }
    counter_ptr = &counters[ip]
    return  // Naked return
}

// Function pointer types with named returns
type HashFunction = fn(*u8, u32) -> hash: u64
type PacketProcessor = fn(*xdp_md) -> result: xdp_action
```

#### 7.3.3 Code Generation

Named return values compile to clean, efficient C code with zero runtime overhead:

**KernelScript:**
```kernelscript
fn calculate_sum(a: i32, b: i32) -> result: i32 {
    result = a + b
    return
}
```

**Generated C:**
```c
static int calculate_sum(int a, int b) {
    int result;      // Named return variable declared
    result = a + b;
    return result;   // Naked return becomes explicit
}
```

### 7.4 Helper Functions

KernelScript supports two types of functions with different scoping rules:

1. **Kernel-shared functions** (`@helper`) - Shared across all eBPF programs
2. **Userspace functions** (no `kernel` qualifier, no attributes) - Native userspace code

```kernelscript
// Kernel-shared functions - accessible by all eBPF programs
@helper
fn validate_packet(packet: *PacketHeader) -> bool {
    packet.len >= 64 && packet.len <= 1500
}

// Public kernel-shared function
@helper
pub fn calculate_checksum(data: *u8, len: u32) -> u16 {
    var sum: u32 = 0
    for (i in 0..(len / 2)) {
        sum += data[i * 2] + (data[i * 2 + 1] << 8)
    }
    while (sum >> 16 != 0) {
        sum = (sum & 0xFFFF) + (sum >> 16)
    }
    return !(sum as u16)
}

// Private kernel-shared function
@helper
priv fn internal_kernel_helper() -> u32 {
    return 42
}

@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    // Can call kernel-shared functions
    if (!validate_packet(ctx.packet())) {
        return XDP_DROP
    }
    
    var checksum = calculate_checksum(ctx->data(), ctx.len())
    
    return XDP_PASS
}

@tc("ingress")
fn flow_monitor(ctx: *__sk_buff) -> i32 {
    // Can call the same kernel-shared functions
    if (!validate_packet(ctx.packet())) {
        return 2  // TC_ACT_SHOT
    }
    
    return 0  // TC_ACT_OK
}

// Userspace function (no kernel qualifier, no attributes)
fn setup_monitoring() -> i32 {
    print("Setting up monitoring system")
    return 0
}

fn main() -> i32 {
    setup_monitoring()  // Can call other userspace functions
    
    // Cannot call validate_packet() here - it's kernel-only
    
    var filter_handle = load(packet_filter)
    var monitor_handle = load(flow_monitor)
    
    attach(filter_handle, "eth0", 0)
    attach(monitor_handle, "eth0", 1)
    
    print("Multiple programs attached to eth0")
    print("Running packet processing pipeline...")
    
    // Proper cleanup - detach in reverse order (best practice)
    detach(monitor_handle)
    detach(filter_handle)
    print("All programs detached successfully")
    
    return 0
}
```

### 7.5 eBPF Tail Calls

KernelScript provides transparent eBPF tail call support that automatically converts function calls to tail calls when appropriate. Tail calls enable efficient program chaining without stack overhead and are especially useful for packet processing pipelines.

#### 7.4.1 Automatic Tail Call Detection

The compiler automatically converts function calls to eBPF tail calls when **all** of the following conditions are met:

1. **Return position**: The function call is in a return statement
2. **Same program type**: Both functions have the same attribute (e.g., both `@xdp`)  
3. **Compatible signature**: Same context parameter and return type
4. **eBPF context**: The call is within an attributed eBPF function

```kernelscript
// eBPF programs that can be tail-called
@xdp
fn packet_classifier(ctx: *xdp_md) -> xdp_action {
    var protocol = get_protocol(ctx)  // Regular call (@helper)
    
    return match (protocol) {
        HTTP: process_http(ctx),    // Tail call - meets all conditions
        DNS: process_dns(ctx),      // Tail call - meets all conditions  
        ICMP: handle_icmp(ctx),     // Tail call - meets all conditions
        default: XDP_DROP           // Regular return
    }
}

@xdp  
fn process_http(ctx: *xdp_md) -> xdp_action {
    // HTTP processing logic
    if (is_malicious_http(ctx)) {    // Regular call (@helper)
        return XDP_DROP
    }
    
    return filter_by_policy(ctx)     // Tail call - another @xdp function
}

@xdp
fn filter_by_policy(ctx: *xdp_md) -> xdp_action {
    // Policy enforcement
    return XDP_PASS 
}

// Kernel helper function (not tail-callable)
@helper
fn get_protocol(ctx: *xdp_md) -> u16 {
    // Extract protocol from packet
    return 6  // TCP
}

@helper
fn is_malicious_http(ctx: *xdp_md) -> bool {
    // Security analysis
    return false
}
```

#### 7.4.2 Tail Call Rules and Restrictions

**✅ Valid Tail Calls:**
```kernelscript
@xdp 
fn main_filter(ctx: *xdp_md) -> xdp_action {
    return specialized_filter(ctx)   // ✅ Same type (@xdp), return position
}

@tc("ingress")
fn ingress_handler(ctx: *__sk_buff) -> i32 {
    return security_check(ctx)       // ✅ Same type (@tc), return position  
}
```

**❌ Invalid Tail Calls (Become Regular Calls or Errors):**
```kernelscript
@xdp
fn invalid_examples(ctx: *xdp_md) -> xdp_action {
    // ❌ ERROR: Cannot call eBPF program function directly
    var result = process_http(ctx)
    
    // ❌ ERROR: Mixed program types (@xdp calling @tc)  
    return security_check(ctx)  // security_check is @tc
    
    // ✅ Regular call: kernel function
    validate_packet(ctx)
    
    // ✅ Regular call: kernel function  
    return if (validate_packet(ctx)) { XDP_PASS } else { XDP_DROP }
}
```

#### 7.4.3 Implementation Details

**Automatic Program Array Management:**
The compiler automatically generates and manages eBPF program arrays behind the scenes:

```kernelscript
// User writes this clean code:
@xdp fn classifier(ctx: *xdp_md) -> xdp_action {
    return match (get_protocol(ctx)) {
        HTTP: process_http(ctx),
        DNS: process_dns(ctx),
        default: XDP_DROP
    }
}

// Compiler generates (hidden from user):
// 1. Program array for tail call targets
// 2. Initialization code to populate the array  
// 3. bpf_tail_call() instead of regular function calls
// 4. Proper error handling for failed tail calls
```

**Userspace Transparency:**
Tail calls are completely transparent to userspace code. Each attributed function remains a complete, independent eBPF program that can be loaded and attached individually:

```kernelscript
struct Args {
    interface: str(16),
    mode: str(16),
}

fn main(args: Args) -> i32 {
    if (args.mode == "simple") {
        // Load individual program (no tail calls)
        var http_handle = load(process_http)
        attach(http_handle, args.interface, 0)
    } else {
        // Load main program (automatically sets up tail calls)
        var main_handle = load(packet_classifier)  
        attach(main_handle, args.interface, 0)
    }
    
    return 0
}
```

#### 7.4.4 Performance and Limitations

**Benefits:**
- **Zero stack overhead**: Tail calls replace the current program rather than adding stack frames
- **Efficient chaining**: Ideal for packet processing pipelines
- **Resource sharing**: All programs in the chain share the same context and maps

**eBPF Limitations (automatically handled by compiler):**
- **Maximum chain depth**: eBPF enforces a limit of 33 tail calls per execution
- **No return to caller**: Tail calls are terminal - they replace the current program
- **Same context type**: All programs in the chain must accept the same context

### 7.5 Control Flow Statements

#### 7.5.1 Conditional Statements

KernelScript provides two `if` forms: a standard expression-condition
form and a *declaration-as-condition* form that combines a single-use
binding with a presence check.

##### 7.5.1.1 Expression-condition form

```kernelscript
// Conditional statements
if (condition) {
    // statements
} else if (other_condition) {
    // statements
} else {
    // statements
}
```

##### 7.5.1.2 Declaration-as-condition form (`if (var name = expr)`)

```kernelscript
if (var name = expr) {
    // then-branch: `name` is in scope and bound to `expr`'s value
} else {
    // else-branch: `name` is *not* in scope
}
```

The branch is taken iff `expr` produces a *present* value:

- **Map index** (`m[k]`): present iff the entry exists. The bound name is
  the lookup pointer, so field access auto-derefs and field assignments
  mutate the underlying map entry in place — no explicit write-back is
  needed:

  ```kernelscript
  if (var stats = ip_stats[ip]) {
      stats.count = stats.count + 1   // writes through the lookup pointer
  } else {
      ip_stats[ip] = PacketStats { count: 1, total_bytes: 0 }
  }
  ```

- **Pointer-returning expression**: present iff non-null. Useful with
  helpers and kfuncs that may return `null`.

Semantics:

- **Single evaluation.** `expr` is evaluated exactly once; its presence
  test guards both branches.
- **Scoping.** `name` is in scope only inside the then-branch. Referencing
  it from the else-branch (or after the `if`) is a compile-time error.
- **No reassignment.** `name` shadows nothing visible to the else-branch
  and may shadow an outer binding only inside the then-branch.
- **Else is optional.** As with the expression-condition form, the
  `else` branch may be omitted.
- **Lowering.** The form lowers to a single `bpf_map_lookup_elem` (or the
  underlying pointer-returning call), a null check, and the chosen
  branch — there is no second lookup.

#### 7.5.2 Match Expressions

KernelScript provides `match` expressions for efficient multi-way branching. Match is an expression that returns a value and can be used anywhere an expression is expected.

```kernelscript
// Basic match expression with constant patterns
var action = match (packet.protocol()) {
    IPPROTO_TCP: XDP_PASS,
    IPPROTO_UDP: XDP_PASS,
    IPPROTO_ICMP: XDP_DROP,
    default: XDP_ABORTED
}

// Match in return statements - ideal for packet processing
@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    var packet = ctx.packet()
    if (packet == null) return XDP_PASS
    
    return match (packet.protocol()) {
        IPPROTO_TCP: handle_tcp(ctx),    // Function call in match arm
        IPPROTO_UDP: handle_udp(ctx),    // Can be tail call candidates
        IPPROTO_ICMP: XDP_DROP,          // Or direct return values
        default: XDP_PASS
    }
}

// Match with complex expressions in arms
var result = match (security_level) {
    HIGH: process_high_security(packet),
    MEDIUM: if (packet.is_encrypted()) { XDP_PASS } else { XDP_DROP },
    LOW: XDP_PASS,
    default: XDP_ABORTED
}

// Nested match expressions
var final_action = match (packet.protocol()) {
    IPPROTO_TCP: match (tcp_header.dst_port) {
        80: handle_http(ctx),
        443: handle_https(ctx),
        22: handle_ssh(ctx),
        default: XDP_PASS
    },
    IPPROTO_UDP: handle_udp(ctx),
    default: XDP_DROP
}
```

#### 7.5.3 Loop Statements

```kernelscript
// Loops with automatic bounds checking
for (i in 0..MAX_ITERATIONS) {
    if (should_break()) {
        break
    }
    process_item(i)
}

// While loops (compiler ensures termination)
var iterations = 0
while (condition && iterations < MAX_ITERATIONS) {
    do_work()
    iterations = iterations + 1
}
```

## 8. Error Handling and Resource Management

### 8.1 Throw and Catch Statements

KernelScript provides modern error handling through `throw` and `catch` statements that compile to efficient C error checking code. Error handling uses integer values for maximum performance and compatibility with both eBPF and userspace environments.

```kernelscript
// Error codes as simple enums or constants (C-style naming)
enum ParseError {
    PARSE_ERROR_TOO_SHORT = 1,
    PARSE_ERROR_INVALID_VERSION = 2,
    PARSE_ERROR_BAD_CHECKSUM = 3,
}

enum NetworkError {
    NETWORK_ERROR_ALLOCATION_FAILED = 10,
    NETWORK_ERROR_MAP_UPDATE_FAILED = 11,
    NETWORK_ERROR_RATE_LIMITED = 12,
}

// Or use simple constants
const ERROR_INVALID_PACKET = 100
const ERROR_RATE_LIMITED = 101

// Functions can throw integer error codes
fn parse_ip_header(packet: *u8, len: u32) -> IpHeader {
    if (len < 20) {
        throw PARSE_ERROR_TOO_SHORT  // Throws integer value 1
    }
    
    var header = cast_to_ip_header(packet)
    if (header.version != 4) {
        throw PARSE_ERROR_INVALID_VERSION  // Throws integer value 2
    }
    
    return header
}

// Error handling with try/catch blocks using integer matching
fn process_packet(ctx: *xdp_md) -> xdp_action {
    try {
        var packet = get_packet(ctx)
        if (packet == null) {
            throw NETWORK_ERROR_ALLOCATION_FAILED  // Throws integer value 10
        }
        
        var header = parse_ip_header(packet.data, packet.len)
        update_flow_stats(header)
        
        return XDP_PASS
        
    } catch 1 {  // PARSE_ERROR_TOO_SHORT
        return XDP_DROP
        
    } catch 2 {  // PARSE_ERROR_INVALID_VERSION
        return XDP_DROP
        
    } catch 10 {  // NETWORK_ERROR_ALLOCATION_FAILED
        return XDP_ABORTED
        
    } catch _ {  // Catch-all for any other error
        return XDP_ABORTED
    }
}

// You can also throw literal integers or variables
fn validate_input(value: i32) {
    if (value < 0) {
        throw 42  // Direct integer throw
    }
    
    var error_code = compute_error_code(value)
    if (error_code != 0) {
        throw error_code  // Variable throw
    }
}
```

### 8.2 Resource Management with Defer

The `defer` statement ensures cleanup code runs automatically at function exit, regardless of how the function returns (normal return, throw, or early exit).

```kernelscript
// Resource management with automatic cleanup
fn update_shared_counter(index: u32) -> bool {
    var data = shared_counters[index]
    if (data == null) {
        return false
    }
    
    // Acquire lock and ensure it's always released
    bpf_spin_lock(&data.lock)
    defer bpf_spin_unlock(&data.lock)  // Always executes at function exit
    
    // Critical section
    data.counter += 1
    
    if (data.counter > 1000000) {
        throw NETWORK_ERROR_RATE_LIMITED  // defer still executes (throws 12)
    }
    
    return true  // defer executes here too
}

// Multiple defer statements execute in reverse order (LIFO)
fn complex_resource_management() -> bool {
    var buffer = allocate_buffer()
    defer free_buffer(buffer)          // Executes 3rd
    
    var lock = acquire_lock()
    defer release_lock(lock)           // Executes 2nd
    
    var fd = open_file("config.txt")
    defer close_file(fd)               // Executes 1st
    
    // Use resources safely
    return process_data(buffer, lock, fd)
    // All defer statements execute automatically in reverse order
}
```

### 8.3 Defer with Try/Catch

Defer statements work seamlessly with error handling - cleanup always occurs even when exceptions are thrown or caught.

```kernelscript
fn safe_packet_processing(ctx: *xdp_md) -> xdp_action {
    var packet_buffer = allocate_packet_buffer()
    defer free_packet_buffer(packet_buffer)  // Always executes
    
    try {
        var lock = acquire_flow_lock()
        defer release_flow_lock(lock)        // Always executes
        
        var flow_data = process_flow(packet_buffer)
        if (flow_data.is_suspicious()) {
            throw NETWORK_ERROR_RATE_LIMITED  // Throws 12
        }
        
        return XDP_PASS
        
    } catch 12 {  // NETWORK_ERROR_RATE_LIMITED
        increment_drop_counter()
        return XDP_DROP
        // Both defer statements execute even in catch block
    }
}
```

### 8.4 Error Handling Rules and Compiler Behavior

#### 8.4.1 eBPF Program Functions

**All throws must be caught** in eBPF program functions. Uncaught throws result in **compilation errors**.

```kernelscript
program packet_filter : xdp {
    fn main(ctx: *xdp_md) -> xdp_action {
        try {
            var result = process_packet(ctx)  // Might throw
            return XDP_PASS
            
        } catch 1 {  // PARSE_ERROR_TOO_SHORT
            return XDP_DROP
            
        } catch 10 {  // NETWORK_ERROR_ALLOCATION_FAILED
            return XDP_ABORTED
        }
        // ❌ Compiler ERROR if any possible throw is not caught
    }
}
```

#### 8.4.2 Helper Functions

Helper functions can propagate errors without catching them - this enables natural error composition and reduces boilerplate.

```kernelscript
// Helper functions can throw without catching
fn extract_flow_key(ctx: *xdp_md) -> FlowKey {
    var packet = get_packet(ctx)
    if packet == null {
        throw NETWORK_ERROR_ALLOCATION_FAILED  // ✅ OK - propagates to caller (throws 10)
    }
    
    return parse_flow_key(packet)  // May also throw - propagates up
}

fn validate_flow(key: FlowKey) -> FlowState {
    var state = lookup_flow_state(key)  // May throw
    if state.is_expired() {
        throw NETWORK_ERROR_RATE_LIMITED  // ✅ OK - propagates to caller (throws 12)
    }
    
    return state
}
```

#### 8.4.3 Userspace Functions

Userspace functions generate **compiler warnings** for uncaught throws, but compilation succeeds. Uncaught throws at runtime terminate the program.

```kernelscript
fn main() -> i32 {
    var prog = load(packet_filter)    // ⚠️ Warning: might throw
    attach(prog, "eth0", 0)           // ⚠️ Warning: might throw
    return 0
    // If any throw occurs, program terminates (like panic)
}

// Better - explicit error handling
fn main() -> i32 {
    try {
        var prog = load(packet_filter)
        attach(prog, "eth0", 0)
        print("Program attached successfully")
        return 0
        
    } catch 20 {  // LOAD_ERROR_PROGRAM_NOT_FOUND
        print("Failed to load program")
        return 1
        
    } catch 30 {  // ATTACH_ERROR_PERMISSION_DENIED
        print("Permission denied - check privileges")
        return 2
    }
}
```

### 8.5 Panic and Assertions

For unrecoverable errors, KernelScript provides panic and assert macros:

```kernelscript
// Panic for unrecoverable errors
fn critical_operation() {
    if (unsafe_condition()) {
        panic("Critical system state violated")
    }
}

// Simple assertions
fn validate_state() {
    assert(map_size < MAX_ENTRIES, "Map overflow detected")
}
```

## 9. User-Space Integration

### 9.1 Command Line Argument Handling

KernelScript provides automatic command line argument parsing for userspace programs. Users can define a custom struct to describe their command line options, and the compiler generates the parsing code using `getopt_long()`.

```kernelscript
// Define command line arguments structure (userspace)
struct Args {
    interface_id: u32,          // --interface_id=<value>
    enable_debug: u32,          // --enable_debug=<0|1>  
    packet_limit: u64,          // --packet_limit=<value>
    timeout_ms: u32,            // --timeout_ms=<value>
}

fn main(args: Args) -> i32 {
    // Arguments automatically parsed from command line
    // Usage: program --interface_id=1 --enable_debug=1 --packet_limit=1000 --timeout_ms=5000
    
    if (args.enable_debug == 1) {
        print("Debug mode enabled for interface: ", args.interface_id)
        print("Packet limit: ", args.packet_limit)
        print("Timeout: ", args.timeout_ms, " ms")
    }
    
    // Use the parsed arguments
    configure_system(args.interface_id, args.packet_limit, args.timeout_ms)
    
    return 0
}

fn configure_system(interface_id: u32, packet_limit: u64, timeout_ms: u32) {
    // Userspace helper function
}

// For programs that don't need command line arguments
fn main() -> i32 {
    print("Simple program with no arguments")
    return 0
}
```

**Automatic Code Generation:**
- Field names are used exactly as command line options: `interface_id` → `--interface_id`
- The compiler generates `getopt_long()` calls with appropriate option parsing
- Type validation ensures only supported primitive types (u8, u16, u32, u64, i8, i16, i32, i64) are used
- Help text is automatically generated based on struct field names

### 9.2 Top-Level Userspace Coordination with Global Maps
```kernelscript
// Global maps (accessible from all programs and userspace)
pin var global_flows : hash<FlowKey, FlowStats>(10000)

pin var global_events : hash<u32, Event>(1024)

pin var global_config : array<ConfigKey, ConfigValue>(64)

// Multiple eBPF programs working together
@xdp fn network_monitor(ctx: *xdp_md) -> xdp_action {
    // Access global maps directly
    var flow_key = extract_flow_key(ctx)
    global_flows[flow_key] += 1
    
    // Use named config for decisions
    if (monitoring.enable_stats) {
        monitoring.packets_processed += 1
    }
    
    // Send event to global stream
    global_events.submit(EVENT_PACKET_PROCESSED { flow_key })
    
    return XDP_PASS
}

@lsm("socket_connect")
fn security_filter(ctx: LsmContext) -> i32 {
    var flow_key = extract_flow_key_from_socket(ctx)
        
    // Check global flow statistics for threat detection — single lookup
    if (var flow_stats = global_flows[flow_key]) {
        if (flow_stats.is_suspicious()) {
            global_events.submit(EVENT_THREAT_DETECTED { flow_key })
            return -EPERM  // Block connection
        }
    }
        
    return 0  // Allow connection
}

struct SystemCoordinator {
    network_monitor: BpfProgram,
    security_filter: BpfProgram,
    
    // Global map access (shared across all programs)
    global_flows: *FlowStatsMap,
    global_events: *EventHash,
    global_config: *ConfigMap,
}

fn new_system_coordinator() -> *SystemCoordinator {
        return SystemCoordinator {
            network_monitor: load(network_monitor),
            security_filter: load(security_filter),
            
            // Global maps are automatically accessible
            global_flows: GlobalMaps::flows(),
            global_events: GlobalMaps::events(),
            global_config: GlobalMaps::config(),
        }
}

fn start_coordinator() -> i32 {
    // Coordinate multiple programs
    var result1 = attach(network_monitor, "eth0", 0)
    var result2 = attach(security_filter, "socket_connect", 0)
    return if (result1 == 0 && result2 == 0) { 0 } else { -1 }
}

fn process_events(coordinator: *SystemCoordinator) {
    // Process events from all programs
    if (var event = coordinator->global_events.read()) {
        if (event.event_type == EVENT_PACKET_PROCESSED) {
            print("Processed packet for flow: ", event.flow_key)
        } else if (event.event_type == EVENT_THREAT_DETECTED) {
            print("THREAT DETECTED: ", event.flow_key)
            handle_threat(coordinator, event.flow_key)
        }
    }
}

fn handle_threat(coordinator: *SystemCoordinator, flow_key: FlowKey) {
    // Coordinated response across all programs
    coordinator->global_config[CONFIG_KEY_THREAT_LEVEL] = CONFIG_VALUE_HIGH
}

struct Args {
    interface_id: u32,
    monitoring_enabled: u32,
}

fn main(args: Args) -> i32 {
    // Command line arguments automatically parsed
    // Usage: program --interface-id=0 --monitoring-enabled=1
    
    var coordinator = new_system_coordinator()
    start_coordinator()
    
    if (args.monitoring_enabled == 1) {
        print("Multi-program eBPF system started on interface: ", args.interface_id)
    }
    
    while (true) {
        process_events(coordinator)
        sleep(100)
    }
    
    return 0
}
```

### 9.3 Cross-Language Bindings
```kernelscript
// Runtime configuration for system behavior
config runtime {
    enable_logging: bool = true,
    verbose_mode: bool = false,
}

program network_monitor : xdp {
    fn main(ctx: *xdp_md) -> xdp_action {
        if (runtime.enable_logging) {
            print("Processing packet")
        }
        return XDP_PASS
    }
}

program flow_analyzer : tc {
    fn main(ctx: *__sk_buff) -> i32 {
        return 0  // TC_ACT_OK
    }
}

// Userspace coordination with cross-language binding support
struct Args {
    interface_id: u32,
    verbose_mode: u32,
    enable_monitoring: u32,
}

fn main(args: Args) -> i32 {
    // Command line arguments automatically parsed
    // Usage: program --interface-id=0 --verbose-mode=1 --enable-monitoring=1
    
    var network_monitor = load(network_monitor)
    var flow_analyzer = load(flow_analyzer)
    
    attach(network_monitor, args.interface_id, 0)
    attach(flow_analyzer, args.interface_id, 1)
    
    // Update runtime config based on command line
    runtime.verbose_mode = (args.verbose_mode == 1)
    
    if (runtime.verbose_mode) {
        print("Multi-program system loaded on interface: ", args.interface_id)
        print("Verbose mode enabled")
    }
    
    // Coordinate both programs
    handle_system_events(args.verbose_mode == 1)
    
    return 0
}

fn handle_system_events(verbose: bool) {
    while (true) {
        // Process events from all programs
        if (runtime.verbose_mode) {
            print("Processing system events...")
        }
        sleep(1000)
    }
}

```

## 10. Memory Management and Safety

### 10.1 Pointer Safety and Bounds Checking

KernelScript employs context-aware pointer safety mechanisms that adapt to the execution environment while maintaining a consistent programming model.

```kernelscript
// eBPF Context - Automatic bounds checking with verifier compliance
@xdp
fn safe_packet_processing(ctx: *xdp_md) -> xdp_action {
    var packet_data: *u8 = ctx->data()
    var packet_end: *u8 = ctx->data_end()
    
    // Compiler automatically generates verifier-compliant bounds checks
    if (packet_data + 20 <= packet_end) {
        var ip_header = packet_data as *IpHeader
        // Safe access - bounds verified by compiler-generated checks
        if (ip_header->version == 4) {
            return process_ipv4_packet(ip_header)
        }
    }
    
    return XDP_DROP
}

// Userspace Context - Traditional pointer safety
fn safe_userspace_access(data: *u8, len: u32) -> u8 {
    // Explicit null and bounds checking
    if (data == null || len == 0) {
        throw INVALID_POINTER_ERROR
    }
    
    return data[0]  // Compiler may insert runtime bounds check
}
```

### 10.2 Dynamic Pointer Integration (Transparent Dynptr)

The compiler transparently uses eBPF's dynamic pointer (dynptr) APIs when beneficial, without exposing complexity to the programmer.

```kernelscript
var event_log : hash<u32, Event>(1024)

@helper
fn transparent_dynptr_usage(event_data: *u8, data_len: u32) {
    // User writes simple pointer code — IfLet binds the *u8 returned by
    // reserve() only inside the truthy branch.
    if (var log_entry = event_log.reserve(data_len + 16)) {
        // Regular pointer operations - compiler uses dynptr API internally
        var header = log_entry as *EventHeader
        header->timestamp = bpf_ktime_get_ns()
        header->data_len = data_len

        // Memory copy using pointer arithmetic
        memory_copy(event_data, log_entry + 16, data_len)

        event_log.submit(log_entry)  // Compiler ensures proper cleanup
    }
}

// What compiler generates (using modern dynptr APIs):
// - bpf_ringbuf_reserve_dynptr() for allocation
// - bpf_dynptr_data() for pointer retrieval
// - bpf_dynptr_write() for ALL field assignments (event->field = value)
// - bpf_ringbuf_submit_dynptr() for submission
// Example: event->id = 42 becomes:
//   { __u32 __tmp_val = 42;
//     bpf_dynptr_write(&event_dynptr, __builtin_offsetof(struct Event, id), &__tmp_val, 4, 0); }
```

### 10.3 Stack Management and Large Struct Handling

```kernelscript
// Context-aware stack management
@helper
fn ebpf_stack_management() {
    var small_struct = SmallData { x: 1, y: 2 }  // 8 bytes - fine
    var medium_struct = MediumData { /* 128 bytes */ }  // ⚠️ Warning
    var large_struct = LargeData { /* 1024 bytes */ }   // ❌ Error in eBPF
    
    // Compiler suggestions:
    process_small(small_struct)      // ✅ Pass by value
    process_medium(&medium_struct)   // ✅ Pass by pointer (recommended)
    // process_large(large_struct)   // ❌ Compilation error
    process_large(&large_struct)     // ✅ Must use pointer
}

// Userspace - relaxed stack rules
fn userspace_stack_management() {
    var large_struct = LargeData { /* 1024 bytes */ }
    process_large(large_struct)      // ✅ Fine in userspace - plenty of stack
}

// Automatic stack tracking for eBPF
@xdp
fn stack_aware_function(ctx: *xdp_md) -> xdp_action {
    var buffer: [u8; 256] = [0; 256]  // Compiler tracks: 256 bytes used
    var header_info = PacketInfo {    // Compiler tracks: +64 bytes
        // ... fields
    }
    
    // If total stack usage > 512 bytes, compiler may:
    // 1. Issue warning about stack pressure
    // 2. Suggest using pointers for large data
    // 3. Automatically spill to map storage (advanced optimization)
    
    return process_packet_data(&buffer, &header_info)
}
```

### 10.4 Memory Lifetime and Resource Management

```kernelscript
// Automatic resource tracking and cleanup
@helper
fn resource_safe_processing(input: *u8, len: u32) -> ProcessResult {
    // Stack-based resource with automatic cleanup
    var work_buffer: [u8; 512] = [0; 512]
    var work_ptr: *u8 = &work_buffer[0]
    
    // Heap-like resource (userspace) or map-backed storage (eBPF)
    var temp_storage: *u8 = allocate_temp_space(len * 2)
    if (temp_storage == null) {
        throw ALLOCATION_ERROR
    }
    
    // Compiler ensures cleanup on all exit paths
    defer {
        deallocate_temp_space(temp_storage)  // Automatic cleanup
    }
    
    // Process data safely
    var result = transform_data(input, len, work_ptr, temp_storage)
    
    return result  // defer ensures cleanup
}

// Map value pointer lifetime tracking
var cache_map : hash<u32, DataCache>(1024)

@helper
fn map_lifetime_safety(key: u32) {
    if (var cache_entry = cache_map[key]) {
        // Compiler tracks that cache_entry is valid here
        cache_entry->access_count += 1
        cache_entry->last_access = bpf_ktime_get_ns()

        // Compiler warns/errors if cache_entry used after invalidating operations
        cache_map[other_key] = other_value  // Invalidates cache_entry

        // ❌ Compiler error: "Use of potentially invalidated map value pointer"
        // cache_entry->access_count += 1
    }
}
```

### 10.5 Null Safety Enforcement

```kernelscript
// Compile-time null safety checks
@helper
fn null_safety_demonstration(maybe_ptr: *PacketData) -> u32 {
    // ❌ Compilation error: "Potential null pointer dereference"
    // return maybe_ptr->packet_count
    
    // ✅ Required null check
    if (maybe_ptr != null) {
        return maybe_ptr->packet_count  // Safe - null check verified
    }
    
    return 0
}

// Optional pointer types for clarity
@helper
fn optional_pointer_example() -> i32 {
    var data_ptr: *u8 = try_get_data()  // May return null
    
    // Compiler enforces null checking
    if (data_ptr != null) {
        var result = process_data(data_ptr)
        return 0
    } else {
        return -1
    }
}
```

### 10.6 Cross-Context Memory Safety

```kernelscript
// Context boundary safety
@xdp 
fn kernel_side_processing(ctx: *xdp_md) -> xdp_action {
    var packet_data = ctx->data()
    
    // Shared memory through maps - safe across contexts
    if (var shared_buffer = shared_map[0]) {
        shared_buffer->kernel_processed_count += 1
        memory_copy(packet_data, shared_buffer->data, min(packet_len, 64))
    }

    return XDP_PASS
}

// Userspace cannot directly access kernel pointers
fn userspace_processing() -> i32 {
    // ❌ Cannot access kernel context pointers directly
    // var packet_data = some_kernel_context.data()  // Compilation error

    // ✅ Access through shared maps
    if (var shared_buffer = shared_map[0]) {
        shared_buffer->userspace_processed_count += 1
        process_shared_data(shared_buffer->data)
    }

    return 0
}
```

## 11. Compilation and Build System

### 11.1 Deployment Configuration (deploy.yaml)
```yaml
# Deployment configuration for KernelScript programs
apiVersion: kernelscript.dev/v1
kind: ProgramDeployment
metadata:
  name: network-monitoring
spec:
  programs:
    - name: packet_counter
      type: xdp
      attach:
        interfaces: ["eth0", "eth1"]
        mode: "native"  # or "generic"
      
    - name: security_monitor
      type: lsm
      attach:
        hooks: ["socket_connect"]
        
    - name: perf_tracer
      type: kprobe
      attach:
        functions: 
          - "sys_read"
          - "sys_write"
        auto_attach: true
        
  global_maps:
    pin_path: "/sys/fs/bpf/monitoring/"
    cleanup_on_exit: true
    
  userspace:
    auto_start: true
    restart_policy: "always"
```

### 11.3 Build Commands
```bash
# Compile KernelScript to eBPF bytecode
kernelscript build

# Run tests
kernelscript test

# Deploy using configuration
kernelscript deploy --config=deploy.yaml

# Manual attachment (if auto_attach=false)
kernelscript attach perf_monitor --function=sys_read
```

## 12. Testing Framework

KernelScript provides a built-in testing framework that allows developers to write unit tests for their eBPF programs. The testing framework includes the `@test` attribute for marking test functions and the `test()` builtin function for running eBPF programs in a controlled test environment.

### 12.1 Test Functions with @test Attribute

Functions marked with the `@test` attribute are considered test functions and are compiled differently when using the `--test` compilation mode. Test functions can use the `test()` builtin to trigger eBPF program execution in a controlled test environment.

```kernelscript
// Simple packet filter to test
@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    var packet_size = ctx->data_end - ctx->data
    if (packet_size > 1000) {
        return XDP_DROP
    }
    return XDP_PASS
}

// Test function using @test attribute
@test
fn test_packet_filter() -> i32 {
    // Create test context
    var test_ctx = XdpTestContext {
        packet_size: 500,
        interface_id: 1,
        expected_action: 2,  // XDP_PASS
    }
    
    // Use test() builtin to run the eBPF program
    var result = test(packet_filter, test_ctx)
    
    if (result == 2) {  // XDP_PASS
        print("Test passed")
        return 0
    } else {
        print("Test failed: expected %d, got %d", 2, result)
        return 1
    }
}
```

### 12.2 Test Compilation Mode

KernelScript supports a special `--test` compilation mode that generates test-specific userspace code instead of eBPF programs. This mode allows running unit tests in a controlled userspace environment.

**Compilation Modes:**

```bash
# Regular compilation - generates eBPF programs and userspace code
kernelscript compile program.ks

# Test compilation - generates test userspace code too
kernelscript compile --test program.ks
```

**Test Mode Behavior:**

1. **Only @test functions are compiled**: Regular eBPF programs are excluded from test builds
2. **Userspace test executable**: Generates `program.test.c` instead of `program.c` and `program.ebpf.c`
3. **Simple Makefile**: Generates basic Makefile with `test` and `run-test` targets
4. **Mock environment**: Provides mock implementations of eBPF-specific functions for testing

**Generated Makefile in Test Mode:**

```makefile
# Auto-generated Makefile for test compilation
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -g

PROGRAM_NAME = program
TEST_TARGET = $(PROGRAM_NAME).test

.PHONY: test run-test clean

test: $(TEST_TARGET)

run-test: $(TEST_TARGET)
	./$(TEST_TARGET)

$(TEST_TARGET): $(PROGRAM_NAME).test.c
	$(CC) $(CFLAGS) -o $@ $<

clean:
	rm -f $(TEST_TARGET)
```

### 12.3 Access Control Restrictions

The `test()` builtin function is **only** available to functions marked with the `@test` attribute. Attempting to call `test()` from regular functions, helper functions, or eBPF program functions will result in a compilation error.

```kernelscript
// ✅ Valid - test() call from @test function
@test
fn test_packet_behavior() -> i32 {
    var result = test(packet_filter, test_ctx)  // This is allowed
    return if (result == 2) { 0 } else { 1 }
}

// ❌ Compilation Error - test() call from regular function
fn regular_function() -> i32 {
    var result = test(packet_filter, test_ctx)  // ERROR!
    return 0
}

// ❌ Compilation Error - test() call from helper function
@helper
fn helper_function() -> i32 {
    var result = test(packet_filter, test_ctx)  // ERROR!
    return 0
}

// ❌ Compilation Error - test() call from eBPF program function
@xdp
fn packet_filter(ctx: *xdp_md) -> xdp_action {
    var result = test(packet_filter, test_ctx)  // ERROR!
    return XDP_PASS
}
```

This restriction ensures that testing code is clearly separated from production code and prevents accidental inclusion of test runner calls in production eBPF programs.

### 12.4 Testing Best Practices

**Organize Tests by Functionality:**
```kernelscript
@test
fn test_small_packets() -> i32 {
    var test_ctx = XdpTestContext { packet_size: 64, interface_id: 1, expected_action: 2 }
    var result = test(packet_filter, test_ctx)
    return if (result == 2) { 0 } else { 1 }
}

@test
fn test_large_packets() -> i32 {
    var test_ctx = XdpTestContext { packet_size: 1500, interface_id: 1, expected_action: 1 }
    var result = test(packet_filter, test_ctx)
    return if (result == 1) { 0 } else { 1 }
}
```

**Use Descriptive Test Names:**
```kernelscript
@test
fn test_rate_limiter_blocks_excessive_traffic() -> i32 {
    var test_ctx = XdpTestContext { packet_size: 100, interface_id: 1, expected_action: 1 }
    var result = test(rate_limiting_filter, test_ctx)
    return if (result == 1) { 0 } else { 1 }
}
```

**Test Edge Cases:**
```kernelscript
@test
fn test_zero_length_packet() -> i32 {
    var test_ctx = XdpTestContext { packet_size: 0, interface_id: 1, expected_action: 1 }
    var result = test(packet_validator, test_ctx)
    return if (result == 1) { 0 } else { 1 }
}
```

## 13. Complete Formal Grammar (EBNF)

```ebnf
(* KernelScript Complete Grammar *)

(* Top-level structure *)
kernelscript_file = { global_declaration } 

global_declaration = config_declaration | map_declaration | type_declaration | 
                    function_declaration | struct_declaration | impl_declaration |
                    global_variable_declaration | bindings_declaration | import_declaration |
                    extern_declaration 

(* Map declarations - global scope *)
map_declaration = [ "pin" ] [ "@flags" "(" flag_expression ")" ] "var" identifier ":" map_type "<" key_type "," value_type ">" "(" map_config ")"

map_type = "hash" | "array" | "percpu_hash" | "percpu_array" | "lru_hash" 

map_config = integer_literal [ "," map_config_item { "," map_config_item } ] 
map_config_item = identifier "=" literal 

flag_expression = identifier | ( identifier { "|" identifier } ) 

(* eBPF program function attributes *)
attribute_list = attribute { attribute }
attribute = "@" attribute_name [ "(" attribute_args ")" ]
attribute_name = "xdp" | "tc" | "kprobe" | "tracepoint" |
                 "struct_ops" | "kfunc" | "helper" | "private" | "test"
attribute_args = string_literal | identifier 

(* Named configuration declarations *)
config_declaration = "config" identifier "{" { config_field } "}" 
config_field = identifier ":" type_annotation [ "=" expression ] ","

(* Global variable declarations *)
global_variable_declaration = [ "pin" ] [ "local" ] "var" identifier [ ":" type_annotation ] [ "=" expression ]

(* Pinning restrictions:
   - "pin local var" is a compilation error - local variables cannot be pinned
   - Only shared variables (without "local") can be pinned
   - Pinned variables are automatically shared between kernel and userspace
   - Compiler generates a struct containing all pinned variables and uses a single-entry map
*) 

(* Scoping rules for KernelScript:
   - Attributed functions (e.g., @xdp, @tc, @tracepoint): Kernel space (eBPF) - compiles to eBPF bytecode
   - Regular functions: User space - compiles to native executable  
   - Maps, global configs, and global variables: Shared between both kernel and user space
   
   Userspace main function can have two forms:
   1. fn main() -> i32 { ... }                    // No command line arguments
   2. fn main(args: CustomStruct) -> i32 { ... }  // Custom argument struct, automatically parsed from command line
*)



(* Type declarations *)
type_declaration = "type" identifier "=" type_definition 
type_definition = struct_type | enum_type | type_alias 

struct_type = "struct" identifier "{" { struct_field } "}" 
struct_field = identifier ":" type_annotation "," 

enum_type = "enum" identifier "{" enum_variant { "," enum_variant } [ "," ] "}" 
enum_variant = identifier [ "=" integer_literal ] 

type_alias = type_annotation 

(* Function declarations *)
function_declaration = [ attribute_list ] [ visibility ] [ "kernel" ] "fn" identifier "(" parameter_list ")" 
                       [ return_type_spec ] "{" statement_list "}"

(* Return type specification - supports both unnamed and named return values *)
return_type_spec = "->" type_annotation                        (* Unnamed: fn() -> u64 *)
                 | "->" identifier ":" type_annotation          (* Named: fn() -> result: u64 *)

impl_declaration = [ attribute_list ] "impl" identifier "{" impl_body "}"
impl_body = { impl_function }
impl_function = "fn" identifier "(" parameter_list ")" [ return_type_spec ] "{" statement_list "}" 

visibility = "pub" | "priv" 
parameter_list = [ parameter { "," parameter } ] 
parameter = identifier ":" type_annotation 

(* Statements *)
statement_list = { statement } 
statement = expression_statement | assignment_statement | declaration_statement |
            if_statement | for_statement | while_statement | return_statement |
            break_statement | continue_statement | block_statement | delete_statement |
            try_statement | throw_statement | defer_statement 

expression_statement = expression 

assignment_statement   = simple_assignment | compound_assignment | field_assignment |
                         arrow_assignment  | index_assignment    | compound_index_assignment |
                         compound_field_index_assignment 

simple_assignment              = identifier "=" expression                              (* x = e *)
compound_assignment            = identifier compound_operator expression                (* x op= e *)
field_assignment               = primary_expression "." identifier "=" expression       (* o.field = e *)
arrow_assignment               = primary_expression "->" identifier "=" expression      (* p->field = e *)
index_assignment               = expression "[" expression "]" "=" expression           (* m[k] = e *)
compound_index_assignment      = expression "[" expression "]" compound_operator expression
                                                                                         (* m[k] op= e:
                                                                                            scalar map values; reads, applies op, writes back;
                                                                                            absent entries read as 0, so the form creates an
                                                                                            entry on first use. See §6.2.5.1. *)
compound_field_index_assignment = identifier "[" expression "]" "." identifier compound_operator expression
                                                                                         (* m[k].field op= e:
                                                                                            struct-valued map; lowers to a single
                                                                                            bpf_map_lookup_elem + null-checked
                                                                                            ptr->field op= e; absent entries are a no-op
                                                                                            (no entry is created). See §6.2.5.2. *)

assignment_operator = "=" | compound_operator
compound_operator   = "+=" | "-=" | "*=" | "/=" | "%=" 

declaration_statement = "var" identifier [ ":" type_annotation ] "=" expression 

if_statement = expression_if | iflet_if 

expression_if = "if" "(" expression ")" "{" statement_list "}" 
                { "else" "if" "(" expression ")" "{" statement_list "}" }
                [ "else" "{" statement_list "}" ]

iflet_if = "if" "(" "var" identifier "=" expression ")" "{" statement_list "}"
           [ "else" ( "{" statement_list "}" | iflet_if | expression_if ) ]
           (* Declaration-as-condition: the right-hand side is evaluated once;
              the then-branch is taken iff the value is *present* (a map hit
              or a non-null pointer). `identifier` is bound only inside the
              then-branch. For map-index right-hand sides the binding is the
              lookup pointer (field access auto-derefs, field writes mutate
              the underlying entry in place). See §7.5.1.2. *) 

for_statement = "for" "(" identifier "in" expression ".." expression ")" "{" statement_list "}" |
                "for" "(" identifier "," identifier ")" "in" expression "{" statement_list "}" 

while_statement = "while" "(" expression ")" "{" statement_list "}" 

return_statement = "return" [ expression ] 
break_statement = "break" 
continue_statement = "continue" 
delete_statement = "delete" primary_expression "[" expression "]" 
block_statement = "{" statement_list "}" 

(* Error handling and resource management statements *)
try_statement = "try" "{" statement_list "}" { catch_clause } 
catch_clause = "catch" ( integer_literal | "_" ) "{" statement_list "}" 

throw_statement = "throw" expression 

defer_statement = "defer" expression 

(* Expressions *)
expression = logical_or_expression 

logical_or_expression = logical_and_expression { "||" logical_and_expression } 
logical_and_expression = equality_expression { "&&" equality_expression } 
equality_expression = relational_expression { equality_operator relational_expression } 
equality_operator = "==" | "!=" 

relational_expression = additive_expression { relational_operator additive_expression } 
relational_operator = "<" | "<=" | ">" | ">=" 

additive_expression = multiplicative_expression { additive_operator multiplicative_expression } 
additive_operator = "+" | "-" 

multiplicative_expression = unary_expression { multiplicative_operator unary_expression } 
multiplicative_operator = "*" | "/" | "%" 

unary_expression = [ unary_operator ] primary_expression 
unary_operator = "!" | "-" | "*" | "&" 

(* Pointer operations:
   * "*" = dereference operator (access value through pointer)
   * "&" = address-of operator (take address of value)
   * "->" = arrow operator for struct field access through pointer (in field_access)
*)

primary_expression = config_access | identifier | literal | function_call | field_access | 
                     array_access | parenthesized_expression | struct_literal | match_expression 

config_access = identifier "." identifier 

function_call = identifier "(" argument_list ")" 
argument_list = [ expression { "," expression } ] 

field_access = primary_expression ("." identifier | "->" identifier)
array_access = primary_expression "[" expression "]" 
parenthesized_expression = "(" expression ")" 

struct_literal = identifier "{" struct_literal_field { "," struct_literal_field } [ "," ] "}" 
struct_literal_field = identifier ":" expression 

match_expression = "match" "(" expression ")" "{" match_arm { "," match_arm } [ "," ] "}"
match_arm = match_pattern ":" expression
match_pattern = integer_literal | identifier | "default" 

(* Type annotations *)
type_annotation = primitive_type | compound_type | identifier 

primitive_type = "u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64" | 
                 "bool" | "char" | "void" | "ProgramRef" | string_type 

compound_type = array_type | pointer_type | function_type 

string_type = "str" "(" integer_literal ")" 

array_type = "[" type_annotation "" integer_literal "]" 
pointer_type = "*" type_annotation 
function_type = "fn" "(" [ type_annotation { "," type_annotation } ] ")" [ return_type_spec ] 

(* Literals *)
literal = integer_literal | string_literal | char_literal | boolean_literal | 
          array_literal | null_literal 

integer_literal = decimal_literal | hex_literal | octal_literal | binary_literal 
decimal_literal = digit { digit } 
hex_literal = "0x" hex_digit { hex_digit } 
octal_literal = "0o" octal_digit { octal_digit } 
binary_literal = "0b" binary_digit { binary_digit } 

string_literal = '"' { string_char } '"' 
char_literal = "'" char "'" 
boolean_literal = "true" | "false" 
array_literal = "[" [ expression { "," expression } ] "]" 
null_literal = "null" 

(* Import declarations - unified syntax for KernelScript and external languages *)
import_declaration = "import" identifier "from" string_literal 

(* External kernel function declarations - for importing existing kernel kfuncs *)
extern_declaration = "extern" identifier "(" parameter_list ")" [ "->" type_annotation ]

(* Include declarations - for KernelScript headers (.kh files) *)
include_declaration = "include" string_literal

(* Examples:
   import utils from "./common/utils.ks"          // KernelScript import
   import ml_analysis from "./ml/threat.py"       // Python import (userspace only)
   
   extern bpf_ktime_get_ns() -> u64               // Import existing kernel kfunc
   extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32  // Import with parameters
   
   include "common_kfuncs.kh"                    // Include header with extern declarations
   include "types/networking.kh"                 // Include header with type definitions
   
   Import behavior is determined by file extension:
   - .ks files: Import KernelScript symbols (functions, types, maps, configs)  
   - .py files: Import Python functions with automatic FFI bridging (userspace only)
   - .kh files: Include headers with declarations only (flattened into global namespace)
*) 

(* Identifiers and basic tokens *)
identifier = letter { letter | digit | "_" } 
letter = "a"..."z" | "A"..."Z" 
digit = "0"..."9" 
hex_digit = digit | "a"..."f" | "A"..."F" 
octal_digit = "0"..."7" 
binary_digit = "0" | "1" 

(* String and character content *)
string_char = any_char_except_quote_and_backslash | escape_sequence 
char = any_char_except_quote_and_backslash | escape_sequence 
escape_sequence = "\" ( "n" | "t" | "r" | "\" | "'" | '"' | "0" | "x" hex_digit hex_digit ) 

(* Comments *)
comment = line_comment 
line_comment = "//" { any_char_except_newline } newline 

(* Whitespace *)
whitespace = " " | "\t" | "\n" | "\r" 
```

### Grammar Hierarchy Explanation:

**Top Level:**
- `kernelscript_file` contains global declarations
- Global maps, types, configs, and functions (both kernel and userspace)

**Function Structure:**
- `function_declaration` defines functions with optional attributes
- Functions with attributes (e.g., `@xdp`, `@tc`, `@tracepoint`) are eBPF programs
- Functions without attributes are userspace functions
- `@helper` functions are shared across all eBPF programs

**Scoping Rules:**
- **Global scope**: Maps, types, configs, and all function declarations
- **Function scope**: Variables and parameters within functions
- **Kernel scope**: `@helper` functions accessible to all eBPF programs
- **Userspace scope**: Regular functions (no attributes, no `kernel` qualifier)

This specification provides a comprehensive foundation for KernelScript while addressing the concerns about template complexity and userspace integration. The simplified type system avoids complex template metaprograming while still providing safety, and the top-level userspace section enables seamless coordination of multiple eBPF programs with centralized control plane management.


================================================
FILE: dune-project
================================================
(lang dune 2.9)

(name kernelscript)

(use_standard_c_and_cxx_flags true)

(package
 (name kernelscript)
 (authors "Cong Wang")
 (maintainers "Cong Wang <cwang@multikernel.io>")
 (license Apache-2.0)
 (synopsis "A modern programming language for eBPF development")
 (depends
  ocaml
  dune
  menhir
  alcotest
  str
  unix))

(using menhir 2.0) 

================================================
FILE: examples/basic_match.ks
================================================
// Basic Match Construct Demo for KernelScript
// Demonstrates packet matching with the new match construct

include "xdp.kh"

// Protocol constants
enum IpProtocol {
    ICMP = 1,
    TCP = 6,
    UDP = 17
}

// Helper functions for packet processing (declared first)
@helper
fn get_ip_protocol(ctx: *xdp_md) -> u32 {
    // In a real implementation, this would extract the protocol field
    // from the IP header. For demo purposes, we return TCP.
    return 6 // IPPROTO_TCP
}

@helper  
fn get_tcp_dest_port(ctx: *xdp_md) -> u32 {
    // In a real implementation, this would extract the destination port
    // from the TCP header. For demo purposes, we return HTTP.
    return 80 // HTTP port
}

@helper
fn get_udp_dest_port(ctx: *xdp_md) -> u32 {
    // In a real implementation, this would extract the destination port
    // from the UDP header. For demo purposes, we return DNS.
    return 53 // DNS port
}

// Specialized TCP port-based classifier (tail-callable)
@xdp
fn tcp_port_classifier(ctx: *xdp_md) -> xdp_action {
    var port = get_tcp_dest_port(ctx)
    
    return match (port) {
        80: XDP_PASS,       // Allow HTTP
        443: XDP_PASS,      // Allow HTTPS  
        22: XDP_PASS,       // Allow SSH
        21: XDP_DROP,       // Block FTP for security
        23: XDP_DROP,       // Block Telnet (insecure)
        default: XDP_PASS   // Allow other TCP ports by default
    }
}

// Specialized UDP port-based classifier (tail-callable)
@xdp  
fn udp_port_classifier(ctx: *xdp_md) -> xdp_action {
    var port = get_udp_dest_port(ctx)
    
    return match (port) {
        53: XDP_PASS,       // Allow DNS
        123: XDP_PASS,      // Allow NTP
        161: XDP_DROP,      // Block SNMP (security risk)
        69: XDP_DROP,       // Block TFTP (insecure)
        default: XDP_PASS   // Allow other UDP ports by default
    }
}

// Main packet classifier using match construct with tail call delegation
@xdp
fn packet_classifier(ctx: *xdp_md) -> xdp_action {
    var protocol = get_ip_protocol(ctx)
    
    // Match construct provides clean protocol-based delegation
    return match (protocol) {
        TCP: tcp_port_classifier(ctx),    // Tail call to TCP specialist 
        UDP: udp_port_classifier(ctx),    // Tail call to UDP specialist
        ICMP: XDP_DROP,                   // Drop ICMP for security  
        default: XDP_ABORTED              // Abort unknown protocols
    }
}

fn main() -> i32 {
    var prog = load(packet_classifier)
    attach(prog, "lo", 0)
    
    print("Packet classifier attached to loopback interface")
    print("Processing packets with pattern matching...")
    
    // In a real application, the program would run here
    // For demonstration, we detach after showing the lifecycle
    detach(prog)
    print("Packet classifier detached")
    
    return 0
}

 

================================================
FILE: examples/break_continue_unbound.ks
================================================
// Example demonstrating break and continue in truly unbound loops
// This should force bpf_loop() usage

include "xdp.kh"

var counter_map : hash<u32, u32>(10)

@xdp fn packet_filter(ctx: *xdp_md) -> xdp_action {
  var end_value = 1000 // Large value to make it unbound
  
  // This should be treated as unbound due to large range
  for (i in 0..end_value) {
    // Skip even numbers
    if (i % 2 == 0) {
      continue
    }
    
    // Stop processing at threshold
    if (i > 50) {
      break
    }
    
    // Count odd numbers up to threshold
    var key = 0
    var current = counter_map[key]
    counter_map[key] = current + 1
  }
  
  return XDP_PASS
}

// Userspace coordination (no wrapper)
fn main() -> i32 {
  var limit = 1000 // Runtime-determined limit
  var count = 0
  
  // This should also be unbound
  for (i in 0..limit) {
    if (i % 2 == 0) {
      continue
    }
    
    if (i > 50) {
      break
    }
    
    count = count + 1
  }
  
  var prog = load(packet_filter)
  attach(prog, "lo", 0)
  
  print("Break/continue demo program attached to loopback")
  print("Demonstrating break and continue functionality...")
  
  // Show break/continue working
  detach(prog)
  print("Break/continue demo program detached")
  
  return 0
} 

================================================
FILE: examples/common_kfuncs.kh
================================================
// Common kernel function declarations
extern bpf_ktime_get_ns() -> u64
extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32
extern bpf_get_current_pid_tgid() -> u64

// Common type definitions
type Timestamp = u64
type ProcessId = u32


================================================
FILE: examples/dynptr.ks
================================================
// Dynptr showcase - compiler should transparently use dynptr APIs for packet access
// Example to demonstrate bpf_dynptr_from_mem usage
// This would be for accessing memory buffers, not packet data

include "xdp.kh"

struct DataBuffer {
    data: u8[32],
    size: u32
}

var buffer_map : hash<u32, DataBuffer>(1024)

@helper
fn process_map_data(buffer_ptr: *DataBuffer) -> u32 {
    // This should use bpf_dynptr_from_mem for map value access!
    var size_value = buffer_ptr->size  // Map data field access
    return size_value
}

@xdp  
  fn test(ctx: *xdp_md) -> xdp_action {
    // Packet data access - should use bpf_dynptr_from_xdp
    var packet_byte = *ctx->data
    
    // Map lookup - this gives us a pointer to map value
    var key = 1
    var buffer_value = buffer_map[key]  // Get map value
    
    if (buffer_value.size > 0) {
        // Pass address of the struct to demonstrate map data pointer access
        var buffer_ptr = &buffer_value
        var map_size = process_map_data(buffer_ptr)
        
        if (packet_byte > 0 || map_size > 0) {
            return XDP_PASS
        }
    }
    
    return XDP_DROP
}

================================================
FILE: examples/error_handling_demo.ks
================================================
// Minimal error handling demo
include "xdp.kh"

var counters : hash<u32, u64>(1024)

@xdp fn error_demo(ctx: *xdp_md) -> xdp_action {
    var key = 42
    
    try {
        // Try to get value from map
        var value = counters[key]
        if (value == 0) {
            throw 1  // Key not found
        }
        return 2  // XDP_PASS
        
    } catch 1 {
        // Handle missing key by initializing it
        counters[key] = 100
        return 1  // XDP_DROP
    }
}

fn main() -> i32 {
    try {
        // Simulate some operation that might fail
        var result = 42
        if (result > 40) {
            throw 2  // Throw error code 2
        }
        return 0  // Success
        
    } catch 2 {
        // Handle the error
        return 1  // Return error code 1
    }
} 

================================================
FILE: examples/extern_kfunc_demo.ks
================================================
include "xdp.kh"

// External kfunc declarations - these would typically be imported from kernel BTF
extern bpf_ktime_get_ns() -> u64
extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32
extern bpf_get_current_pid_tgid() -> u64

// XDP program that uses external kfuncs
@xdp
fn packet_tracer(ctx: *xdp_md) -> xdp_action {
    // Get current timestamp using external kfunc
    var timestamp = bpf_ktime_get_ns()
    
    // Get current process ID using external kfunc
    var pid_tgid = bpf_get_current_pid_tgid()
    
    // Print debug information (this would need proper string handling in real implementation)
    var result = bpf_trace_printk(null, 0)
    
    // Always pass packets through
    return 2  // XDP_PASS
}

fn main() -> i32 {
    return 0
}

================================================
FILE: examples/functions.ks
================================================
include "xdp.kh"

type IpAddress = u32

@helper
fn helper_function(value: u32) -> u32 {
  return value + 10
}

@helper
fn another_helper() -> u32 {
  return 42
}

@xdp fn test_functions(ctx: *xdp_md) -> xdp_action {
  var result = helper_function(5)
  var const_val = another_helper()
  return XDP_PASS
}

fn global_function(x: u32) -> u32 {
  return x * 2
}

fn add_numbers(a: i32, b: i32) -> i32 {
  return a + b
}

fn multiply_numbers(a: i32, b: i32) -> i32 {
  return a * b
}

fn subtract_numbers(a: i32, b: i32) -> i32 {
  return a - b
}

fn process_with_callback(x: i32, y: i32, callback: fn(i32, i32) -> i32) -> i32 {
  return callback(x, y)
}

// Function pointer type declaration
type BinaryOp = fn(i32, i32) -> i32

fn main() -> i32 {
  var result = global_function(21)
  
  // Assign functions to function pointers
  var add_op: BinaryOp = add_numbers
  var mul_op: BinaryOp = multiply_numbers
  var sub_op: BinaryOp = subtract_numbers
  
  // Call functions through function pointers
  var sum = add_op(10, 20)            // Result: 30
  var product = mul_op(5, 6)          // Result: 30
  var difference = sub_op(15, 7)      // Result: 8
  
  // Higher-order function with function pointer parameter
  var callback_result = process_with_callback(4, 7, add_numbers)      // Result: 11
  var callback_result2 = process_with_callback(4, 7, multiply_numbers) // Result: 28
  
  return 0
} 

================================================
FILE: examples/import/network_utils.py
================================================
"""
Simple network utilities for KernelScript import testing
"""

def calculate_bandwidth(packets_per_second, avg_packet_size=1500):
    """Calculate bandwidth in bytes per second"""
    return packets_per_second * avg_packet_size

def is_rate_limited(current_rate, max_rate=1000000):
    """Check if current rate exceeds maximum allowed rate"""
    return current_rate > max_rate

def get_default_mtu():
    """Get default MTU size"""
    return 1500

def format_packet_count(count):
    """Format packet count for display"""
    if count > 1000000:
        return f"{count / 1000000:.1f}M packets"
    elif count > 1000:
        return f"{count / 1000:.1f}K packets"
    else:
        return f"{count} packets"

# Configuration constants
MAX_PACKET_SIZE = 9000
DEFAULT_TIMEOUT = 30 

================================================
FILE: examples/import/simple_utils.ks
================================================
// Simple utilities for import testing

fn validate_config() -> bool {
    return true
}

fn get_status() -> u32 {
    return 42
} 

================================================
FILE: examples/import_demo.ks
================================================
// Working demo of unified import syntax

// Import KernelScript module (compiled to .so)
import utils from "./import/simple_utils.ks"

// Import Python module (uses Python bridge)
import network_utils from "./import/network_utils.py"

include "xdp.kh"

config network {
    enable_filtering: bool = false,
    status_code: u32 = 0,
    packet_count: u32 = 5000,
}

@xdp 
fn intelligent_filter(ct
Download .txt
gitextract_4pa0mdxk/

├── .github/
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── BUILTINS.md
├── LICENSE
├── README.md
├── SPEC.md
├── dune-project
├── examples/
│   ├── basic_match.ks
│   ├── break_continue_unbound.ks
│   ├── common_kfuncs.kh
│   ├── dynptr.ks
│   ├── error_handling_demo.ks
│   ├── extern_kfunc_demo.ks
│   ├── functions.ks
│   ├── import/
│   │   ├── network_utils.py
│   │   └── simple_utils.ks
│   ├── import_demo.ks
│   ├── include_demo.ks
│   ├── local_global_vars.ks
│   ├── map_operations_demo.ks
│   ├── maps_demo.ks
│   ├── multi_programs.ks
│   ├── named_return.ks
│   ├── object_allocation.ks
│   ├── packet_filter.ks
│   ├── packet_matching.ks
│   ├── pattern_test.ks
│   ├── pointer_simple.ks
│   ├── print_demo.ks
│   ├── private_kfunc.ks
│   ├── probe.kh
│   ├── probe_do_exit.ks
│   ├── python_demo.py
│   ├── rate_limiter.ks
│   ├── ringbuf_demo.ks
│   ├── ringbuf_on_event_demo.ks
│   ├── safety_demo.ks
│   ├── sched_ext_ops.kh
│   ├── sched_ext_simple.ks
│   ├── simple_gfp_test.ks
│   ├── simple_program_lifecycle.ks
│   ├── string_test.ks
│   ├── struct_ops_simple.ks
│   ├── symbols.ks
│   ├── tail_call.ks
│   ├── tc.kh
│   ├── tcp_congestion_ops.kh
│   ├── test_config.ks
│   ├── test_error_handling.ks
│   ├── test_exec.ks
│   ├── test_functions.ks
│   ├── tracepoint.kh
│   ├── tracepoint_sched_switch.ks
│   ├── type_alias.ks
│   ├── type_checking.ks
│   ├── types_demo.ks
│   ├── userspace_example.ks
│   ├── xdp.kh
│   └── xdp_kfuncs.kh
├── kernelscript.opam
├── src/
│   ├── ast.ml
│   ├── btf_binary_parser.ml
│   ├── btf_binary_parser.mli
│   ├── btf_parser.ml
│   ├── btf_parser.mli
│   ├── btf_stubs.c
│   ├── codegen_common.ml
│   ├── context/
│   │   ├── context_codegen.ml
│   │   ├── context_codegen.mli
│   │   ├── dune
│   │   ├── fprobe_codegen.ml
│   │   ├── kprobe_codegen.ml
│   │   ├── tc_codegen.ml
│   │   ├── tracepoint_codegen.ml
│   │   └── xdp_codegen.ml
│   ├── dune
│   ├── dynptr_bridge.ml
│   ├── ebpf_c_codegen.ml
│   ├── evaluator.ml
│   ├── import_resolver.ml
│   ├── include_resolver.ml
│   ├── ir.ml
│   ├── ir_analysis.ml
│   ├── ir_function_system.ml
│   ├── ir_generator.ml
│   ├── kernel_module_codegen.ml
│   ├── kernel_module_codegen.mli
│   ├── kernelscript_bridge.ml
│   ├── lexer.mll
│   ├── loop_analysis.ml
│   ├── main.ml
│   ├── map_assignment.ml
│   ├── map_operations.ml
│   ├── maps.ml
│   ├── multi_program_analyzer.ml
│   ├── multi_program_ir_optimizer.ml
│   ├── parse.ml
│   ├── parser.mly
│   ├── python_bridge.ml
│   ├── safety_checker.ml
│   ├── stdlib.ml
│   ├── struct_ops_registry.ml
│   ├── struct_ops_registry.mli
│   ├── symbol_table.ml
│   ├── tail_call_analyzer.ml
│   ├── test_codegen.ml
│   ├── type_checker.ml
│   └── userspace_codegen.ml
└── tests/
    ├── dune
    ├── test_address_of_user_types.ml
    ├── test_all_examples.sh
    ├── test_array_init.ml
    ├── test_array_literals.ml
    ├── test_ast.ml
    ├── test_bpf_loop_callbacks.ml
    ├── test_break_continue.ml
    ├── test_btf_binary_parser.ml
    ├── test_comment_positions.ml
    ├── test_compound_index_assignment.ml
    ├── test_config.ml
    ├── test_config_struct_generation.ml
    ├── test_config_validation.ml
    ├── test_const_variables.ml
    ├── test_context_field_types.ml
    ├── test_definition_order.ml
    ├── test_detach_api.ml
    ├── test_dynptr_bridge.ml
    ├── test_ebpf_c_codegen.ml
    ├── test_ebpf_string_generation.ml
    ├── test_enum.ml
    ├── test_error_handling.ml
    ├── test_evaluator.ml
    ├── test_exec.ml
    ├── test_extern.ml
    ├── test_for_statements.ml
    ├── test_function_generation.ml
    ├── test_function_pointers.ml
    ├── test_function_scope.ml
    ├── test_function_validation.ml
    ├── test_global_var.ml
    ├── test_global_var_ordering.ml
    ├── test_iflet.ml
    ├── test_import_system.ml
    ├── test_include.ml
    ├── test_integer_literal.ml
    ├── test_ir.ml
    ├── test_ir_analysis.ml
    ├── test_ir_function_system.ml
    ├── test_ir_patterns.ml
    ├── test_kfunc_attribute.ml
    ├── test_lexer.ml
    ├── test_map_assignment.ml
    ├── test_map_flags.ml
    ├── test_map_integration.ml
    ├── test_map_operations.ml
    ├── test_map_syntax.ml
    ├── test_maps.ml
    ├── test_match.ml
    ├── test_named_returns.ml
    ├── test_nested_if_codegen.ml
    ├── test_object_allocation.ml
    ├── test_parser.ml
    ├── test_pinned_globals.ml
    ├── test_pointer_syntax.ml
    ├── test_private_attribute.ml
    ├── test_probe.ml
    ├── test_program_ref.ml
    ├── test_return_path_analysis.ml
    ├── test_return_value_propagation.ml
    ├── test_ringbuf.ml
    ├── test_safety_checker.ml
    ├── test_stdlib.ml
    ├── test_string_codegen.ml
    ├── test_string_literal_bugs.ml
    ├── test_string_struct_fixes.ml
    ├── test_string_to_array_unification.ml
    ├── test_string_type.ml
    ├── test_struct_field_access.ml
    ├── test_struct_initialization.ml
    ├── test_struct_ops.ml
    ├── test_symbol_table.ml
    ├── test_tail_call.ml
    ├── test_tc.ml
    ├── test_test_attribute.ml
    ├── test_tracepoint.ml
    ├── test_truthy_falsy.ml
    ├── test_type_alias.ml
    ├── test_type_checker.ml
    ├── test_userspace.ml
    ├── test_userspace_for_codegen.ml
    ├── test_userspace_maps.ml
    ├── test_userspace_skeleton_header.ml
    ├── test_userspace_statements.ml
    ├── test_userspace_struct_flexibility.ml
    ├── test_utils.ml
    └── test_void_functions.ml
Download .txt
SYMBOL INDEX (32 symbols across 3 files)

FILE: examples/import/network_utils.py
  function calculate_bandwidth (line 5) | def calculate_bandwidth(packets_per_second, avg_packet_size=1500):
  function is_rate_limited (line 9) | def is_rate_limited(current_rate, max_rate=1000000):
  function get_default_mtu (line 13) | def get_default_mtu():
  function format_packet_count (line 17) | def format_packet_count(count):

FILE: examples/python_demo.py
  function main (line 21) | def main():

FILE: src/btf_stubs.c
  function value (line 30) | value btf_kind_struct_stub(value unit) {
  function value (line 35) | value btf_kind_union_stub(value unit) {
  function value (line 40) | value btf_kind_enum_stub(value unit) {
  function value (line 45) | value btf_kind_enum64_stub(value unit) {
  function btf_handle_finalize (line 69) | static void btf_handle_finalize(value v) {
  type custom_operations (line 77) | struct custom_operations
  type btf (line 87) | struct btf
  type btf (line 88) | struct btf
  function value (line 92) | static inline value value_of_btf(struct btf *btf) {
  function value (line 99) | value btf_new_from_file_stub(value path) {
  function value (line 127) | value btf_get_nr_types_stub(value btf_handle) {
  function value (line 144) | value btf_type_by_id_stub(value btf_handle, value type_id) {
  function value (line 198) | value btf_name_by_offset_stub(value btf_handle, value offset) {
  function value (line 215) | value btf_type_get_members_stub(value btf_handle, value type_id) {
  type btf (line 308) | struct btf
  type btf_type (line 311) | struct btf_type
  type btf_type (line 322) | struct btf_type
  type btf (line 378) | struct btf
  type btf_type (line 378) | struct btf_type
  type btf_param (line 402) | struct btf_param
  type btf_param (line 402) | struct btf_param
  type btf_param (line 405) | struct btf_param
  function value (line 436) | value btf_resolve_type_stub(value btf_handle, value type_id) {
  function value (line 603) | value btf_extract_function_signatures_stub(value btf_handle, value funct...
  function value (line 680) | value btf_extract_kernel_struct_and_enum_names_stub(value btf_handle) {
  function value (line 714) | value btf_extract_kfuncs_stub(value btf_handle) {
  function value (line 771) | value btf_free_stub(value btf_handle) {
Condensed preview — 196 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,096K chars).
[
  {
    "path": ".github/workflows/ci.yml",
    "chars": 1147,
    "preview": "name: CI\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n  workflow_dispatch:\n\njobs:\n  build:"
  },
  {
    "path": ".gitignore",
    "chars": 240,
    "preview": "# Build directories\n_build/\n*.install\n\n# Cursor editor files\n.cursor/\n\n# OCaml build artifacts\n*.cmi\n*.cmo\n*.cmx\n*.cma\n*"
  },
  {
    "path": "BUILTINS.md",
    "chars": 10655,
    "preview": "# KernelScript Builtin Functions Reference\n\nThis document provides a comprehensive reference for all builtin functions a"
  },
  {
    "path": "LICENSE",
    "chars": 11339,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 16469,
    "preview": "![KernelScript Logo](logo.png)\n\n# KernelScript\n\n> **⚠️ Beta Version Notice**\n> KernelScript is currently in beta develop"
  },
  {
    "path": "SPEC.md",
    "chars": 147891,
    "preview": "# KernelScript Language Format Specification v1.0\n\n## 1. Design Philosophy and Scope\n\n### 1.1 Core Principles\n- **Simpli"
  },
  {
    "path": "dune-project",
    "chars": 345,
    "preview": "(lang dune 2.9)\n\n(name kernelscript)\n\n(use_standard_c_and_cxx_flags true)\n\n(package\n (name kernelscript)\n (authors \"Cong"
  },
  {
    "path": "examples/basic_match.ks",
    "chars": 2841,
    "preview": "// Basic Match Construct Demo for KernelScript\n// Demonstrates packet matching with the new match construct\n\ninclude \"xd"
  },
  {
    "path": "examples/break_continue_unbound.ks",
    "chars": 1260,
    "preview": "// Example demonstrating break and continue in truly unbound loops\n// This should force bpf_loop() usage\n\ninclude \"xdp.k"
  },
  {
    "path": "examples/common_kfuncs.kh",
    "chars": 239,
    "preview": "// Common kernel function declarations\nextern bpf_ktime_get_ns() -> u64\nextern bpf_trace_printk(fmt: *u8, fmt_size: u32)"
  },
  {
    "path": "examples/dynptr.ks",
    "chars": 1142,
    "preview": "// Dynptr showcase - compiler should transparently use dynptr APIs for packet access\n// Example to demonstrate bpf_dynpt"
  },
  {
    "path": "examples/error_handling_demo.ks",
    "chars": 798,
    "preview": "// Minimal error handling demo\ninclude \"xdp.kh\"\n\nvar counters : hash<u32, u64>(1024)\n\n@xdp fn error_demo(ctx: *xdp_md) -"
  },
  {
    "path": "examples/extern_kfunc_demo.ks",
    "chars": 761,
    "preview": "include \"xdp.kh\"\n\n// External kfunc declarations - these would typically be imported from kernel BTF\nextern bpf_ktime_ge"
  },
  {
    "path": "examples/functions.ks",
    "chars": 1398,
    "preview": "include \"xdp.kh\"\n\ntype IpAddress = u32\n\n@helper\nfn helper_function(value: u32) -> u32 {\n  return value + 10\n}\n\n@helper\nf"
  },
  {
    "path": "examples/import/network_utils.py",
    "chars": 784,
    "preview": "\"\"\"\nSimple network utilities for KernelScript import testing\n\"\"\"\n\ndef calculate_bandwidth(packets_per_second, avg_packet"
  },
  {
    "path": "examples/import/simple_utils.ks",
    "chars": 131,
    "preview": "// Simple utilities for import testing\n\nfn validate_config() -> bool {\n    return true\n}\n\nfn get_status() -> u32 {\n    r"
  },
  {
    "path": "examples/import_demo.ks",
    "chars": 1308,
    "preview": "// Working demo of unified import syntax\n\n// Import KernelScript module (compiled to .so)\nimport utils from \"./import/si"
  },
  {
    "path": "examples/include_demo.ks",
    "chars": 795,
    "preview": "// Example demonstrating include functionality\n// This shows how to include KernelScript headers (.kh files)\n\n// Include"
  },
  {
    "path": "examples/local_global_vars.ks",
    "chars": 1474,
    "preview": "// Example demonstrating local vs shared global variables\n//\n// This example shows the difference between:\n// - Regular "
  },
  {
    "path": "examples/map_operations_demo.ks",
    "chars": 5677,
    "preview": "// Map Operations Semantics Demo for KernelScript\n// Demonstrates advanced map operation analysis, concurrent access saf"
  },
  {
    "path": "examples/maps_demo.ks",
    "chars": 3097,
    "preview": "// This example demonstrates the complete eBPF map type system\n\ninclude \"xdp.kh\"\ninclude \"tc.kh\"\n\n// Type aliases for cl"
  },
  {
    "path": "examples/multi_programs.ks",
    "chars": 857,
    "preview": "// TC context struct (from BTF)\ninclude \"xdp.kh\"\ninclude \"tc.kh\"\n\n// TC action constants\npin var shared_counter : hash<u"
  },
  {
    "path": "examples/named_return.ks",
    "chars": 4374,
    "preview": "// Basic named return value - Go-style syntax\ninclude \"xdp.kh\"\n\nfn add_with_named_return(a: i32, b: i32) -> sum: i32 {\n "
  },
  {
    "path": "examples/object_allocation.ks",
    "chars": 2148,
    "preview": "// Simple XDP packet inspector with object allocation\n// Demonstrates new/delete for connection tracking\n\ninclude \"xdp.k"
  },
  {
    "path": "examples/packet_filter.ks",
    "chars": 523,
    "preview": "include \"xdp.kh\"\n\n@xdp fn packet_filter(ctx: *xdp_md) -> xdp_action {\n  var packet_size = ctx->data_end - ctx->data\n  if"
  },
  {
    "path": "examples/packet_matching.ks",
    "chars": 11905,
    "preview": "// Packet Matching Demo - KernelScript Match Construct\n//\n// This example demonstrates the powerful match construct for "
  },
  {
    "path": "examples/pattern_test.ks",
    "chars": 858,
    "preview": "// Pattern Test Example - tests struct initialization (IRStructLiteral pattern)\n\ninclude \"xdp.kh\"\n\nstruct PacketInfo {\n "
  },
  {
    "path": "examples/pointer_simple.ks",
    "chars": 245,
    "preview": "// Simple pointer demo\ninclude \"xdp.kh\"\n\nstruct Point {\n    x: u32,\n    y: u32,\n}\n\n@helper  \nfn update_point(p: *Point) "
  },
  {
    "path": "examples/print_demo.ks",
    "chars": 880,
    "preview": "// This shows the same print() function working in both eBPF and userspace contexts\n\ninclude \"xdp.kh\"\n\nconfig demo {\n   "
  },
  {
    "path": "examples/private_kfunc.ks",
    "chars": 1125,
    "preview": "// Minimal example showing @private and @kfunc functions\n\n// Private helper function - internal to kernel module, not ex"
  },
  {
    "path": "examples/probe.kh",
    "chars": 571,
    "preview": "// AUTO-GENERATED PROBE DEFINITIONS - DO NOT EDIT\n// Contains all kernel types and functions needed for probe programs\n/"
  },
  {
    "path": "examples/probe_do_exit.ks",
    "chars": 1478,
    "preview": "// Kprobe Example: Monitor process exit events\n// \n// This example demonstrates how to use probe to intercept and monito"
  },
  {
    "path": "examples/python_demo.py",
    "chars": 3529,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nDemo Python Script - Called via exec() from KernelScript\n\nThis script demonstrates the CORREC"
  },
  {
    "path": "examples/rate_limiter.ks",
    "chars": 1312,
    "preview": "include \"xdp.kh\"\n\nvar packet_counts : hash<u32, u64>(1024)\n\nconfig network {\n  limit : u32,\n}\n\n@xdp fn rate_limiter(ctx:"
  },
  {
    "path": "examples/ringbuf_demo.ks",
    "chars": 5366,
    "preview": "// Ring Buffer Demonstration for KernelScript\n// Shows complete ring buffer API usage from eBPF to userspace\n\n// Event s"
  },
  {
    "path": "examples/ringbuf_on_event_demo.ks",
    "chars": 1421,
    "preview": "// Ring Buffer on_event() Demo\n// Shows how to register event handlers for ring buffers\n\ninclude \"xdp.kh\"\n\nstruct Networ"
  },
  {
    "path": "examples/safety_demo.ks",
    "chars": 3645,
    "preview": "// This file demonstrates the memory safety analysis capabilities\n\n// Type aliases for clarity\ninclude \"xdp.kh\"\n\ntype Pa"
  },
  {
    "path": "examples/sched_ext_ops.kh",
    "chars": 1472,
    "preview": "// AUTO-GENERATED SCHED_EXT_OPS DEFINITIONS - DO NOT EDIT\n// Contains kernel struct definition for sched_ext_ops\n// Gene"
  },
  {
    "path": "examples/sched_ext_simple.ks",
    "chars": 3396,
    "preview": "// Simple sched-ext scheduler implementation\n// This demonstrates a basic FIFO scheduler using sched_ext_ops\n\ninclude \"s"
  },
  {
    "path": "examples/simple_gfp_test.ks",
    "chars": 680,
    "preview": "// Simple test to verify GFP flag validation \n\ninclude \"xdp.kh\"\n\nstruct TestData {\n    value: u64,\n}\n\n@kfunc\nfn valid_kf"
  },
  {
    "path": "examples/simple_program_lifecycle.ks",
    "chars": 431,
    "preview": "include \"xdp.kh\"\n\n@xdp fn simple_xdp(ctx: *xdp_md) -> xdp_action {\n  return XDP_PASS\n}\n\nfn main() -> i32 {\n  var prog = "
  },
  {
    "path": "examples/string_test.ks",
    "chars": 1895,
    "preview": "// KernelScript String Type Demonstration\n// Shows unified string syntax working in both eBPF and userspace contexts\n\nin"
  },
  {
    "path": "examples/struct_ops_simple.ks",
    "chars": 1463,
    "preview": "// Test file with impl block struct_ops declarations using the new syntax\n// This demonstrates the clean, intuitive impl"
  },
  {
    "path": "examples/symbols.ks",
    "chars": 2930,
    "preview": "// This file demonstrates hierarchical symbol resolution,\n// global scope management, map visibility rules,\n// and funct"
  },
  {
    "path": "examples/tail_call.ks",
    "chars": 1055,
    "preview": "// Minimal Tail Call Demo\n// Shows both regular kernel function calls and actual eBPF tail calls\n\n// KERNEL FUNCTION - c"
  },
  {
    "path": "examples/tc.kh",
    "chars": 1385,
    "preview": "// AUTO-GENERATED TC DEFINITIONS - DO NOT EDIT\n// Contains all kernel types and functions needed for tc programs\n// Gene"
  },
  {
    "path": "examples/tcp_congestion_ops.kh",
    "chars": 544,
    "preview": "// AUTO-GENERATED TCP_CONGESTION_OPS DEFINITIONS - DO NOT EDIT\n// Contains kernel struct definition for tcp_congestion_o"
  },
  {
    "path": "examples/test_config.ks",
    "chars": 937,
    "preview": "// Test KernelScript file demonstrating config system\n\ninclude \"xdp.kh\"\n\nconfig network {\n    max_packet_size: u32 = 150"
  },
  {
    "path": "examples/test_error_handling.ks",
    "chars": 2130,
    "preview": "// Test catch/throw/defer functionality with integer-based error handling\ninclude \"xdp.kh\"\n\nvar test_map : hash<u32, u64"
  },
  {
    "path": "examples/test_exec.ks",
    "chars": 1062,
    "preview": "// Test exec() builtin with Python integration\n\n// Global maps for sharing with Python\ninclude \"xdp.kh\"\n\nvar packet_stat"
  },
  {
    "path": "examples/test_functions.ks",
    "chars": 1943,
    "preview": "// Example demonstrating @test functions for eBPF program testing\n\n// Test context structures for different program type"
  },
  {
    "path": "examples/tracepoint.kh",
    "chars": 664,
    "preview": "// AUTO-GENERATED TRACEPOINT DEFINITIONS - DO NOT EDIT\n// Contains all kernel types and functions needed for tracepoint "
  },
  {
    "path": "examples/tracepoint_sched_switch.ks",
    "chars": 3246,
    "preview": "// Tracepoint Example: Monitor process scheduling events\n// \n// This example demonstrates how to use tracepoint to monit"
  },
  {
    "path": "examples/type_alias.ks",
    "chars": 594,
    "preview": "// Test file for type alias functionality\ninclude \"xdp.kh\"\n\ntype IpAddress = u32\ntype Port = u16\ntype EthBuffer = u8[14]"
  },
  {
    "path": "examples/type_checking.ks",
    "chars": 4345,
    "preview": "// This file demonstrates the type checking capabilities\n\n// Type definitions for comprehensive type checking\ninclude \"x"
  },
  {
    "path": "examples/types_demo.ks",
    "chars": 3028,
    "preview": "// This file demonstrates all the new type system features\n\n// Type alias for common types\ninclude \"xdp.kh\"\n\ntype IpAddr"
  },
  {
    "path": "examples/userspace_example.ks",
    "chars": 897,
    "preview": "include \"xdp.kh\"\n\n@xdp fn packet_monitor(ctx: *xdp_md) -> xdp_action {\n    return XDP_PASS\n}\n\n// Userspace types and fun"
  },
  {
    "path": "examples/xdp.kh",
    "chars": 459,
    "preview": "// AUTO-GENERATED XDP DEFINITIONS - DO NOT EDIT\n// Contains all kernel types and functions needed for xdp programs\n// Ge"
  },
  {
    "path": "examples/xdp_kfuncs.kh",
    "chars": 208,
    "preview": "// XDP-specific kernel function declarations\nextern bpf_xdp_adjust_head(ctx: *xdp_md, delta: i32) -> i32\nextern bpf_xdp_"
  },
  {
    "path": "kernelscript.opam",
    "chars": 566,
    "preview": "opam-version: \"2.0\"\nname: \"kernelscript\"\nauthors: [\"Cong Wang\"]\nmaintainer: [\"Cong Wang <cwang@multikernel.io>\"]\nlicense"
  },
  {
    "path": "src/ast.ml",
    "chars": 35786,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/btf_binary_parser.ml",
    "chars": 9039,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/btf_binary_parser.mli",
    "chars": 2020,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/btf_parser.ml",
    "chars": 32642,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/btf_parser.mli",
    "chars": 3079,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/btf_stubs.c",
    "chars": 27545,
    "preview": "/*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/codegen_common.ml",
    "chars": 6043,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/context/context_codegen.ml",
    "chars": 10670,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/context/context_codegen.mli",
    "chars": 3214,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/context/dune",
    "chars": 196,
    "preview": "(library\n (public_name kernelscript.context)\n (name kernelscript_context)\n (modules context_codegen xdp_codegen tc_codeg"
  },
  {
    "path": "src/context/fprobe_codegen.ml",
    "chars": 2718,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/context/kprobe_codegen.ml",
    "chars": 4324,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/context/tc_codegen.ml",
    "chars": 4158,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/context/tracepoint_codegen.ml",
    "chars": 3602,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/context/xdp_codegen.ml",
    "chars": 3842,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/dune",
    "chars": 1020,
    "preview": "(library\n (name kernelscript)\n (modules ast parser lexer parse type_checker symbol_table maps map_assignment\n          m"
  },
  {
    "path": "src/dynptr_bridge.ml",
    "chars": 4169,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/ebpf_c_codegen.ml",
    "chars": 158180,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/evaluator.ml",
    "chars": 42647,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/import_resolver.ml",
    "chars": 11807,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/include_resolver.ml",
    "chars": 7261,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/ir.ml",
    "chars": 43156,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/ir_analysis.ml",
    "chars": 17017,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/ir_function_system.ml",
    "chars": 6332,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/ir_generator.ml",
    "chars": 170783,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/kernel_module_codegen.ml",
    "chars": 18120,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/kernel_module_codegen.mli",
    "chars": 1107,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/kernelscript_bridge.ml",
    "chars": 10304,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/lexer.mll",
    "chars": 7198,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/loop_analysis.ml",
    "chars": 7509,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/main.ml",
    "chars": 49838,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/map_assignment.ml",
    "chars": 5620,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/map_operations.ml",
    "chars": 19167,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/maps.ml",
    "chars": 13908,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/multi_program_analyzer.ml",
    "chars": 18431,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/multi_program_ir_optimizer.ml",
    "chars": 10460,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/parse.ml",
    "chars": 7268,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/parser.mly",
    "chars": 28361,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/python_bridge.ml",
    "chars": 4365,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/safety_checker.ml",
    "chars": 23630,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/stdlib.ml",
    "chars": 12555,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/struct_ops_registry.ml",
    "chars": 7705,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/struct_ops_registry.mli",
    "chars": 2324,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/symbol_table.ml",
    "chars": 42216,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/tail_call_analyzer.ml",
    "chars": 13729,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/test_codegen.ml",
    "chars": 14890,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/type_checker.ml",
    "chars": 179791,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "src/userspace_codegen.ml",
    "chars": 193048,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/dune",
    "chars": 17628,
    "preview": "(library\n (name test_utils)\n (modules test_utils)\n (libraries kernelscript))\n\n(executable\n (name test_ringbuf)\n (modules"
  },
  {
    "path": "tests/test_address_of_user_types.ml",
    "chars": 4534,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_all_examples.sh",
    "chars": 5686,
    "preview": "#!/bin/bash\n#\n# Copyright 2025 Multikernel Technologies, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"L"
  },
  {
    "path": "tests/test_array_init.ml",
    "chars": 7489,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_array_literals.ml",
    "chars": 7751,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ast.ml",
    "chars": 6370,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_bpf_loop_callbacks.ml",
    "chars": 8426,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_break_continue.ml",
    "chars": 10266,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_btf_binary_parser.ml",
    "chars": 21054,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_comment_positions.ml",
    "chars": 4843,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_compound_index_assignment.ml",
    "chars": 19560,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_config.ml",
    "chars": 25413,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_config_struct_generation.ml",
    "chars": 19304,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_config_validation.ml",
    "chars": 8642,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_const_variables.ml",
    "chars": 5901,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_context_field_types.ml",
    "chars": 9764,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_definition_order.ml",
    "chars": 16386,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_detach_api.ml",
    "chars": 5707,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_dynptr_bridge.ml",
    "chars": 5637,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ebpf_c_codegen.ml",
    "chars": 66699,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ebpf_string_generation.ml",
    "chars": 10166,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_enum.ml",
    "chars": 25400,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_error_handling.ml",
    "chars": 14838,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_evaluator.ml",
    "chars": 4395,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_exec.ml",
    "chars": 8140,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_extern.ml",
    "chars": 8798,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_for_statements.ml",
    "chars": 7906,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_function_generation.ml",
    "chars": 8235,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_function_pointers.ml",
    "chars": 20812,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_function_scope.ml",
    "chars": 23690,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_function_validation.ml",
    "chars": 4396,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_global_var.ml",
    "chars": 31459,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_global_var_ordering.ml",
    "chars": 5044,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_iflet.ml",
    "chars": 13011,
    "preview": "(*\n * Copyright 2026 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_import_system.ml",
    "chars": 18684,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_include.ml",
    "chars": 8888,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_integer_literal.ml",
    "chars": 18591,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ir.ml",
    "chars": 14142,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ir_analysis.ml",
    "chars": 43607,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ir_function_system.ml",
    "chars": 9863,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ir_patterns.ml",
    "chars": 9385,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_kfunc_attribute.ml",
    "chars": 9059,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_lexer.ml",
    "chars": 9589,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_map_assignment.ml",
    "chars": 13887,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_map_flags.ml",
    "chars": 15392,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_map_integration.ml",
    "chars": 16669,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_map_operations.ml",
    "chars": 31952,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_map_syntax.ml",
    "chars": 16846,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_maps.ml",
    "chars": 8660,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_match.ml",
    "chars": 21596,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_named_returns.ml",
    "chars": 12557,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_nested_if_codegen.ml",
    "chars": 6966,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_object_allocation.ml",
    "chars": 4387,
    "preview": "open Kernelscript.Ast\nopen Alcotest\n\nlet pos = { line = 1; column = 1; filename = \"test\" }\n\nlet make_expr desc = {\n  exp"
  },
  {
    "path": "tests/test_parser.ml",
    "chars": 33262,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_pinned_globals.ml",
    "chars": 6714,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_pointer_syntax.ml",
    "chars": 16127,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_private_attribute.ml",
    "chars": 3288,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_probe.ml",
    "chars": 27236,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_program_ref.ml",
    "chars": 8668,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_return_path_analysis.ml",
    "chars": 8480,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_return_value_propagation.ml",
    "chars": 7776,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_ringbuf.ml",
    "chars": 40347,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_safety_checker.ml",
    "chars": 8847,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_stdlib.ml",
    "chars": 4417,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_string_codegen.ml",
    "chars": 14855,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_string_literal_bugs.ml",
    "chars": 18055,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_string_struct_fixes.ml",
    "chars": 17027,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_string_to_array_unification.ml",
    "chars": 6182,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_string_type.ml",
    "chars": 6154,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_struct_field_access.ml",
    "chars": 20287,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_struct_initialization.ml",
    "chars": 11846,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_struct_ops.ml",
    "chars": 54906,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_symbol_table.ml",
    "chars": 36799,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_tail_call.ml",
    "chars": 28994,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_tc.ml",
    "chars": 24463,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_test_attribute.ml",
    "chars": 6187,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_tracepoint.ml",
    "chars": 19583,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_truthy_falsy.ml",
    "chars": 11415,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_type_alias.ml",
    "chars": 16742,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_type_checker.ml",
    "chars": 47402,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_userspace.ml",
    "chars": 25996,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_userspace_for_codegen.ml",
    "chars": 13162,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_userspace_maps.ml",
    "chars": 31893,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_userspace_skeleton_header.ml",
    "chars": 6640,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_userspace_statements.ml",
    "chars": 12889,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_userspace_struct_flexibility.ml",
    "chars": 10115,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_utils.ml",
    "chars": 9223,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "tests/test_void_functions.ml",
    "chars": 14693,
    "preview": "(*\n * Copyright 2025 Multikernel Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
  }
]

About this extraction

This page contains the full source code of the multikernel/kernelscript GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 196 files (2.8 MB), approximately 751.6k tokens, and a symbol index with 32 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!