Record jsqlite and tooling discoveries
ober
d54563e6d6358e973d46b62b80cda0b1976d7cc5
--- a/data/cookbooks.sexp +++ b/data/cookbooks.sexp @@ -5409,4 +5409,42 @@ "immutable" "hamt-empty" "hamt-ref") ("title" . - "Use HAMT persistent maps from (std misc persistent)"))) + "Use HAMT persistent maps from (std misc persistent)")) + (("code" + . + "(import (chezscheme) (jsh ffi))\n\n;; Direct foreign-procedure bindings outside (jsh ffi) need libjsh-ffi loaded\n;; first in dynamic/dev builds. Calling any existing (jsh ffi) wrapper triggers\n;; that module's guarded loader. In static builds this is harmless because the\n;; symbols are already registered.\n\n(def *my-c-symbol* #f)\n\n(def (my-c-symbol arg-bv arg-len)\n (unless *my-c-symbol*\n (ffi-getpid) ; forces (jsh ffi)'s libjsh-ffi loader path in dynamic builds\n (set! *my-c-symbol*\n (foreign-procedure \"ffi_my_new_symbol\" (u8* int) int)))\n (*my-c-symbol* arg-bv arg-len))") ("id" . "jsh-direct-ffi-after-loader") + ("imports" "(chezscheme)" "(jsh ffi)") + ("notes" + . + "Prefer adding exported bindings inside (jsh ffi) when that module is the source being edited. If binding a new ffi-shim.c symbol from jsh.ss or another script-level file, resolve it lazily after an existing (jsh ffi) call such as ffi-getpid; otherwise dynamic builds can raise `Exception in foreign-procedure: no entry for ...` even though the symbol exists in libjsh-ffi. Regenerate ffi-shim-symbols.list for static builds.") + ("tags" "jsh" "ffi" "foreign-procedure" "libjsh-ffi" + "load-shared-object" "dynamic") + ("title" + . + "Bind a new jsh ffi-shim symbol outside (jsh ffi)")) + (("code" + . + "(import (except (jerboa prelude)\n sqlite-open sqlite-close sqlite-exec sqlite-execute sqlite-query\n sqlite-prepare sqlite-finalize sqlite-step sqlite-bind))\n(import (jsqlite api))\n\n(def (escape-like-pattern s)\n (let ((len (string-length s)))\n (let loop ((i 0) (parts '()))\n (if (>= i len)\n (apply string-append (reverse parts))\n (let ((c (string-ref s i)))\n (loop (+ i 1)\n (cons (cond\n ((char=? c #\\\\) \"\\\\\\\\\")\n ((char=? c #\\%) \"\\\\%\")\n ((char=? c #\\_) \"\\\\_\")\n (else (string c)))\n parts)))))))\n\n(def (contains-pattern s)\n (string-append \"%\" (escape-like-pattern s) \"%\"))\n\n(def db (sqlite-open \":memory:\"))\n(sqlite-exec db \"CREATE TABLE notes (body TEXT)\")\n(sqlite-exec db \"INSERT INTO notes (body) VALUES (?)\" \"100% literal\")\n(sqlite-query db \"SELECT body FROM notes WHERE body LIKE ? ESCAPE '\\\\'\" (contains-pattern \"100%\"))\n(sqlite-close db)") ("id" . "jsqlite-escaped-like-search") + ("imports" + "(except (jerboa prelude) sqlite-open sqlite-close sqlite-exec sqlite-execute sqlite-query sqlite-prepare sqlite-finalize sqlite-step sqlite-bind)" + "(jsqlite api)") + ("notes" + . + "jsqlite does not provide SQLite FTS virtual tables. For simple literal substring search, keep the SQL fixed, pass the pattern as a parameter, and escape backslash, percent, and underscore before wrapping with % wildcards. If importing jsqlite API alongside the prelude, exclude prelude sqlite names to avoid duplicate bindings.") + ("tags" "jsqlite" "sqlite" "like" "escape" "search" + "parameters") + ("title" + . + "Literal substring search in jsqlite with LIKE ESCAPE")) + (("code" + . + "(import (except (jerboa prelude)\n sqlite-open sqlite-close sqlite-exec sqlite-execute sqlite-query\n sqlite-prepare sqlite-finalize sqlite-step sqlite-bind))\n(import (jsqlite api))\n\n(def db (sqlite-open \":memory:\"))\n(sqlite-exec db \"CREATE TABLE terminal_size (cols INTEGER, \\\"rows\\\" INTEGER)\")\n(sqlite-exec db \"INSERT INTO terminal_size (cols, \\\"rows\\\") VALUES (?, ?)\" 80 24)\n(sqlite-query db \"SELECT cols, \\\"rows\\\" FROM terminal_size\")\n(sqlite-close db)") ("id" . "jsqlite-quote-keyword-identifiers") + ("imports" + "(except (jerboa prelude) sqlite-open sqlite-close sqlite-exec sqlite-execute sqlite-query sqlite-prepare sqlite-finalize sqlite-step sqlite-bind)" + "(jsqlite api)") + ("notes" + . + "Names such as rows can be parsed as SQL keywords by jsqlite. Quote keyword-like identifiers consistently in CREATE TABLE, INSERT, UPDATE, and SELECT statements. This is preferable to relying on a parser accepting bare identifiers that happen to work in another SQLite implementation.") + ("tags" "jsqlite" "sqlite" "sql" "identifier" "keyword" + "schema") + ("title" . "Quote SQL keyword column names in jsqlite"))) --- a/data/features.sexp +++ b/data/features.sexp @@ -1954,4 +1954,24 @@ ("use_case" . "Debugging static Chez/Jerboa binaries that fail at startup with foreign-procedure: no entry for ...") + ("votes" . 0)) + (("description" + . + "`jerboa_function_signature` can report `Could not find` for symbols that `jerboa_module_exports` confirms are exported from imported project modules, such as `(jsh ffi)` or `(jsh signals)`. It should evaluate the imports and inspect the binding when static metadata is unavailable, or clearly distinguish non-procedure bindings from unresolved symbols.") + ("estimated_token_reduction" + . + "~300-700 tokens per affected API check by avoiding fallback searches/evals.") + ("example_scenario" + . + "While adding a jsh meta-command, `module_exports` showed `ffi-kill-pid` and `signal-name->number`, but `function_signature` could not find either with imports supplied.") + ("id" . "function-signature-imported-export-resolution") + ("impact" . "medium") + ("tags" "function_signature" "module_exports" "arity" + "imports" "project-modules") + ("title" + . + "Resolve imported exported bindings in function_signature") + ("use_case" + . + "When writing Jerboa code, agents are required to verify API arities before editing. This currently forces fallback to source search or ad hoc eval for some project exports.") ("votes" . 0)))