run.js
1 // SPDX-License-Identifier: AGPL-3.0-or-later 2 // SPDX-FileCopyrightText: 2025 hyperpolymath 3 // 4 // AffineScript Playground - Deno Entry Point 5 // Demonstrates affine type semantics for WebAssembly 6 7 /** 8 * AffineScript Playground 9 * 10 * This playground demonstrates affine type semantics - types that can be used 11 * at most once. This is useful for: 12 * - Resource management (file handles, network connections) 13 * - Memory safety without garbage collection 14 * - WebAssembly linear memory safety 15 */ 16 17 // Import from compiled ReScript 18 import { demonstrate } from "./Affine.res.js"; 19 20 // Affine type wrapper - simulates use-at-most-once semantics 21 class AffineResource { 22 #consumed = false; 23 #resourceValue; 24 25 constructor(value) { 26 this.#resourceValue = value; 27 } 28 29 /** 30 * Consume the resource. Can only be called once. 31 * Affine semantics: use at most once (0 or 1 times) 32 */ 33 consume() { 34 if (this.#consumed) { 35 throw new Error("Affine type violation: resource already consumed"); 36 } 37 this.#consumed = true; 38 return this.#resourceValue; 39 } 40 41 /** 42 * Check if resource has been consumed 43 */ 44 isConsumed() { 45 return this.#consumed; 46 } 47 48 /** 49 * Affine types can be dropped without use (unlike linear types) 50 */ 51 drop() { 52 if (!this.#consumed) { 53 console.log("Resource dropped without use (affine allows this)"); 54 this.#consumed = true; 55 } 56 } 57 } 58 59 // Example: WASM memory handle with affine semantics 60 function allocateWasmMemory(size) { 61 const handle = { 62 ptr: Math.floor(Math.random() * 0xffff), // Simulated pointer 63 size, 64 }; 65 console.log(`Allocated WASM memory at 0x${handle.ptr.toString(16)}, size: ${size}`); 66 return new AffineResource(handle); 67 } 68 69 function useWasmMemory(resource) { 70 const handle = resource.consume(); 71 console.log(`Using WASM memory at 0x${handle.ptr.toString(16)}`); 72 // Memory is now consumed - cannot be used again 73 } 74 75 // Main demonstration 76 function demonstrateAffineTypes() { 77 console.log("=== AffineScript Playground ===\n"); 78 console.log("Demonstrating affine type semantics:\n"); 79 80 // Example 1: Proper affine usage 81 console.log("1. Proper usage (use once):"); 82 const mem1 = allocateWasmMemory(1024); 83 useWasmMemory(mem1); 84 console.log(` Resource consumed: ${mem1.isConsumed()}\n`); 85 86 // Example 2: Affine allows dropping without use 87 console.log("2. Drop without use (affine allows this):"); 88 const mem2 = allocateWasmMemory(512); 89 mem2.drop(); 90 console.log(` Resource consumed: ${mem2.isConsumed()}\n`); 91 92 // Example 3: Attempting double use (will throw) 93 console.log("3. Double use attempt (will throw):"); 94 const mem3 = allocateWasmMemory(256); 95 try { 96 mem3.consume(); 97 mem3.consume(); // This will throw 98 } catch (error) { 99 console.log(` Error: ${error.message}\n`); 100 } 101 102 console.log("=== Demo Complete ==="); 103 } 104 105 // Run if executed directly 106 if (import.meta.main) { 107 demonstrateAffineTypes(); 108 } 109 110 export { AffineResource, allocateWasmMemory, useWasmMemory, demonstrateAffineTypes };