{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "oop-intro",
      "metadata": {},
      "source": "# Aner objects: lists, graphs, and a binary search tree\n\nUse your installed Aner executable and the compatible VS Code extension (**0.1.16** for this example). Follow the versions recommended together by your release; see `docs/INSTALLATION.md` and `docs/VSCODE.md`. Choose **Run All** in this shared variable notebook. Classes, objects, and methods execute in Aner's native runtime.\n\nRun each class definition cell once per session. To change or repeat class definitions, choose **Aner: Restart Notebook Session**, then **Run All**. Saved output is historical content, not a heap snapshot.\n"
    },
    {
      "cell_type": "markdown",
      "id": "oop-list-intro",
      "metadata": {},
      "source": "## A linked list\n\n`Node?` is either a Node reference or `null`. `.unwrap()` checks it before use. `public let value` is a read only public field; `public var next` can be reassigned from other classes. Fields are private by default. Class methods receive an implicit typed receiver; they may omit `self` and result annotations. Constructors require every field.\n"
    },
    {
      "cell_type": "code",
      "id": "oop-list-definitions",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "// A linked list uses nullable links and mutable object fields.\n",
        "// let fixes the binding; methods may still update the object's var fields.\n",
        "class Node {\n",
        "    public let value: Int64\n",
        "    public var next: Node?\n",
        "\n",
        "    fn get() {\n",
        "        return value\n",
        "    }\n",
        "}\n",
        "\n",
        "class LinkedList {\n",
        "    public var head: Node?\n",
        "\n",
        "    fn push(value: Int64) {\n",
        "        head = Node(value: value, next: head)\n",
        "    }\n",
        "\n",
        "    fn len() {\n",
        "        var count = 0\n",
        "        var cursor = head\n",
        "        while cursor != null {\n",
        "            let node = cursor.unwrap()\n",
        "            count = count + 1\n",
        "            cursor = node.next\n",
        "        }\n",
        "        return count\n",
        "    }\n",
        "\n",
        "    fn sum() {\n",
        "        var total = 0\n",
        "        var cursor = head\n",
        "        while cursor != null {\n",
        "            let node = cursor.unwrap()\n",
        "            total = total + node.value\n",
        "            cursor = node.next\n",
        "        }\n",
        "        return total\n",
        "    }\n",
        "}"
      ]
    },
    {
      "cell_type": "code",
      "id": "oop-list-run",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let numbers = LinkedList(head: null)\n",
        "numbers.push(30)\n",
        "numbers.push(20)\n",
        "numbers.push(10)\n",
        "print(\"Length\")\n",
        "print(numbers.len())\n",
        "print(\"Sum\")\n",
        "print(numbers.sum())\n",
        "print(\"First value\")\n",
        "print(numbers.head.unwrap().get())\n",
        "let alias = numbers\n",
        "print(\"Aliases share identity\")\n",
        "print(alias == numbers)\n",
        "alias.push(5)\n",
        "print(\"Length after an update through the alias\")\n",
        "print(numbers.len())\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "oop-graph-intro",
      "metadata": {},
      "source": "## A directed graph with a cycle\n\nA Vertex owns an adjacency list reference; each Edge refers to a target Vertex. These classes refer to one another. The example creates a two vertex cycle and counts outgoing neighbors, without claiming a general graph traversal.\n"
    },
    {
      "cell_type": "code",
      "id": "oop-graph-definitions",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "// Directed graph with linked adjacency lists; no array/list library is needed.\n",
        "// Two connections create a cycle between vertices. neighbor_count counts only\n",
        "// outgoing neighbors; it is not a graph traversal or reachability algorithm.\n",
        "class Vertex {\n",
        "    public let id: Int64\n",
        "    public var edges: Edge?\n",
        "\n",
        "    fn connect(target: Vertex) {\n",
        "        edges = Edge(target: target, next: edges)\n",
        "    }\n",
        "\n",
        "    fn neighbor_count() {\n",
        "        var count = 0\n",
        "        var cursor = edges\n",
        "        while cursor != null {\n",
        "            let edge = cursor.unwrap()\n",
        "            count = count + 1\n",
        "            cursor = edge.next\n",
        "        }\n",
        "        return count\n",
        "    }\n",
        "}\n",
        "\n",
        "class Edge {\n",
        "    public let target: Vertex\n",
        "    public var next: Edge?\n",
        "}"
      ]
    },
    {
      "cell_type": "code",
      "id": "oop-graph-run",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let first = Vertex(id: 10, edges: null)\n",
        "let second = Vertex(id: 20, edges: null)\n",
        "first.connect(second)\n",
        "second.connect(first)\n",
        "print(\"First outgoing neighbors\")\n",
        "print(first.neighbor_count())\n",
        "print(\"Second outgoing neighbors\")\n",
        "print(second.neighbor_count())\n",
        "print(\"First edge reaches second vertex\")\n",
        "print(first.edges.unwrap().target == second)\n",
        "print(\"Return edge reaches first vertex\")\n",
        "print(second.edges.unwrap().target == first)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "oop-tree-intro",
      "metadata": {},
      "source": "## A binary search tree\n\nThis is an unbalanced binary search tree with two children per node. It is not a multiway B tree. Insertion is recursive and subject to the runtime call depth limit; lookup is iterative. Duplicate values are ignored.\n"
    },
    {
      "cell_type": "code",
      "id": "oop-tree-definitions",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "// A binary search tree, not a multiway B-tree. Duplicate values are ignored.\n",
        "// This example is unbalanced; recursive insertion uses Aner's call-depth limit.\n",
        "class TreeNode {\n",
        "    public let value: Int64\n",
        "    public var left: TreeNode?\n",
        "    public var right: TreeNode?\n",
        "\n",
        "    fn insert(value: Int64) -> Unit {\n",
        "        if value < self.value {\n",
        "            if left == null {\n",
        "                left = TreeNode(value: value, left: null, right: null)\n",
        "            } else {\n",
        "                left.unwrap().insert(value)\n",
        "            }\n",
        "        } else if value > self.value {\n",
        "            if right == null {\n",
        "                right = TreeNode(value: value, left: null, right: null)\n",
        "            } else {\n",
        "                right.unwrap().insert(value)\n",
        "            }\n",
        "        }\n",
        "    }\n",
        "}\n",
        "\n",
        "class Tree {\n",
        "    public var root: TreeNode?\n",
        "\n",
        "    fn insert(value: Int64) -> Unit {\n",
        "        if root == null {\n",
        "            root = TreeNode(value: value, left: null, right: null)\n",
        "        } else {\n",
        "            root.unwrap().insert(value)\n",
        "        }\n",
        "    }\n",
        "\n",
        "    fn contains(value: Int64) {\n",
        "        var cursor = root\n",
        "        while cursor != null {\n",
        "            let node = cursor.unwrap()\n",
        "            if value == node.value {\n",
        "                return true\n",
        "            } else if value < node.value {\n",
        "                cursor = node.left\n",
        "            } else {\n",
        "                cursor = node.right\n",
        "            }\n",
        "        }\n",
        "        return false\n",
        "    }\n",
        "}"
      ]
    },
    {
      "cell_type": "code",
      "id": "oop-tree-run",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let tree = Tree(root: null)\n",
        "tree.insert(8)\n",
        "tree.insert(3)\n",
        "tree.insert(10)\n",
        "tree.insert(6)\n",
        "tree.insert(14)\n",
        "print(\"Contains 6\")\n",
        "print(tree.contains(6))\n",
        "print(\"Contains 7\")\n",
        "print(tree.contains(7))\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "oop-state",
      "metadata": {},
      "source": "# Ownership, identity, and notebook state\n\nObjects have reference identity. `let alias = numbers` points to the same LinkedList; it does not copy the list. A `let` binding cannot be rebound, but the object's declared `var` fields may change. `==` compares object identity, not equal field contents. Nullable references must be explicitly unwrapped before field or method access, even inside a check against `null`. Unwrapping `null` is a runtime error and resets this notebook session.\n\nAner traces object references after each successful cell and reclaims unreachable objects, including cycles. Global variables remain roots; these named examples stay alive until their roots are removed or the session ends. Scripts release their object heap on exit. This first heap has explicit object/field limits and does not collect in the middle of an expression or loop; those limits are not a process memory quota.\n\nGeneral lists, inheritance, interfaces/traits, user defined value structs, and checkpoint serialization remain future work. Generic classes are shown in the separate `oop_generics.anernb` notebook. See the supplied `docs/OOP.md` guide for the exact contracts and limits.\n"
    }
  ],
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner",
      "mimetype": "text/x-aner"
    },
    "aner": {
      "status": "example",
      "execution_mode": "persistent-session"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
