From 60a853fc7c2754ef1f1372d087ebd0cc0fc31dc8 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sun, 24 Apr 2022 19:39:15 -0400 Subject: [PATCH] Editable Tetris --- diet-sqlite/codes.lua | 280 ------------ diet-sqlite/ffi.lua | 5 - diet-sqlite/init.fnl | 67 --- diet-sqlite/sqlite3_ffi.lua | 866 ------------------------------------ game/init.fnl | 6 +- game/mode.fnl | 12 +- game/rules.fnl | 112 +++-- game/tilemap.fnl | 67 +-- game/tiles.fnl | 32 +- gneiss/cpu.fnl | 99 ----- gneiss/example.fnl | 34 -- sqlog/compiler.fnl | 289 ------------ sqlog/init.fnl | 63 --- sqlog/macros.fnl | 31 -- sqlog/sqltest.fnl | 18 - 15 files changed, 114 insertions(+), 1867 deletions(-) delete mode 100644 diet-sqlite/codes.lua delete mode 100644 diet-sqlite/ffi.lua delete mode 100644 diet-sqlite/init.fnl delete mode 100644 diet-sqlite/sqlite3_ffi.lua delete mode 100644 gneiss/cpu.fnl delete mode 100644 gneiss/example.fnl delete mode 100644 sqlog/compiler.fnl delete mode 100644 sqlog/init.fnl delete mode 100644 sqlog/macros.fnl delete mode 100644 sqlog/sqltest.fnl diff --git a/diet-sqlite/codes.lua b/diet-sqlite/codes.lua deleted file mode 100644 index 2d90f8d..0000000 --- a/diet-sqlite/codes.lua +++ /dev/null @@ -1,280 +0,0 @@ --- works with luajit ffi or https://github.com/q66/cffi-lua -local ffi = require "diet-sqlite.ffi" - -return { -SQLITE_TRANSIENT = ffi.cast('void(*)(void*)', -1); -SQLITE_STATIC = ffi.cast('void(*)(void*)', 0); - -log_callback_type = 'void(*)(void*,int,const char*)'; - --- error codes -SQLITE_EMPTY = 16; -SQLITE_CANTOPEN = 14; -SQLITE_FULL = 13; -SQLITE_BUSY = 5; -SQLITE_FORMAT = 24; -SQLITE_READONLY = 8; -SQLITE_LOCKED = 6; -SQLITE_INTERNAL = 2; -SQLITE_ROW = 100; -SQLITE_PERM = 3; -SQLITE_CORRUPT = 11; -SQLITE_ABORT = 4; -SQLITE_SCHEMA = 17; -SQLITE_DONE = 101; -SQLITE_MISMATCH = 20; -SQLITE_OK = 0; -SQLITE_TOOBIG = 18; -SQLITE_AUTH = 23; -SQLITE_NOLFS = 22; -SQLITE_PROTOCOL = 15; -SQLITE_IOERR = 10; -SQLITE_CONSTRAINT = 19; -SQLITE_NOTADB = 26; -SQLITE_MISUSE = 21; -SQLITE_RANGE = 25; -SQLITE_NOMEM = 7; -SQLITE_ERROR = 1; -SQLITE_INTERRUPT = 9; -SQLITE_NOTFOUND = 12; --- Codes -SQLITE_IOERR_BLOCKED = 2826; -SQLITE_LIMIT_EXPR_DEPTH = 3; -SQLITE_IOERR_SHMMAP = 5386; -SQLITE_ACCESS_READ = 2; -SQLITE_IOCAP_SAFE_APPEND = 512; -SQLITE_READONLY_CANTLOCK = 520; -SQLITE_CREATE_INDEX = 1; -SQLITE_STATUS_SCRATCH_SIZE = 8; -SQLITE_OPEN_MAIN_JOURNAL = 2048; -SQLITE_CREATE_VIEW = 8; -SQLITE_SET_LOCKPROXYFILE = 3; -SQLITE_CANTOPEN_NOTEMPDIR = 270; -SQLITE_NULL = 5; -SQLITE_IOCAP_ATOMIC1K = 4; -SQLITE_STATUS_PAGECACHE_OVERFLOW = 2; -SQLITE_SHM_SHARED = 4; -SQLITE_ANALYZE = 28; -SQLITE_FCNTL_WIN32_AV_RETRY = 9; -SQLITE_LOCKED_SHAREDCACHE = 262; -SQLITE_OPEN_TRANSIENT_DB = 1024; -SQLITE_TESTCTRL_ALWAYS = 13; -SQLITE_DBCONFIG_LOOKASIDE = 1001; -SQLITE_CREATE_TEMP_TRIGGER = 5; -SQLITE_IOERR_TRUNCATE = 1546; -SQLITE_IOERR_DELETE = 2570; -SQLITE_GET_LOCKPROXYFILE = 2; -SQLITE_FCNTL_SIZE_HINT = 5; -SQLITE_STATUS_SCRATCH_OVERFLOW = 4; -SQLITE_OPEN_MAIN_DB = 256; -SQLITE_STATUS_PARSER_STACK = 6; -SQLITE_OPEN_PRIVATECACHE = 262144; -SQLITE_FUNCTION = 31; -SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8; -SQLITE_IOERR_SEEK = 5642; -SQLITE_FCNTL_CHUNK_SIZE = 6; -SQLITE_DROP_TEMP_VIEW = 15; -SQLITE_DBSTATUS_LOOKASIDE_USED = 0; -SQLITE_IOCAP_POWERSAFE_OVERWRITE = 4096; -SQLITE_CONFIG_URI = 17; -SQLITE_IOERR_READ = 266; -SQLITE_ABORT = 4; -SQLITE_DBSTATUS_MAX = 9; -SQLITE_OPEN_FULLMUTEX = 65536; -SQLITE_IOCAP_ATOMIC64K = 256; -SQLITE_CREATE_TEMP_VIEW = 6; -SQLITE_ATTACH = 24; -SQLITE_CREATE_TRIGGER = 7; -SQLITE_MUTEX_FAST = 0; -SQLITE_REPLACE = 5; -SQLITE_TESTCTRL_PENDING_BYTE = 11; -SQLITE_DELETE = 9; -SQLITE_IOERR_DIR_FSYNC = 1290; -SQLITE_FCNTL_PRAGMA = 14; -SQLITE_FAIL = 3; -SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE = 5; -SQLITE_STMTSTATUS_SORT = 2; -SQLITE_IOERR_LOCK = 3850; -SQLITE_VTAB_CONSTRAINT_SUPPORT = 1; -SQLITE_CHECKPOINT_RESTART = 2; -SQLITE_OPEN_READONLY = 1; -SQLITE_CONFIG_MUTEX = 10; -SQLITE_IOCAP_ATOMIC512 = 2; -SQLITE_FCNTL_VFSNAME = 12; -SQLITE_DBSTATUS_CACHE_HIT = 7; -SQLITE_IOERR_NOMEM = 3082; -SQLITE_CHECKPOINT_PASSIVE = 0; -SQLITE_IOERR_CHECKRESERVEDLOCK = 3594; -SQLITE_IOERR_RDLOCK = 2314; -SQLITE_STMTSTATUS_AUTOINDEX = 3; -SQLITE_ROLLBACK = 1; -SQLITE_UTF16BE = 3; -SQLITE_INDEX_CONSTRAINT_GE = 32; -SQLITE_IOERR_SHMOPEN = 4618; -SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN = 2048; -SQLITE_DBSTATUS_CACHE_WRITE = 9; -SQLITE_IOCAP_ATOMIC4K = 16; -SQLITE_LIMIT_VARIABLE_NUMBER = 9; -SQLITE_DBSTATUS_CACHE_MISS = 8; -SQLITE_CHECKPOINT_FULL = 1; -SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL = 6; -SQLITE_DBSTATUS_LOOKASIDE_HIT = 4; -SQLITE_STATUS_PAGECACHE_SIZE = 7; -SQLITE_SYNC_NORMAL = 2; -SQLITE_DBSTATUS_SCHEMA_USED = 2; -SQLITE_CONFIG_SINGLETHREAD = 1; -SQLITE_LIMIT_SQL_LENGTH = 1; -SQLITE_FCNTL_FILE_POINTER = 7; -SQLITE_CREATE_TEMP_INDEX = 3; -SQLITE_READ = 20; -SQLITE_STATUS_MALLOC_COUNT = 9; -SQLITE_DBSTATUS_STMT_USED = 3; -SQLITE_SHM_EXCLUSIVE = 8; -SQLITE_INDEX_CONSTRAINT_LE = 8; -SQLITE_BUSY_RECOVERY = 261; -SQLITE_DROP_VIEW = 17; -SQLITE_TESTCTRL_PRNG_SAVE = 5; -SQLITE_OPEN_MASTER_JOURNAL = 16384; -SQLITE_PRAGMA = 19; -SQLITE_CONFIG_MALLOC = 4; -SQLITE_UTF16 = 4; -SQLITE_STATUS_MEMORY_USED = 0; -SQLITE_TESTCTRL_LAST = 19; -SQLITE_CONFIG_SERIALIZED = 3; -SQLITE_FCNTL_LOCKSTATE = 1; -SQLITE_OPEN_TEMP_DB = 512; -SQLITE_TESTCTRL_EXPLAIN_STMT = 19; -SQLITE_MUTEX_STATIC_PMEM = 7; -SQLITE_OPEN_SUBJOURNAL = 8192; -SQLITE_TESTCTRL_BITVEC_TEST = 8; -SQLITE_DROP_TRIGGER = 16; -SQLITE_ALTER_TABLE = 26; -SQLITE_IOERR_UNLOCK = 2058; -SQLITE_CONFIG_GETMALLOC = 5; -SQLITE_SHM_LOCK = 2; -SQLITE_DROP_TEMP_TABLE = 13; -SQLITE_FLOAT = 2; -SQLITE_OPEN_CREATE = 4; -SQLITE_TESTCTRL_RESERVE = 14; -SQLITE_TESTCTRL_ASSERT = 12; -SQLITE_FCNTL_OVERWRITE = 11; -SQLITE_STATUS_MALLOC_SIZE = 5; -SQLITE_OPEN_SHAREDCACHE = 131072; -SQLITE_OPEN_URI = 64; -SQLITE_TESTCTRL_SCRATCHMALLOC = 17; -SQLITE_DROP_TABLE = 11; -SQLITE_TESTCTRL_PRNG_RESET = 7; -SQLITE_CREATE_TEMP_TABLE = 4; -SQLITE_TESTCTRL_PRNG_RESTORE = 6; -SQLITE_STATUS_SCRATCH_USED = 3; -SQLITE_LIMIT_TRIGGER_DEPTH = 10; -SQLITE_MUTEX_STATIC_LRU2 = 7; -SQLITE_TESTCTRL_FIRST = 5; -SQLITE_OPEN_AUTOPROXY = 32; -SQLITE_SYNC_FULL = 3; -SQLITE_TESTCTRL_LOCALTIME_FAULT = 18; -SQLITE_TESTCTRL_FAULT_INSTALL = 9; -SQLITE_MUTEX_STATIC_PRNG = 5; -SQLITE_MUTEX_STATIC_OPEN = 4; -SQLITE_MUTEX_STATIC_MEM2 = 4; -SQLITE_TRANSACTION = 22; -SQLITE_MUTEX_STATIC_MEM = 3; -SQLITE_IOERR_DIR_CLOSE = 4362; -SQLITE_MUTEX_STATIC_MASTER = 2; -SQLITE_MUTEX_RECURSIVE = 1; -SQLITE_CREATE_VTABLE = 29; -SQLITE_CONFIG_SCRATCH = 6; -SQLITE_STMTSTATUS_FULLSCAN_STEP = 1; -SQLITE_INDEX_CONSTRAINT_LT = 16; -SQLITE_MUTEX_STATIC_LRU = 6; -SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003; -SQLITE_CONFIG_MEMSTATUS = 9; -SQLITE_BLOB = 4; -SQLITE_UTF16_ALIGNED = 8; -SQLITE_DETACH = 25; -SQLITE_STATUS_PAGECACHE_USED = 1; -SQLITE_FCNTL_PERSIST_WAL = 10; -SQLITE_IOERR_SHORT_READ = 522; -SQLITE_UTF16LE = 2; -SQLITE_UTF8 = 1; -SQLITE_TEXT = 3; -SQLITE_INDEX_CONSTRAINT_EQ = 2; -SQLITE_IOERR_SHMSIZE = 4874; -SQLITE_INSERT = 18; -SQLITE_LOCK_RESERVED = 2; -SQLITE_LIMIT_ATTACHED = 7; -SQLITE_LIMIT_COLUMN = 2; -SQLITE_IOERR_FSTAT = 1802; -SQLITE_CONFIG_LOOKASIDE = 13; -SQLITE_CONFIG_GETPCACHE2 = 19; -SQLITE_READONLY_RECOVERY = 264; -SQLITE_CONFIG_GETMUTEX = 11; -SQLITE_IOCAP_ATOMIC16K = 64; -SQLITE_LIMIT_FUNCTION_ARG = 6; -SQLITE_REINDEX = 27; -SQLITE_OPEN_READWRITE = 2; -SQLITE_COPY = 0; -SQLITE_SAVEPOINT = 32; -SQLITE_DROP_VTABLE = 30; -SQLITE_IOERR_CLOSE = 4106; -SQLITE_INDEX_CONSTRAINT_MATCH = 64; -SQLITE_ANY = 5; -SQLITE_UPDATE = 23; -SQLITE_SELECT = 21; -SQLITE_DROP_INDEX = 10; -SQLITE_INDEX_CONSTRAINT_GT = 4; -SQLITE_IOCAP_SEQUENTIAL = 1024; -SQLITE_CONFIG_PAGECACHE = 7; -SQLITE_TESTCTRL_OPTIMIZATIONS = 15; -SQLITE_IOERR_ACCESS = 3338; -SQLITE_IOCAP_ATOMIC = 1; -SQLITE_TESTCTRL_ISKEYWORD = 16; -SQLITE_IOCAP_ATOMIC32K = 128; -SQLITE_DROP_TEMP_TRIGGER = 14; -SQLITE_OPEN_WAL = 524288; -SQLITE_OPEN_EXCLUSIVE = 16; -SQLITE_CORRUPT_VTAB = 267; -SQLITE_OPEN_TEMP_JOURNAL = 4096; -SQLITE_CANTOPEN_ISDIR = 526; -SQLITE_OPEN_DELETEONCLOSE = 8; -SQLITE_CONFIG_HEAP = 8; -SQLITE_INTEGER = 1; -SQLITE_ACCESS_EXISTS = 0; -SQLITE_FCNTL_POWERSAFE_OVERWRITE = 13; -SQLITE_LIMIT_VDBE_OP = 5; -SQLITE_IOERR_FSYNC = 1034; -SQLITE_LOCK_SHARED = 1; -SQLITE_IOCAP_ATOMIC2K = 8; -SQLITE_LOCK_EXCLUSIVE = 4; -SQLITE_DBSTATUS_CACHE_USED = 1; -SQLITE_LOCK_PENDING = 3; -SQLITE_SYNC_DATAONLY = 16; -SQLITE_DENY = 1; -SQLITE_DROP_TEMP_INDEX = 12; -SQLITE_LAST_ERRNO = 4; -SQLITE_FCNTL_SYNC_OMITTED = 8; -SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS = 10; -SQLITE_CONFIG_LOG = 16; -SQLITE_OPEN_NOMUTEX = 32768; -SQLITE_DBCONFIG_ENABLE_FKEY = 1002; -SQLITE_IGNORE = 2; -SQLITE_IOERR_WRITE = 778; -SQLITE_IOERR_SHMLOCK = 5130; -SQLITE_CONFIG_MULTITHREAD = 2; -SQLITE_ABORT_ROLLBACK = 516; -SQLITE_SHM_NLOCK = 8; -SQLITE_CONFIG_PCACHE = 14; -SQLITE_LIMIT_COMPOUND_SELECT = 4; -SQLITE_ACCESS_READWRITE = 1; -SQLITE_CONFIG_PCACHE2 = 18; -SQLITE_IOCAP_ATOMIC8K = 32; -SQLITE_LOCK_NONE = 0; -SQLITE_CREATE_TABLE = 2; -SQLITE_LIMIT_LENGTH = 0; -SQLITE_CONFIG_GETPCACHE = 15; -SQLITE_SHM_UNLOCK = 1; -SQLITE_PREPARE_PERSISTENT = 0x01; -SQLITE_PREPARE_NORMALIZE = 0x02; -SQLITE_PREPARE_NO_VTAB = 0x04; -} - diff --git a/diet-sqlite/ffi.lua b/diet-sqlite/ffi.lua deleted file mode 100644 index 8368ca0..0000000 --- a/diet-sqlite/ffi.lua +++ /dev/null @@ -1,5 +0,0 @@ --- works with luajit ffi or https://github.com/q66/cffi-lua -local ok, ffi = pcall(require, "ffi") -if not ok then ffi = require "cffi" end - -return ffi diff --git a/diet-sqlite/init.fnl b/diet-sqlite/init.fnl deleted file mode 100644 index 6fab1fc..0000000 --- a/diet-sqlite/init.fnl +++ /dev/null @@ -1,67 +0,0 @@ -; This small library is based on https://github.com/Wiladams/LJIT2SQLite -; It is meant to be an _extremely_ thin wrapper around the SQLite API. - -(local sqlffi (require :diet-sqlite.sqlite3_ffi)) -(local ffi (require :diet-sqlite.ffi)) -(local util (require :lib.util)) -(local {: SQLITE_OK : SQLITE_INTEGER : SQLITE_FLOAT : SQLITE_NULL : SQLITE_BLOB : SQLITE_TEXT : SQLITE_TRANSIENT - : SQLITE_CONFIG_LOG : log_callback_type} (require :diet-sqlite.codes)) - -(local sql {:step sqlffi.sqlite3_step - :reset sqlffi.sqlite3_reset - :shutdown sqlffi.sqlite3_shutdown}) - -(fn sql.open [dbname] - (let [lpdb (ffi.new "sqlite3*[1]") - rc (sqlffi.sqlite3_open dbname lpdb) - db (. lpdb 0)] -; (when (not= db nil) (ffi.gc db sqlffi.sqlite3_close_v2)) - (values rc (. lpdb 0)))) - -(fn sql.close [db] - (ffi.gc db nil) - (sqlffi.sqlite3_close_v2 db)) - -(fn sql.prepare [db sql ?flags] - (let [ppStmt (ffi.new "sqlite3_stmt *[1]") - rc (sqlffi.sqlite3_prepare_v3 db sql -1 (or ?flags 0) ppStmt nil) - stmt (. ppStmt 0)] - (when (not= stmt nil) (ffi.gc stmt sqlffi.sqlite3_finalize)) - (values rc stmt))) - -; this exists just to have a unique object identity you can shove into a table -(set sql.null {}) - -(fn sql.bind [stmt i ?val] - (match (type i) - :table (each [ival val (ipairs i)] (sql.assert (sql.bind stmt ival val))) - :number - (match (type ?val) - :string (sqlffi.sqlite3_bind_text stmt i ?val (length ?val) SQLITE_TRANSIENT) - :number (sqlffi.sqlite3_bind_double stmt i ?val) - :nil (sqlffi.sqlite3_bind_null stmt i) - (where :table (= ?val sql.null)) (sqlffi.sqlite3_bind_null stmt i) - _ (error (.. "Don't know how to bind value " (fv ?val)))))) - -(fn sql.column [stmt icol] - (let [i (- icol 1)] ; column indexes are 0-based - (match (sqlffi.sqlite3_column_type stmt i) - SQLITE_INTEGER (sqlffi.sqlite3_column_double stmt i) - SQLITE_FLOAT (sqlffi.sqlite3_column_double stmt i) - SQLITE_NULL nil - SQLITE_TEXT (ffi.string (sqlffi.sqlite3_column_text stmt i)) - SQLITE_BLOB (error "no blob support right now") - ?unknown (error (.. "unrecognized type " ?unknown))))) - -(fn sql.columns [stmt] - (icollect [i (util.countiter (sqlffi.sqlite3_column_count stmt))] (or (sql.column stmt i) sql.null))) - -(fn sql.assert-rc [rc-expect rc ...] - (if (= rc-expect rc) ... (error (.. "Expected " rc-expect ", got " rc)))) -(fn sql.assert [...] (sql.assert-rc SQLITE_OK ...)) - -(fn sql.register-logger [logfn] - (let [callback (ffi.cast log_callback_type (fn [pArg iErrCode zMsg] (logfn (ffi.string zMsg) iErrCode)))] - (sql.assert (sqlffi.sqlite3_config SQLITE_CONFIG_LOG callback (ffi.cast "void *" nil))))) - -sql diff --git a/diet-sqlite/sqlite3_ffi.lua b/diet-sqlite/sqlite3_ffi.lua deleted file mode 100644 index 9acbadb..0000000 --- a/diet-sqlite/sqlite3_ffi.lua +++ /dev/null @@ -1,866 +0,0 @@ ---[[ -** 2001 September 15 - ** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** ---]] - -local ffi = require "diet-sqlite.ffi" - ---[[ - Created from this version: - - #define SQLITE_VERSION "3.7.12.1" - #define SQLITE_VERSION_NUMBER 3007012 - #define SQLITE_SOURCE_ID "2012-05-22 02:45:53 6d326d44fd1d626aae0e8456e5fa2049f1ce0789" ---]] - - -ffi.cdef[[ - -const char sqlite3_version[]; -const char *sqlite3_libversion(void); -const char *sqlite3_sourceid(void); -int sqlite3_libversion_number(void); - - - -int sqlite3_threadsafe(void); - - -typedef struct sqlite3 sqlite3; - - -typedef int64_t sqlite3_int64; -typedef uint64_t sqlite3_uint64; - - - - int sqlite3_close(sqlite3 *); - int sqlite3_close_v2(sqlite3 *); - - - int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluated */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - - -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; -}; - - -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); - int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); - void (*xShmBarrier)(sqlite3_file*); - int (*xShmUnmap)(sqlite3_file*, int deleteFlag); -}; - - - - - - - - -typedef struct sqlite3_mutex sqlite3_mutex; - - -typedef struct sqlite3_vfs sqlite3_vfs; -typedef void (*sqlite3_syscall_ptr)(void); -struct sqlite3_vfs { - int iVersion; - int szOsFile; - int mxPathname; - sqlite3_vfs *pNext; - const char *zName; - void *pAppData; - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - int (*xGetLastError)(sqlite3_vfs*, int, char *); - - int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); - - int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); - sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); - const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); - -}; - - - - - - - int sqlite3_initialize(void); - int sqlite3_shutdown(void); - int sqlite3_os_init(void); - int sqlite3_os_end(void); - - - int sqlite3_config(int, ...); - - - int sqlite3_db_config(sqlite3*, int op, ...); - - -typedef struct sqlite3_mem_methods sqlite3_mem_methods; -struct sqlite3_mem_methods { - void *(*xMalloc)(int); /* Memory allocation function */ - void (*xFree)(void*); /* Free a prior allocation */ - void *(*xRealloc)(void*,int); /* Resize an allocation */ - int (*xSize)(void*); /* Return the size of an allocation */ - int (*xRoundup)(int); /* Round up request size to allocation size */ - int (*xInit)(void*); /* Initialize the memory allocator */ - void (*xShutdown)(void*); /* Deinitialize the memory allocator */ - void *pAppData; /* Argument to xInit() and xShutdown() */ -}; - - - - - - - - int sqlite3_extended_result_codes(sqlite3*, int onoff); - - - sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - - - int sqlite3_changes(sqlite3*); - - - int sqlite3_total_changes(sqlite3*); - - - void sqlite3_interrupt(sqlite3*); - - - int sqlite3_complete(const char *sql); - int sqlite3_complete16(const void *sql); - - - int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - - - int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -// Legacy, don't want to use this in new code - int sqlite3_get_table( - sqlite3 *db, // An open database - const char *zSql, // SQL to be evaluated - char ***pazResult, // Results of the query - int *pnRow, // Number of result rows written here - int *pnColumn, // Number of result columns written here - char **pzErrmsg // Error msg written here -); - void sqlite3_free_table(char **result); -*/ - - char *sqlite3_mprintf(const char*,...); - char *sqlite3_vmprintf(const char*, va_list); - char *sqlite3_snprintf(int,char*,const char*, ...); - char *sqlite3_vsnprintf(int,char*,const char*, va_list); - - - void *sqlite3_malloc(int); - void *sqlite3_realloc(void*, int); - void sqlite3_free(void*); - - - sqlite3_int64 sqlite3_memory_used(void); - sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - - - void sqlite3_randomness(int N, void *P); - - -int sqlite3_set_authorizer(sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - - - - void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); - void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - - - void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - - int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - - -const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); -int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); - - - -int sqlite3_errcode(sqlite3 *db); -int sqlite3_extended_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - - -typedef struct sqlite3_stmt sqlite3_stmt; - - -int sqlite3_limit(sqlite3*, int id, int newVal); - - - - -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); - int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v3( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); - int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v3( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -const char *sqlite3_sql(sqlite3_stmt *pStmt); -int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); -int sqlite3_stmt_busy(sqlite3_stmt*); - - -typedef struct Mem sqlite3_value; - - -typedef struct sqlite3_context sqlite3_context; - - int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); - int sqlite3_bind_double(sqlite3_stmt*, int, double); - int sqlite3_bind_int(sqlite3_stmt*, int, int); - int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); - int sqlite3_bind_null(sqlite3_stmt*, int); - int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); - int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); - int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); - int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - int sqlite3_bind_parameter_count(sqlite3_stmt*); - const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - int sqlite3_clear_bindings(sqlite3_stmt*); - int sqlite3_column_count(sqlite3_stmt *pStmt); - const char *sqlite3_column_name(sqlite3_stmt*, int N); - const void *sqlite3_column_name16(sqlite3_stmt*, int N); - const char *sqlite3_column_database_name(sqlite3_stmt*,int); - const void *sqlite3_column_database_name16(sqlite3_stmt*,int); - const char *sqlite3_column_table_name(sqlite3_stmt*,int); - const void *sqlite3_column_table_name16(sqlite3_stmt*,int); - const char *sqlite3_column_origin_name(sqlite3_stmt*,int); - const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - const char *sqlite3_column_decltype(sqlite3_stmt*,int); - const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - int sqlite3_step(sqlite3_stmt*); - int sqlite3_data_count(sqlite3_stmt *pStmt); - const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); - int sqlite3_column_bytes(sqlite3_stmt*, int iCol); - int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); - double sqlite3_column_double(sqlite3_stmt*, int iCol); - int sqlite3_column_int(sqlite3_stmt*, int iCol); - sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); - const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); - const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); - int sqlite3_column_type(sqlite3_stmt*, int iCol); - sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - int sqlite3_finalize(sqlite3_stmt *pStmt); - int sqlite3_reset(sqlite3_stmt *pStmt); - - - int sqlite3_create_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - int sqlite3_create_function16( - sqlite3 *db, - const void *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - int sqlite3_create_function_v2( - sqlite3 *db, - - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void(*xDestroy)(void*) -); - - - - - - - const void *sqlite3_value_blob(sqlite3_value*); - int sqlite3_value_bytes(sqlite3_value*); - int sqlite3_value_bytes16(sqlite3_value*); - double sqlite3_value_double(sqlite3_value*); - int sqlite3_value_int(sqlite3_value*); - sqlite3_int64 sqlite3_value_int64(sqlite3_value*); - const unsigned char *sqlite3_value_text(sqlite3_value*); - const void *sqlite3_value_text16(sqlite3_value*); - const void *sqlite3_value_text16le(sqlite3_value*); - const void *sqlite3_value_text16be(sqlite3_value*); - int sqlite3_value_type(sqlite3_value*); - int sqlite3_value_numeric_type(sqlite3_value*); - - - void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - - - void *sqlite3_user_data(sqlite3_context*); - - - sqlite3 *sqlite3_context_db_handle(sqlite3_context*); - - - void *sqlite3_get_auxdata(sqlite3_context*, int N); - void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - - - - - void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); - void sqlite3_result_double(sqlite3_context*, double); - void sqlite3_result_error(sqlite3_context*, const char*, int); - void sqlite3_result_error16(sqlite3_context*, const void*, int); - void sqlite3_result_error_toobig(sqlite3_context*); - void sqlite3_result_error_nomem(sqlite3_context*); - void sqlite3_result_error_code(sqlite3_context*, int); - void sqlite3_result_int(sqlite3_context*, int); - void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); - void sqlite3_result_null(sqlite3_context*); - void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); - void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); - void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); - void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); - void sqlite3_result_value(sqlite3_context*, sqlite3_value*); - void sqlite3_result_zeroblob(sqlite3_context*, int n); - - - int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) -); - int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); - int sqlite3_create_collation16( - sqlite3*, - const void *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) -); - - - int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); - int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - - - - - int sqlite3_sleep(int); - - - char *sqlite3_temp_directory; - - - int sqlite3_get_autocommit(sqlite3*); - - - sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - - const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); - - int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); - - - sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); - - - void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); - void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - - - void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - - - int sqlite3_enable_shared_cache(int); - - - int sqlite3_release_memory(int); - - - int sqlite3_db_release_memory(sqlite3*); - - - sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); - - - int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - - - int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - - - int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - - - int sqlite3_auto_extension(void (*xEntryPoint)(void)); - - - void sqlite3_reset_auto_extension(void); - - - - -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - - -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); - /* The methods above are in version 1 of the sqlite_module object. Those - ** below are for version 2 and greater. */ - int (*xSavepoint)(sqlite3_vtab *pVTab, int); - int (*xRelease)(sqlite3_vtab *pVTab, int); - int (*xRollbackTo)(sqlite3_vtab *pVTab, int); -}; - - -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; - - - - - - int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData /* Client data for xCreate/xConnect */ -); - int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - - -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* NO LONGER USED */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - - -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - - - int sqlite3_declare_vtab(sqlite3*, const char *zSQL); - - - int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - - - - -typedef struct sqlite3_blob sqlite3_blob; - - - int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - - - int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); - - - int sqlite3_blob_close(sqlite3_blob *); - - - int sqlite3_blob_bytes(sqlite3_blob *); - - - int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); - - - int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - - - sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); - int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); - int sqlite3_vfs_unregister(sqlite3_vfs*); - - - sqlite3_mutex *sqlite3_mutex_alloc(int); - void sqlite3_mutex_free(sqlite3_mutex*); - void sqlite3_mutex_enter(sqlite3_mutex*); - int sqlite3_mutex_try(sqlite3_mutex*); - void sqlite3_mutex_leave(sqlite3_mutex*); - - -typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; -struct sqlite3_mutex_methods { - int (*xMutexInit)(void); - int (*xMutexEnd)(void); - sqlite3_mutex *(*xMutexAlloc)(int); - void (*xMutexFree)(sqlite3_mutex *); - void (*xMutexEnter)(sqlite3_mutex *); - int (*xMutexTry)(sqlite3_mutex *); - void (*xMutexLeave)(sqlite3_mutex *); - int (*xMutexHeld)(sqlite3_mutex *); - int (*xMutexNotheld)(sqlite3_mutex *); -}; - - - - - - sqlite3_mutex *sqlite3_db_mutex(sqlite3*); - - int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - - - int sqlite3_test_control(int op, ...); - - - - int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); - - - int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); - - - - - - int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); - - - - - -typedef struct sqlite3_pcache sqlite3_pcache; - - -typedef struct sqlite3_pcache_page sqlite3_pcache_page; -struct sqlite3_pcache_page { - void *pBuf; /* The content of the page */ - void *pExtra; /* Extra information associated with the page */ -}; - - -typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; -struct sqlite3_pcache_methods2 { - int iVersion; - void *pArg; - int (*xInit)(void*); - void (*xShutdown)(void*); - sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); - void (*xCachesize)(sqlite3_pcache*, int nCachesize); - int (*xPagecount)(sqlite3_pcache*); - sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); - void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); - void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, - unsigned oldKey, unsigned newKey); - void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); - void (*xDestroy)(sqlite3_pcache*); - void (*xShrink)(sqlite3_pcache*); -}; - - - - -typedef struct sqlite3_backup sqlite3_backup; - - - sqlite3_backup *sqlite3_backup_init( - sqlite3 *pDest, /* Destination database handle */ - const char *zDestName, /* Destination database name */ - sqlite3 *pSource, /* Source database handle */ - const char *zSourceName /* Source database name */ -); - int sqlite3_backup_step(sqlite3_backup *p, int nPage); - int sqlite3_backup_finish(sqlite3_backup *p); - int sqlite3_backup_remaining(sqlite3_backup *p); - int sqlite3_backup_pagecount(sqlite3_backup *p); - - - int sqlite3_unlock_notify( - sqlite3 *pBlocked, /* Waiting connection */ - void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ - void *pNotifyArg /* Argument to pass to xNotify */ -); - - - - int sqlite3_stricmp(const char *, const char *); - int sqlite3_strnicmp(const char *, const char *, int); - - - void sqlite3_log(int iErrCode, const char *zFormat, ...); - - - void *sqlite3_wal_hook( - sqlite3*, - int(*)(void *,sqlite3*,const char*,int), - void* -); - - - int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); - - - int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); - - - int sqlite3_wal_checkpoint_v2( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of attached database (or NULL) */ - int eMode, /* SQLITE_CHECKPOINT_* value */ - int *pnLog, /* OUT: Size of WAL log in frames */ - int *pnCkpt /* OUT: Total number of frames checkpointed */ -); - - - int sqlite3_vtab_config(sqlite3*, int op, ...); - - int sqlite3_vtab_on_conflict(sqlite3 *); - - - - - - -// RTree Geometry Queries -typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; - - - int sqlite3_rtree_geometry_callback( - sqlite3 *db, - const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), - void *pContext -); - - -struct sqlite3_rtree_geometry { - void *pContext; - int nParam; - double *aParam; - void *pUser; - void (*xDelUser)(void *); -}; -]] - -local Lib = ffi.load(ffi.os == "Windows" and "bin/sqlite3" or "sqlite3") - -return Lib; - diff --git a/game/init.fnl b/game/init.fnl index 12efa60..a9396ba 100644 --- a/game/init.fnl +++ b/game/init.fnl @@ -15,16 +15,12 @@ (modes:register :game gamemode) -(set state.entities [(bomberman.new [48 48]) (pacman.new [112 112])]) -(set state.map (map.new-tilemap 28 31 tile.bombertile (tile.itile-named tile.bombertile :empty))) -(set state.bombs (map.new-entitymap state.map.w state.map.h)) -(rules.generate-maze state.map) +(rules.reset-game) (command.add nil { "love:game" (fn [] (let [node (core.root_view:get_active_node)] (node:add_view (ModeView gamemode)))) - "love:regenerate-maze" #(rules.generate-maze state.map) }) {} diff --git a/game/mode.fnl b/game/mode.fnl index 1dabd9f..8b9d81d 100644 --- a/game/mode.fnl +++ b/game/mode.fnl @@ -2,12 +2,11 @@ (local state (require :game.state)) (local map (require :game.tilemap)) (local rules (require :game.rules)) +(local tiles (require :game.tiles)) +(local dim (require :game.dim)) (local {: draw : update} (util.require :game.entity)) -(fn game-update [dt] - (map.update-entitymap state.bombs dt rules) - (each [_ entity (ipairs state.entities)] - (update entity dt rules))) +(fn game-update [dt]) (fn exception-update [dt] (when (love.keyboard.isDown :f2) @@ -20,9 +19,8 @@ (set state.update-exception (.. msg "\n" (debug.traceback))))))) (fn game-draw [] - (map.draw-tilemaps 0 0 [state.bombs state.map]) - (each [_ entity (ipairs state.entities)] - (draw entity))) + (map.draw-tilemap (* dim.tilesize 5) 0 state.well tiles.tetristile) + (map.draw-tilemap (/ dim.tilesize 2) dim.tilesize (rules.tetromino state.next-piece 1) tiles.tetristile)) (fn exception-draw [] (love.graphics.setColor 1 0 0 1) diff --git a/game/rules.fnl b/game/rules.fnl index e890d3e..04a8bc0 100644 --- a/game/rules.fnl +++ b/game/rules.fnl @@ -2,55 +2,95 @@ (local map (require :game.tilemap)) (local tileset (require :game.tiles)) (local state (require :game.state)) -(local Bomb (require :game.entities.bomb)) (local Rules {}) -(fn Rules.tile-at [[x y]] - (map.tile-at-overlay x y [state.bombs state.map])) -(local tile-at Rules.tile-at) +(local tetrominoes + {:O [["##" + "##"]] -(fn Rules.place-bomb [[x y]] - (when (. (tile-at [x y]) :empty) - (map.set-entity-at x y state.bombs (Bomb.new)))) + :L [["###" + "# "] -(fn Rules.clear-bomb [bomb] - (map.remove-entity state.bombs bomb)) + ["# " + "# " + "##"] -(fn explode-in-dir [x y dx dy len] - (when (and (>= x 0) (< x state.map.w) (>= y 0) (< y state.map.h)) - (let [tile (tile-at [x y])] - (if tile.empty - (do (map.set-entity-at x y state.bombs (Bomb.new-explosion)) - (when (> len 0) - (explode-in-dir (+ x dx) (+ y dy) dx dy (- len 1)))) + [" #" + "###"] - (= tile.state :ticking) - (Bomb.explode tile Rules) + ["##" + " #" + " #"]] - tile.breakable - (map.set-itile-at x y state.map (tileset.itile-named state.map.tileset :empty)))))) + :J [["###" + " #"] -(fn Rules.explode-bomb [bomb] - (each [_ [dx dy] (ipairs [[-1 0] [1 0] [0 -1] [0 1]])] - (explode-in-dir (+ bomb.x dx) (+ bomb.y dy) dx dy 1))) + ["##" + "# " + "# "] -(fn Rules.generate-maze [tilemap] - (let [empty (tileset.itile-named tilemap.tileset :empty) - wall (tileset.itile-named tilemap.tileset :strongwall) - weak (tileset.itile-named tilemap.tileset :weakwall)] - (for [x 0 (- tilemap.w 1)] (for [y 0 (- tilemap.h 1)] - (map.set-itile-at x y tilemap - (if (or (= y 0) (= y (- tilemap.h 1)) (= x 0) (= x (- tilemap.w 1))) - wall + ["# " + "###"] - (and (= (% x 2) 0) (= (% y 2) 0)) - wall + [" #" + " #" + "##"]] - (< (math.random) 0.3) - weak + :I [["####"] - empty)))))) + ["#" + "#" + "#" + "#"]] + + :S [[" ##" + "## "] + + ["# " + "##" + " #"]] + + :Z [["## " + " ##"] + + [" #" + "##" + "# "]] + + :T [["###" + " # "] + + ["# " + "##" + "# "] + + [" # " + "###"] + + [" #" + "##" + " #"]]}) + +(fn Rules.choose-random-tetromino [] + (let [possible-values (icollect [k (pairs state.tetrominoes)] k) + ivalue (love.math.random (length possible-values))] + (. possible-values ivalue))) + +(fn Rules.reset-game [] + (set state.tetrominoes tetrominoes) + (set state.well (map.new-tilemap 12 21)) + (for [y 0 19] + (map.set-itile-at 0 y state.well "X") + (map.set-itile-at 11 y state.well "X")) + (for [x 0 11] + (map.set-itile-at x 20 state.well "X")) + (set state.next-piece (Rules.choose-random-tetromino))) + +(fn Rules.tetromino [k irotation] + (let [rotations (or (. state.tetrominoes k) [["##" "##"]]) + irotation (+ (% (- irotation 1) (length rotations)) 1)] + (. rotations irotation))) Rules diff --git a/game/tilemap.fnl b/game/tilemap.fnl index 1f02285..c1385de 100644 --- a/game/tilemap.fnl +++ b/game/tilemap.fnl @@ -9,65 +9,44 @@ (defmethod drawtile :default #nil) (fn itile-at [x y tilemap] - (-?> tilemap (. y) (. x))) + (let [itile (-?> tilemap (. (+ y 1)) (: :sub (+ x 1) (+ x 1)))] + (if (or (= itile nil) (= itile "")) " " itile))) -(fn tile-at [x y tilemap] +(fn tile-at [x y tilemap tileset] (let [itile (itile-at x y tilemap)] (match (type itile) - :number (. tilemap.tileset itile) + :string (. tileset itile) :table itile))) (fn set-itile-at [x y tilemap itile] - (when (= nil (. tilemap y)) - (tset tilemap y [])) - (tset (. tilemap y) x itile)) + (let [row (or (. tilemap (+ y 1)) "") + row (.. row (string.rep " " (math.max 0 (- x (length row))))) + pre (row:sub 1 (- x 1)) + post (row:sub (+ x 1)) + row (.. pre itile post)] + (tset tilemap (+ y 1) row))) -(fn tile-at-overlay [x y tilemaps ?itilemap] - (let [itilemap (or ?itilemap 1) - tilemap (. tilemaps itilemap)] - (when tilemap - (let [tile (tile-at x y tilemap)] - (if (= tile nil) - (tile-at-overlay x y tilemaps (+ itilemap 1)) - (values tile tilemap)))))) - -(fn new-tilemap [w h tileset ?itile] - (local tilemap {: w : h : tileset}) +(fn new-tilemap [w h ?itile] + (local tilemap []) (when (not= ?itile nil) (each [x y (all-coordinates w h)] - (set-itile-at x y tilemap ?itile))) + (set-itile-at x y tilemap (or ?itile " ")))) tilemap) -(fn new-entitymap [w h] - {: w : h :entities []}) - -(fn set-entity-at [x y tilemap entity] - (set entity.x x) - (set entity.y y) - (table.insert tilemap.entities entity) - (set-itile-at x y tilemap entity)) - -(fn remove-entity [tilemap entity] - (lume.remove tilemap.entities entity) - (set-itile-at entity.x entity.y tilemap)) - -(fn draw-tilemaps [x y tilemaps] - (local base-tilemap (. tilemaps (length tilemaps))) - (each [tx ty (all-coordinates base-tilemap.w base-tilemap.h)] - (let [(tile tilemap) (tile-at-overlay tx ty tilemaps) - xt (+ x (* tx dim.tilesize) (/ dim.tilesize 2)) - yt (+ y (* ty dim.tilesize) (/ dim.tilesize 2))] - (drawtile tile xt yt)))) - -(fn update-entitymap [tilemap ...] - (each [_ entity (ipairs (lume.clone tilemap.entities))] - (update entity ...))) +(fn draw-tilemap [x y tilemap tileset] + (each [irow row (ipairs tilemap)] + (for [icol 1 (length row)] + (let [tx (- icol 1) + ty (- irow 1) + tile (tile-at tx ty tilemap tileset) + xt (+ x (* tx dim.tilesize) (/ dim.tilesize 2)) + yt (+ y (* ty dim.tilesize) (/ dim.tilesize 2))] + (drawtile tile xt yt))))) (fn world-to-tile [vec] (-> vec ((vec-op #(math.floor (/ $1 dim.tilesize)))))) -{: new-tilemap : itile-at : tile-at : set-itile-at : tile-at-overlay : draw-tilemaps - : new-entitymap : set-entity-at : remove-entity : update-entitymap +{: new-tilemap : itile-at : tile-at : set-itile-at : draw-tilemap : world-to-tile : drawtile} diff --git a/game/tiles.fnl b/game/tiles.fnl index ddaeca3..3f14b50 100644 --- a/game/tiles.fnl +++ b/game/tiles.fnl @@ -11,31 +11,17 @@ (- y (/ dim.tilesize 2)) dim.tilesize dim.tilesize)) -(fn tileset.make-tileset [tiles] - (each [itile tile (ipairs tiles)] - (tset tiles tile.name itile)) - tiles) -(fn tileset.itile-named [tileset name] - (. tileset name)) +(defmethod drawtile :wall (fn [tile x y] (rect x y [0.7 0.7 0.7]))) +(defmethod drawtile :block (fn [tile x y] (rect x y [0.4 0.4 0.4]))) -(defmethod drawtile :strongwall (fn [tile x y] (rect x y [0.7 0.7 0.7]))) -(defmethod drawtile :weakwall (fn [tile x y] (rect x y [0.4 0.4 0.4]))) -(defmethod drawtile :dot (fn [tile x y] - (love.graphics.setColor 1 1 1) - (love.graphics.circle :fill x y (/ dim.tilesize 8)))) - -(set tileset.bombertile (tileset.make-tileset - [{:name :empty - :empty true} - {:name :strongwall - :wall true} - {:name :weakwall - :wall true - :breakable true} - {:name :dot - :edible true} - ])) +(set tileset.tetristile + {" " {:name :empty + :empty true} + "X" {:name :wall + :wall true} + "#" {:name :block + :wall true}}) tileset.hot diff --git a/gneiss/cpu.fnl b/gneiss/cpu.fnl deleted file mode 100644 index eba7b3c..0000000 --- a/gneiss/cpu.fnl +++ /dev/null @@ -1,99 +0,0 @@ -(local Sqlog (require :sqlog)) -(import-macros {: $ : specify : query} :sqlog.macros) - -(fn nextval [varname] ($ (+ (coalesce (max ,[:var varname]) 0) 1))) - -(local Cpu {}) -(fn Cpu.new [self ?filename] - (set self.sqlog (Sqlog ?filename)) - (set self.instructions []) - (self:init-new-db)) - -(fn Cpu.init-new-db [self] - "Initialize a fresh database with the necessary tables and rules." - (specify self.sqlog - ; cpu layout: - (table cpu.running process-id) - [cpu.running 0] ; 0 means nothing - (table cpu.fp process-id frame-id) - (table cpu.frame frame-id var-id value) - (table cpu.program program-id instruction-id instruction) - ; special frame variables: - ; $result - the anonymous result of the most recent computation (useful?) - ; $fp-return - the frame-id to return to when finished - ; $program - the id of the program that the frame is referencing - ; $ip - the id of the instruction within the program that the process is executing - - ; function calls create a new frame by incrementing cpu.next-fp and populating cpu.frame. - ; returning from a function call sets the $result of $fp-return to the $result of the current frame, - ; sets cpu.fp for the current process to $fp-return, and removes all data from cpu.frame with the current frame ID. - (table compiler.sourcemap program-id instruction-id filename position) - - (* [cpu.next-process ,(nextval :process-id)] [cpu.fp process-id _]) - (* [cpu.next-fp ,(nextval :frame-id)] [cpu.frame frame-id _ _]) - (* [cpu.next-program-id ,(nextval :program-id)] [cpu.program program-id _ _ _]) - (* [cpu.next-instruction-id program-id ,(nextval :instruction-id)] [cpu.program program-id instruction-id _ _]) - (* [cpu.next-instruction-id next-program-id 1] [cpu.next-program-id next-program-id]) - (* [cpu.frame-var var-id value] [cpu.running process-id] [cpu.fp process-id frame-id] [cpu.frame frame-id var-id value]) - (* [cpu.my-fp fp] [cpu.running pid] [cpu.fp pid fp]) - (* [cpu.ip program-id ip] [cpu.frame-var :$ip ip] [cpu.frame-var :$program program-id]) - (* [cpu.instruction instruction] [cpu.ip program-id ip] [cpu.program program-id ip instruction]) - (* [cpu.return-fp fp] [cpu.frame-var :$fp-return fp]) - - ; frame 1 destroys all processes that enter it (program 1 will implement this logic) - [cpu.frame 1 :$ip 1] - [cpu.frame 1 :$program 1]) - - ; define program 1 for frame 1 - (self:insert-program ($ - (!- [cpu.fp _ 1]) - (!= [cpu.frame _ _ 0] [cpu.frame 1 :$ip _]))) ; this shouldn't be needed - - (set self.ret - (self:def-instruction - ($ (!= [cpu.fp _ fp-return] [cpu.fp pid _] [cpu.running pid] [cpu.return-fp fp-return]))))) - -(fn Cpu.def-instruction [self ...] - "Creates a new reusable instruction and returns its ID" - (let [analysis (self.sqlog:compile-action [:do ...])] - (table.insert self.instructions analysis) - (length self.instructions))) - -(fn Cpu.insert-program [self ...] - "Creates a new program with the specified instructions" - (let [[{: program-id}] (query self.sqlog [cpu.next-program-id program-id])] - (each [ip action (ipairs [...])] - (let [instruction (if (not= (type action) :table) action (self:def-instruction action))] - (specify self.sqlog [cpu.program #program-id #ip #instruction]))) - program-id)) - -(fn Cpu.initialize-process [self program-id] - "Creates a new process, starting at the beginning of the specified program" - (let [[{: process-id : fp}] (query self.sqlog [cpu.next-process process-id] [cpu.next-fp fp])] - (specify self.sqlog - (!+ [cpu.fp #process-id #fp]) - (!+ [cpu.frame #fp :$program #program-id]) - (!+ [cpu.frame #fp :$ip 1]) - (!+ [cpu.frame #fp :$fp-return 1])))) - -(fn Cpu.process-round [self] - "Executes each currently-active process until it hits a suspend instruction or is removed." - (let [process-ids (query self.sqlog [cpu.fp process-id _])] - (each [_ {: process-id} (ipairs process-ids)] - (specify self.sqlog (!= [cpu.running #process-id] [cpu.running _])) - (var done false) - (while (not done) - (let [[instruction-result] (query self.sqlog [cpu.instruction instruction]) - {: instruction} (or instruction-result {}) - action (and instruction (. self.instructions instruction))] - (if (= action nil) (set done true) - (= (type action) :function) (action self) - (self.sqlog:execute action)) - (specify self.sqlog (!= [cpu.frame _ _ (+ ip 1)] [cpu.frame fp :$ip ip] [cpu.fp #process-id fp]))))) - (specify self.sqlog (!= [cpu.running 0] [cpu.running _])) - process-ids)) - -(fn Cpu.run [self] (while (> (length (self:process-round)) 0))) - -(setmetatable Cpu {:__call (fn [cls ...] (doto (setmetatable {} {:__index cls}) (: :new ...)))}) - diff --git a/gneiss/example.fnl b/gneiss/example.fnl deleted file mode 100644 index a9f09b2..0000000 --- a/gneiss/example.fnl +++ /dev/null @@ -1,34 +0,0 @@ -(local Cpu (require :gneiss.cpu)) -(local {: show} (require :inspector.debug)) -(local sql (require :diet-sqlite)) -(import-macros {: $ : query : specify} :sqlog.macros) - -(sql.shutdown) -; (sql.register-logger #(print "SQL:" $2 $1)) - -(local cpu (Cpu)) - -(macro divisible-by [val denominator] - `($ (= (% ,val ,denominator) 0))) - -(pp (divisible-by i 3)) - -(specify cpu.sqlog - (table fizzbuzz i fizzbuzz)) - -(let [pgid (cpu:insert-program ($ - (do ; 1 - (!+ [cpu.frame fp :i 1] [cpu.my-fp fp])) ; ideally: (!+ [cpu.frame-var :i 1]) - (do ;2 - (!+ [fizzbuzz i (case (when (and ,(divisible-by i 3) ,(divisible-by i 5)) :fizzbuzz) - (when ,(divisible-by i 3) :fizz) - (when ,(divisible-by i 5) :buzz) - (else i))] [cpu.frame-var :i i]) - (!= [cpu.frame _ _ (+ i 1)] [cpu.frame fp :i i] [cpu.my-fp fp]) ; ideally: (!= [cpu.frame-var :i 1])? - (!= [cpu.frame _ _ 1] [cpu.frame fp :$ip _] [cpu.my-fp fp] [cpu.frame-var :i i] (< i 100))) ; if i < 100 goto 2 - ,cpu.ret)) - pid (cpu:initialize-process pgid)] - (cpu:run) - (show (query cpu.sqlog [fizzbuzz i fizzbuzz]))) - -{} diff --git a/sqlog/compiler.fnl b/sqlog/compiler.fnl deleted file mode 100644 index 5265302..0000000 --- a/sqlog/compiler.fnl +++ /dev/null @@ -1,289 +0,0 @@ -; sqlog, a datalog-like system built on sqlite -; may not actually have the full power of datalog OR the full power of sqlite - -; datalog has a database of facts, and rules. facts are represented in sqlite directly as tables. -; rules are used by the sqlog engine when generating queries; typically they take the form -; of subqueries used in the WITH RECURSIVE clause. -; It would be possible to store them as views, but the view would need to be regenerated from -; its base rules anytime there is a change, so sqlog needs to know about them no matter what. -; Making sqlog manage them in-memory also allows us to use it to query arbitrary sqlite databases. - -; Ideally we would persist rules as JSON in a special table; maybe sqlog_rules? - -(local Compiler {}) - -; Generating SQL from Datalog should not be too complex, but it pays to start with the simplest -; case and build up from there. - -; simple queries: -; [p x y] -> SELECT p.c1 AS x, p.c2 AS y FROM p -; [p 1 y] -> SELECT p.c2 AS y FROM p WHERE p.c1 = 1 -; [q x] [p x 1] -> SELECT q.c1 AS x FROM q JOIN p WHERE p.c1 = q.c1 AND p.c2 = 1 -; [p 1 2] -> SELECT true FROM p WHERE p.c1 = 1 AND p.c2 = 2 -; [p 1 x] [p x 2] -> SELECT t1.c2 AS x FROM p AS t1 JOIN p AS t2 WHERE t1.c1 = 1 AND t1.c2 = t2.c1 AND t2.c2 = 2 - -; queries using rules: -; ([ancestor x y] [parent x y]) -> SELECT p.c1 AS x, p.c2 AS y FROM parent AS p -; ([ancestor x y] [parent x z] [ancestor z y]) -> SELECT p.c1 AS x, a.y AS y FROM parent AS p JOIN ancestor AS a WHERE p.c1 = a.x AND p.c2 = a.y -; [ancestor x :john] -> WITH RECURSIVE ancestor(x, y) AS (SELECT ... UNION SELECT ...) SELECT a.c1 AS x FROM ancestor AS a WHERE a.y = 'john' -; ([ancestor :bob x] [ancestor x :john]) -> SELECT 'bob' AS c1, a.c1 AS c2 FROM ancestor AS a WHERE a.c2 = 'john' - -; queries with arithmetic operations (function calls?) -; [p x y] [q (+ x 1)] -> SELECT p.c1 AS x, p.c2 AS y FROM p JOIN q WHERE q.c1 = p.c1 + 1 -; [p (+ x 1) y] [q x] -> SELECT q.c1 AS x, p.c2 AS y FROM p JOIN q WHERE p.c1 = q.c1 + 1 -; [p (+ x 1) x] -> SELECT p.c2 AS x FROM p WHERE p.c1 = p.c2 + 1 - -; queries with comparisons -; [p x y] (< x 5) -> SELECT p.c1 AS x, p.c2 AS y FROM p WHERE p.c1 < 5 -; [p x y] (= x y) -> unnecessary but supported, can be written (p x x) -; [p x y] (= x (+ y 1)) -> unnecessary but supported, can be written (p (+ x 1) x)? - -; confusing expressions we probably won't support: -; [p (+ x 1) (* x 2)] -> SELECT p.c1 - 1 AS x FROM p WHERE p.c1 + 1 = p.c2 * 2?? -; no, that's not right - this says x+1 = c1 AND x*2 = c2 -; [p (+ x 1) (* x 2)] -> SELECT p.c1 - 1 AS x FROM p WHERE p.c2 = (p.c1 - 1) * 2 -; [p (+ x 1) y] -> meaningless? or... -; -> SELECT p.c1 - 1 AS x, p.c2 AS y FROM p -; is there a way to trick sql into generating x = p.c1 - 1 from p.c1 = x + 1? -; [p z y] (= z (+ x 1)) - -; unsupported: inline comparisons -; [p (< x 5) y] -> SELECT p.c1 AS x, p.c2 AS y FROM p WHERE p.c1 < 5 -- does this make sense? seems hard to read, hard to parse - -; insert: -; [p 1 2] -> INSERT INTO p (c1, c2) VALUES (1, 2) -; [p 1 (+ 2 3)] -> INSERT INTO p (c1, c2) VALUES (1, 2 + 3) -; (!+ [p (+ x 1) 3] [q x]) -> INSERT INTO p (c1, c2) SELECT q.c1 + 1 AS c1, 3 AS c2 FROM q - -; delete: -; (!- [p _ _]) -> DELETE FROM p -; (!- [p 1 _]) -> DELETE FROM p WHERE p.c1 = 1 -; augh sqlite doesn't support joins on delete! The most generic solution: -; (!- [p 1 x] [q x]) -> DELETE FROM p WHERE p._rowid_ IN (SELECT p._rowid_ FROM p JOIN q WHERE p.c1 = 1 AND p.c2 = q.c1) - -; update: -; (!= [q (+ x 1)] [q x]) -> UPDATE q SET c1 = q.c1 + 1 -; (!= [p (+ x 1) _] [p x 3]) -> UPDATE p SET c1 = p.c1 + 1 WHERE p.c2 = 3 -; invalid update: -; (!= [p (+ x 1) _] [q x]) -> UPDATE p SET c1 = q.c1 + 1 FROM q -- this is valid sql, but it's madness - enforce the first query clause matches table - -(fn cat [list sep ?f] - "Join all the elements in list with the string sep. If ?f is supplied, it is called to transform each value in the list into a new value first." - (table.concat (icollect [i v (ipairs list)] ((or ?f #$1) v i)) sep)) - -(fn any [list pred] - "Returns true if the supplied predicate function returns true for any values in list." - (var found false) - (each [_ v (ipairs list) :until found] (set found (pred v))) - found) - -(fn append-if-missing [list value] - "Adds value to the end of list if it is not currently included." - (when (not (any list #(= $1 value))) - (table.insert list value))) - -(fn countiter [max] - "An iterator that counts from 1 to max, inclusive." - (fn [_ iprev] - (let [i (if iprev (+ iprev 1) 1)] - (when (<= i max) i)))) - -(fn quoteid [name] (.. "\"" (name:gsub "\"" "\"\"") "\"")) - -(fn Compiler.new [self] - (set self.tables {}) - (set self.rules {})) - -(fn Compiler.deftable [self name ...] - "Defines the column names of a table and their expected ordering" - (when (. name self.rules) (error "tables and rules must not overlap")) - (tset self.tables name [...]) - {:query (.. "CREATE TABLE " (quoteid name) "(" (cat [...] ", " quoteid) - ", PRIMARY KEY (" (cat [...] ", " quoteid) "))") - :constants [] - :selection []}) - -(fn Compiler.defrule [self head ...] - "Defines a new rule or expands the definition of an existing rule." - (match head - [:literal name] (let [rulelist (or (. self.rules name) [])] - (table.insert rulelist [head ...]) - (tset self.rules name rulelist)) - _ (error "Expected literal for head, got " (fv head)))) - -(fn new-analysis [?parent] - "Creates a new empty analysis object. If ?parent is supplied, share the list of constants and referenced rules, as these are shared - with the full SQL expression." - {:variables [] ; list of all variable names referenced; used to determine which values to return from a query - :variable-mapping {} ; a mapping from variable name to a SQL expr to which it is equal - :selection [] ; list of all columns being selected, generally of the form [:as expr name] - :clauses [] ; list of WHERE clauses, to be joined together by AND - :tables [] ; list of tables or rules queried. (. tables 1) is generally aliased to _t1. All tables are inner joined. - :constants (or (?. ?parent :constants) []) ; list of constant values to be bound to the prepared SQL expression - :referenced-rules (or (?. ?parent :referenced-rules) [])}) ; list of all rules referenced by this expression, so they can be included - -(fn add-clause [analysis clause] (table.insert analysis.clauses clause)) - -(fn Compiler.reference-name [self analysis name] - "Called when a query references a new table. Appends the table or rule name to the end of analysis.tables - and returns the index of the new value. Also updates analysis.referenced-rules as needed." - (if (or (. self.rules name) (. self.tables name)) - (do (table.insert analysis.tables name) - (when (. self.rules name) - (append-if-missing analysis.referenced-rules name)) - (length analysis.tables)) - (error (.. "Unknown table / rule " name)))) - -(fn Compiler.reference-variable [self analysis varname expr] - "Called when a query expression (expr) is known to be equal to the value of varname - usually because - the variable appears in the position of a particular rule or column. Defines a mapping from variable - to expression if none exists, otherwise adds a new clause testing that the original mapping is equal - to this new mapping, implementing unification." - (when (not= varname :_) - (match (. analysis.variable-mapping varname) - mapping (add-clause analysis [:= mapping expr]) - nil (do (tset analysis.variable-mapping varname expr) - (table.insert analysis.variables varname))))) - -; These are SQL functions that return boolean values and can be used as a standalone clause. -(local comparitors (collect [_ op (ipairs [:< :> :<= :>= := :and :or])] op true)) -(fn Compiler.analyze-literal [self analysis literal] - "Adds a literal of the form [table expr expr expr...] or a comparison expression of the form (op expr expr) to - the analysis object. Typically this implies a join and some number of WHERE clauses." - (match literal - [:literal name params] (let [itable (self:reference-name analysis name)] - (each [icolumn value (ipairs params)] - (match value - [:var varname] (self:reference-variable analysis varname [:column itable icolumn]) - [:const val] (add-clause analysis [:= [:column itable icolumn] [:const val]]) - (where [op] (= (. comparitors op) nil)) (add-clause analysis [:= [:column itable icolumn] value]) - _ (error (.. "expected var, const, or function, got " (fv value)))))) - (where [op] (. comparitors op)) (add-clause analysis literal) - _ (error (.. "Expected literal or comparison but got " (fv literal))))) - -(local infix-ops (collect [_ op (ipairs [:+ :- :* :/ :< :> :<= :>= := :|| :and :or :%])] op true)) -(fn Compiler.gen-expr [self analysis expr] - "Generates SQL code for a given expression tree." - (match expr - [:const val] (do (table.insert analysis.constants val) "?") - [:column itable icolumn] (.. "_t" itable "." - (match (. self.tables (. analysis.tables itable)) - colnames (quoteid (. colnames icolumn)) - _ (.. "c" icolumn))) - [:rowid itable] (.. "_t" itable "._rowid_") - [:as subexpr name] (.. (self:gen-expr analysis subexpr) " AS " (quoteid name)) - [:set column subexpr] (.. (quoteid column) " = " (self:gen-expr analysis subexpr)) - [:case & clauses] (.. "CASE " (cat clauses " " #(self:gen-expr analysis $1)) " END") - [:when cmp result] (.. "WHEN " (self:gen-expr analysis cmp) " THEN " (self:gen-expr analysis result)) - [:else result] (.. "ELSE " (self:gen-expr analysis result)) - (where [:var name] (. analysis.variable-mapping name)) (self:gen-expr analysis (. analysis.variable-mapping name)) - (where [op lhs rhs] (. infix-ops op)) (.. "(" (self:gen-expr analysis lhs) " " op " " (self:gen-expr analysis rhs) ")") - [funcname & args] (.. funcname "(" (cat args ", " #(self:gen-expr analysis $1)) ")") - _ (error (.. "Unrecognized expression " (fv expr))))) - -(fn Compiler.gen-rule-clause [self analysis-parent [head & literals]] - "Generates a SELECT statement for a given rule (potentially in a family of rules with the same name to be unioned together)" - (let [analysis (new-analysis analysis-parent)] - (each [_ literal (ipairs literals)] (self:analyze-literal analysis literal)) - (match head - [:literal name params] - (set analysis.selection (icollect [icolumn param (ipairs params)] [:as param (.. :c icolumn)])) - _ (error (.. "Expected literal, got " (fv head)))) - (self:gen-select analysis))) - -(fn Compiler.gen-rule [self analysis name] - "Generates a full expression for a rule family with the given name, to be placed in a WITH RECURSIVE block." - (let [rule (. self.rules name) - column-count (match rule - [[[:literal _ clauses]]] (length clauses) - _ (error (.. "Rule should be list of list of literals, was " (fv rule))))] - (.. (quoteid name) "(" (table.concat (icollect [i (countiter column-count)] (.. "c" i)) ", ") ") AS NOT MATERIALIZED (" - (cat rule " UNION " #(self:gen-rule-clause analysis $1)) ")"))) - -(fn Compiler.gen-with-rules [self analysis] - "Generates a WITH block containing all of the referenced rules found during analysis. Will append to the referenced-rules list - as needed if rules depend on other rules, and only return when all requirements are satisfied." - (let [rulequeries []] - ; ipairs will iterate over all referenced-rules even if gen-rule causes more to be appended - (each [_ name (ipairs analysis.referenced-rules)] - (table.insert rulequeries (self:gen-rule analysis name))) - (if (> (length rulequeries) 0) - (.. "WITH RECURSIVE " (cat rulequeries ", ") " ") - ""))) - -(fn Compiler.gen-select [self analysis] - "Generates a SELECT statement for the query defined by analysis." - (.. "SELECT " - (if (> (length analysis.selection) 0) - (cat analysis.selection ", " #(self:gen-expr analysis $1)) - "true") - (if (> (length analysis.tables) 0) - (.. " FROM " (cat analysis.tables " JOIN " #(.. (quoteid $1) " AS _t" $2))) - "") - (if (> (length analysis.clauses) 0) - (.. " WHERE " (cat analysis.clauses " AND " #(self:gen-expr analysis $1))) - ""))) - -(fn tail [[ _ & result]] result) -(fn Compiler.gen-update [self analysis] - "Generates an UPDATE statement for the query defined by analysis." - (.. "UPDATE " (quoteid (. analysis.tables 1)) " AS _t1 SET " - (cat analysis.selection ", " #(self:gen-expr analysis $1)) - (if (>= (length analysis.tables) 2) - (.. " FROM " (cat (tail analysis.tables) " JOIN " #(.. (quoteid $1) " AS _t" (+ $2 1)))) - "") - (if (> (length analysis.clauses) 0) - (.. " WHERE " (cat analysis.clauses " AND " #(self:gen-expr analysis $1))) - ""))) - -(fn Compiler.query [self ...] - "Analyzes the given literals and generates an appropriate SELECT statement." - (let [analysis (new-analysis)] - (each [_ literal (ipairs [...])] (self:analyze-literal analysis literal)) - (set analysis.selection (icollect [_ varname (ipairs analysis.variables)] [:as (. analysis.variable-mapping varname) varname])) - (set analysis.query (.. (self:gen-with-rules analysis) (self:gen-select analysis))) - analysis)) - -(fn Compiler.insert [self head ...] - "Analyzes the given literals and generates an appropriate INSERT statement." - (match head - [:literal name params] - (let [analysis (new-analysis) - columns (. self.tables name)] - (each [_ literal (ipairs [...])] (self:analyze-literal analysis literal)) - (set analysis.selection (icollect [icolumn param (ipairs params)] - (match param - [:var :_] nil - expr [:as expr (. columns icolumn)]))) - (set analysis.query (.. (self:gen-with-rules analysis) - "INSERT INTO " (quoteid name) " (" (cat analysis.selection ", " #(match $1 [:as _ column] (quoteid column))) ") " - (self:gen-select analysis))) - analysis) - _ (error (.. "Expected literal, got " (fv head))))) - -(fn Compiler.delete [self head ...] - "Analyzes the given literals and generates an appropriate DELETE statement." - (match head - [:literal name params] - (let [analysis (new-analysis)] - (each [_ literal (ipairs [head ...])] (self:analyze-literal analysis literal)) - (set analysis.selection [[:as [:rowid 1] :_rowid_]]) - (set analysis.query (.. (self:gen-with-rules analysis) "DELETE FROM " (quoteid name) " WHERE _rowid_ IN (" (self:gen-select analysis) ")")) - analysis) - _ (error (.. "Expected literal, got " (fv head))))) - -(fn Compiler.update [self newhead head ...] - "Analyzes the given literals and generates an appropriate UPDATE statement." - (match [newhead head] - [[:literal name params] [:literal name]] - (let [analysis (new-analysis) - columns (. self.tables name)] - (each [_ literal (ipairs [head ...])] (self:analyze-literal analysis literal)) - (set analysis.selection (icollect [icolumn param (ipairs params)] - (match param - [:var :_] nil - expr [:set (. columns icolumn) expr]))) - (set analysis.query (.. (self:gen-with-rules analysis) (self:gen-update analysis))) - analysis))) - -(setmetatable Compiler {:__call (fn [cls ...] (doto (setmetatable {} {:__index cls} ) (: :new ...)))}) diff --git a/sqlog/init.fnl b/sqlog/init.fnl deleted file mode 100644 index 1b5c39e..0000000 --- a/sqlog/init.fnl +++ /dev/null @@ -1,63 +0,0 @@ -(local Compiler (require :sqlog.compiler)) -(local sqlite (require :diet-sqlite)) -(local {: SQLITE_ROW} (require :diet-sqlite.codes)) - -(local Sqlog {}) - -(fn Sqlog.new [self ?dbname] - (set self.compiler (Compiler)) - (set self.db (sqlite.assert (sqlite.open (or ?dbname ":memory:"))))) - -(fn Sqlog.deftable [self name ...] (self:execute (self.compiler:deftable name ...))) -(fn Sqlog.defrule [self head ...] (self.compiler:defrule head ...)) - -(fn multi? [analysis] (and analysis (> (length analysis) 0))) -(fn Sqlog.compile-sql [self analysis] - (if (multi? analysis) (each [_ a (ipairs analysis)] (self:compile-sql a)) - (when (= analysis.stmt nil) - (let [stmt (sqlite.assert (sqlite.prepare self.db analysis.query))] - (sqlite.bind stmt analysis.constants) - (set analysis.stmt stmt)))) - analysis) - -(fn Sqlog.execute [self analysis ?collect-results] - (if (multi? analysis) (icollect [_ a (ipairs analysis)] (self:execute a ?collect-results)) - (do (print "running:" analysis.query (fv analysis.constants)) - (self:compile-sql analysis) - (sqlite.reset analysis.stmt) - (if ?collect-results - (let [result []] - (while (= SQLITE_ROW (sqlite.step analysis.stmt)) - (table.insert result (collect [icol expr (ipairs analysis.selection)] - (match expr - [:as _ name] name - _ icol) - (sqlite.column analysis.stmt icol)))) - result) - (sqlite.step analysis.stmt))))) - -(fn Sqlog.compile-action [self action] - (self:compile-sql - (match action - [:do & actions] (icollect [_ act (ipairs actions)] (self:compile-action act)) - [:!+ & insert] (self.compiler:insert (table.unpack insert)) - [:literal] (self.compiler:insert action) - [:!- & delete] (self.compiler:delete (table.unpack delete)) - [:!= & update] (self.compiler:update (table.unpack update)) - _ (error (.. "No such action " (fv action)))))) - -(fn Sqlog.compile-query [self ...] (self:compile-sql (self.compiler:query ...))) - -(fn Sqlog.specify [self action ...] - (when (not= action nil) - (match action - [:* & rule] (self:defrule (table.unpack rule)) - [:table & params] (self:deftable (table.unpack (icollect [_ param (ipairs params)] - (match param [_ name] name)))) - [:sql query & constants] (self:execute {: query : constants}) - _ (self:execute (self:compile-action action))) - (self:specify ...))) - -(fn Sqlog.query [self ...] (self:execute (self:compile-query ...) true)) - -(setmetatable Sqlog {:__call (fn [cls ...] (doto (setmetatable {} {:__index cls} ) (: :new ...)))}) diff --git a/sqlog/macros.fnl b/sqlog/macros.fnl deleted file mode 100644 index 6778a6a..0000000 --- a/sqlog/macros.fnl +++ /dev/null @@ -1,31 +0,0 @@ -; [q X] -> q(X) -> [:literal :q [:var :X]] -; [q :x] -> q(x) -> [:literal :q [:const :x]] -; [q #(+ 1 2)] -> q(3) -> [:literal q [:const (+ 1 2)]] - -(fn clause [c] - (match c - (where [escape expr] (list? c) (= (tostring escape) :unquote)) expr - (where [escape expr] (list? c) (= (tostring escape) :hashfn)) `[:const ,expr] - (where [name & params] (sequence? c)) `[:literal ,(tostring name) ,(icollect [_ param (ipairs params)] (clause param))] - (where [head & args] (list? c) (sym? head)) (icollect [_ expr (ipairs args) :into [(tostring head)]] (clause expr)) - (where c (list? c)) (icollect [_ val (ipairs c)] (clause val)) - (where v (sym? c)) `[:var ,(tostring v)] - _ `[:const ,c])) - -(fn clauses [...] - (icollect [_ c (ipairs [...]) :into `(values)] (clause c))) - -(fn defrule [s ...] `(: ,s :defrule ,(clauses ...))) - -(fn defrules [s ...] - (icollect [_ rule (ipairs [...]) :into `(do)] - (defrule s (table.unpack rule)))) - -(fn query [s ...] `(: ,s :query ,(clauses ...))) -(fn insert [s ...] `(: ,s :insert ,(clauses ...))) -(fn delete [s ...] `(: ,s :delete ,(clauses ...))) -(fn update [s ...] `(: ,s :update ,(clauses ...))) -(fn specify [s ...] `(: ,s :specify ,(clauses ...))) - -{: clause : clauses :$ clauses : defrule : defrules : query : insert : delete : update : specify} - diff --git a/sqlog/sqltest.fnl b/sqlog/sqltest.fnl deleted file mode 100644 index 2ea997b..0000000 --- a/sqlog/sqltest.fnl +++ /dev/null @@ -1,18 +0,0 @@ -(local Sqlog (require :sqlog)) -(local {: show} (require :inspector.debug)) -(import-macros {: $ : query : specify} :sqlog.macros) - -(local s (Sqlog)) -(specify s - (table parent parent child) - (* [generation name (|| name " jr") 2] [parent name (|| name " jr")]) - (* [generation name (|| name " iii") 3] [ancestor name (|| name " iii")]) - (* [ancestor x y 2] [parent x y]) - (* [ancestor x y (+ gen 1)] [parent x z] [ancestor z y gen]) - [parent :bob "bob jr"] - [parent "bob jr" "bob iii"] - [parent :bob #(.. :fred :dy)] - [parent :fred :jim] - [parent :fred :betty]) -(show (query s [ancestor (case descendant (when "bob jr" :bob) (else :jim)) descendant gen])) -