AI, networking, and vision — built in. Every release moves the stack forward.
v2026.10.3 is the current release — see the changelog.
v2026.10.3
- Garbage collector roots, finished — compiled code now tells the collector exactly which stack slots hold references (typed slots on x64 and ARM64), and an
Int[]has its own heap tag, so anIntor anInt[]element that happens to equal an object's address is never rewritten by a collection, interpreted or compiled (design) - A hardened loader — a fuzz target on
Loader::Load(hundreds of millions of executions) fixed a crash on a repeated class or method id, allocations of up to 16 GB from a corrupt count, an abort on a bad method signature, a silent exit on an unknown opcode and a read past the end of a short.obe; a verifier now checks jump targets, local and trap ids and class, method and field ids before anything runs (trust model) - Errors no longer end the host — a fatal compiler error and a failed library load are returned instead of calling
exit(1), so the language server stays up, and parser and analyzer diagnostics share one record - Debugger — output stays whole, messages are ordered, unknown requests are refused, you can pause, breakpoints keep their file and have their own ids, and a breakpoint-heavy run costs about 100× less in the hook (25 s to 0.25 s on four threads)
- Native library ABI is versioned —
VMContextcarries an ABI version and its own size, so a library can tell it was built for a different VM; an unresolved call target and an exception on a worker thread are reported, not crashes HttpClientreuses connections — plain-HTTP connections wait in a pool when the server allows it and aGETorDELETEto the same host reuses one, so a program making many requests no longer runs Windows out of ports;HttpClient->CloseIdleConnections()closes the waiting ones (guide)- Library fixes — a failed request, an empty reply or a missing file in the OpenAI, Gemini, misc, net, JSON, XML, RegEx, RSS and JSON-RPC libraries no longer dereferences
Nil;RegExrepeat counts are bounded (a{99999999999}no longer fills the heap); sorting a vector ofCollection.Pairworks (guide) - Language server — edits analyze faster (a hover after an edit in a small workspace: 165 ms to 53 ms on Windows) and a library that fails to load no longer takes the server down (guide)
- Checkers example — an SDL2 game with ten AI levels built on
System.AI, a self-play learner and generated music (programs/examples/checkers, guide) - Tested more deeply — the nightly hardening run is scheduled, a local script runs the cloud checks on your own machine first, and four intermittently failing tests were traced to their causes and fixed (three TLS tests whose certificates were valid only from the second they were made, and a JSON-RPC test that picked a port still held by an earlier connection)
- Getting-started guides — Query.Structured, HTTP, JSON, XML and RegEx, collections, game AI and editor setup, each with a program that was compiled and run, plus what is new in 10.3
- New docs — the architecture assessment, the VM trust model (an
.obeis native code), a collections guide, error conventions and how to add an intrinsic - Upgrading — recompile your
.obefiles and rebuild your own.obllibraries: the file format changed, and a program or library built by an earlier version is refused with a message saying so
v2026.10.2
- Query.Structured, a columnar engine — every column is a typed array with a null bitmap, text is dictionary-encoded, and 65,536-row groups carry zone maps so a filter skips what it cannot match. Queries return views with nothing copied, a
whereis compiled once into typed predicates, prepared statements take?placeholders, and a method-chaining API (Col("value")->Gt(0.5)) sits beside SQL. The SQL parser is new:INNER/LEFT JOINthrough aCatalog,GROUP BYwithCOUNT/SUM/AVG/MIN/MAX/MEDIAN/STDDEVandHAVING, multi-keyORDER BY ASC|DESC,LIMIT/OFFSET,DISTINCT,MATCHES,INSERT/UPDATE/DELETE/CREATE TABLE, and SQL expressions in every clause (score * 100 as pct,group by x % 10,having sum(a) / count(*) > 2,on t.n + 1 = u.w), evaluated 1,024 rows at a time and reduced to the ordinary filter where an index or zone map can serve it. The old API keeps its signatures and results. At 100,000 rows on Windows x64, awherewent from 0.558 s to 0.023 s,order byfrom 3.16 s to 0.096 s andSumfrom 0.051 s to 0.004 s (#1291, #1295, #1298, #1301, #1303, #1325, #1367, #1398, #1416, #1417) - Files and URLs are tables — a quoted path in
FROMorJOINis read by its extension (.csv,.tsv,.json,.jsonl,.xml,.otab, each also.gz),csv('data.txt', delimiter => ';')sets options, a glob reads several files as one table with a_filecolumn, anhttp(s)path goes through a download cache revalidated withETagandLast-Modified, and an archive member or worksheet follows the path after a dot:from 'results.zip'.'2026/runs.csv',from 'budget.xlsx'.'Q1 2026'.Catalog->SetFileAccess(false)refuses them all. The URL download cache is correct across processes that share the temporary folder (one folder of immutable versions per URL and one small note, published by an atomic rename), and a file rewritten within the second of its last read is read again (#1303, #1366, #1384, #1391) - Sources —
CsvSource,FilesystemSource(flat or recursive with parent keys),ObjectSource<T>,TextSource(regular-expression capture groups become typed columns),JsonLinesSource,JsonSourceandXmlSource(nested parts become child tables),HttpJsonSource,ArchiveSource(zip, tar and gzipped tar; nothing is extracted, and traversal, duplicate or overlapping members, zip bombs and CRC mismatches are refused),XlsxSource(typed cells, both date systems, merged cells kept or filled). In their own libraries so a file-only program loads no native module:query_ml'sMlResultSource(folds, out-of-fold predictions, thresholds and intervals fromSystem.ML),query_odbc'sOdbcSource(typed from the driver, with columns and aSetWherecondition pushed into the SQL, names quoted and values bound),query_vision'sVisionSource(images and a detector's boxes as tables;YoloDetectoroverAPI.Onnx) (#1329, #1331, #1334, #1350, #1352) - The
.otabfile —Save,Load,ToBytes,FromBytesandAppend; every block and the footer carry a CRC32, a save writespath.partand renames it into place, andOtabFilereads only the footer and the columns named, over HTTP range requests as well as from disk. A table opened withTableStore->NeworTable->Openis durable: every statement goes to a change log before the call returns,Checkpointfolds it into a save, and a writer lock refuses a second writer. Index definitions are kept in format 2, written only for a table with indexes. Byte-exact spec indocs/OTAB_FORMAT.md(#1315, #1321, #1365) - Hash and sorted indexes, and a planner that explains —
CreateIndex(column, IndexKind->HASH | SORTED), SQLCREATE INDEXandDROP INDEX; a hash index serves=andIN, a sorted index ranges,BETWEEN,ORDER BY,GROUP BYandMin/Max. A lookup gives candidate slots and the whole condition is tested on them in slot order, so results equal a scan's by construction.Explainshows the plan. At 1,000,000 rows on Windows x64, equality on an Int 73 ms to 0.02 ms,ORDER BY value LIMIT 102.8 s to 0.08 s. Several threads may query one table at once, including right after a write (#1351, #1364) - Serving, bridges and threads —
TableServer(query_server.obl) answersGET /tables,GET /tables/NAMEandGETorPOST /queryas CSV, JSON or.otab, refusing anything but aSELECT, any file or URL named in a query, and any result over its row limit;RemoteSourcequeries a published table as a local one.ToCsv,ToJson,ToMatrixandFromMatrixonViewandTable.GetErroranswers the calling thread's own error, aCatalogcan be shared between threads, andThread->GetCurrentId()andThread->IsAlive(id)are new.TableServeranswers requests at once, andBeginWrite()andEndWrite()bracket the program's own changes to published tables (#1325, #1378, #1389) - Hugging Face models without Python —
System.NLP.Onnx.TextClassifieropens a model folder (whatsave_pretrainedwrites, with an ONNX export) and classifies text aspipeline("text-classification")does: its tokenizer, labels, scoring, inputs and maximum length come from the folder, and token ids and scores match Python.System.AI.Hub.HubClient(ai_hub.obl) downloads a model by name, asfrom_pretraineddoes, into a cache that checks every file's size and SHA-256 against the Hub, works offline, and sendsHF_TOKENto the Hub only.BpeTokenizeris RoBERTa's and GPT-2's tokenizer, matching thetokenizerslibrary id for id and offset for offset. - Downloads of any size —
HttpClient->GetToFile(url, path)andHttpsClient->GetToFilestream a body topath.partand rename it into place only when it is complete;Getno longer returns no content for a body over 256 MB. - Interpreted code no longer has an
Intrewritten by a collection — a minor collection treated every operand-stack word that looked like a young object's address as a reference, so anIntthat equalled one changed value (#1452). The VM now computes a reference map for each method, and interpreted frames skip the words the maps prove areIntorFloat; anything not proven keeps the old handling, and typing stops above any frame that compiled code sits under (compiled frames are planned for the next release).OBJECK_GC_ROOTS=conservativerestores the old behavior andOBJECK_GC_ROOTS=auditchecks the maps against the live stacks (#1466, #1470, #1478). - Instance IDs survive the collector —
GetInstanceID()was the object's address, and a minor collection moves young objects, so aHashorMapkeyed byBasicCompareobjects lost its entries once the keys moved. The ID is now a number assigned once per object, which the collector moves with it. - TLS reads time out on a quiet peer — a TLS client socket had no receive timeout, so a peer that stopped sending without closing blocked a read for good; it now times out after 300 seconds (
OBJECK_TLS_RECV_TIMEOUTsets it). A connection reset mid-reply is a failed request, not a 200 with an empty body. - Security: credentials stay with their origin — a redirect to another host or port no longer receives the caller's
Authorization,Proxy-Authorizationor cookies, as in curl and Pythonrequests;API.OpenAIandAPI.Googlesend their tokens this way. - Allocation no longer searches, and collection follows the live heap — the old generation's free-block cache held blocks of any size in a power-of-two list, so after a major collection every allocation of a slightly larger size walked the whole list; each list now holds one size class, and the first read of a 4,000-row text column went from 0.96-1.03 s to 0.023 s. The major-collection threshold started at 8 MB and grew only after eight majors freed nothing, so a program keeping a table past 8 MB collected on nearly every array allocation; it is now twice the live heap after each major, never below 8 MB: binarytrees 18 from 13.9 s and 353 MB to 10.0 s and 273 MB (medians of 3, Windows x64). A given
--gc-thresholdholds exactly as given while a major leaves at least a quarter of it free, waits for twice the live heap while more than three quarters survive, and returns once the live heap fits under it again; a program keeping 4,000 objects under--gc-threshold=64ktook 23,539 majors and 11-18 s before, 8 majors and 0.1 s now (#1308, #1311, #1383) - Collections —
Collection.Hashwas a chained table ofCompareLists, about four objects per entry, that stopped resizing at 196,613 buckets and aborted the VM when keys of different classes collided; it is now open addressing over parallel arrays, doubling without limit, and iteration order changes.Cachesearched its LRU list linearly on every call. New unboxedIntVector,FloatVector,IntMap,IntSetandBitSet. On Windows x64, 1M Int inserts 2.506 s to 0.424 s; 1M appends to anIntVector0.058 s against 0.933 s boxed. On macOS the collector's pointer set clustered under the nano allocator's stride (one major took 29.8 s on the hosted runner); fixed (#1341) - Runtime — bulk
CopyandFillon primitive arrays,Float->ToShortStringand exact floats in JSON,"1e400"->ToFloat()gives infinity instead of stopping the VM,Bool[]serialization no longer over-reads,Serializer->Serializeat zlib level 1 (5 s to 0.23 s on 32 MB).CompressGzipended the program on inputs under 18 bytes.Byte->CompressBrwas raw deflate, never Brotli: it isCompressDeflatenow and the HTTP server'sCompression->BRis removed;UncompressDeflate(input, limit)bounds how far data inflates.File->Renamereplaces an existing target atomically on Windows;File->CreateNew,Runtime->GetProcessIdandIsProcessAliveare new. Number parsing in the VM, compiler, debugger and REPL refuses bad text instead of throwing. A Nil interpolates asNilinstead of raising (#1296, #1297, #1304, #1306, #1307, #1310, #1314, #1350) - Calls nest 16,384 frames deep —
CALL_STACK_SIZE 256ended the shippedman_or_boy.obsand any parser nested past about 300, and quietly bounded an operand stack that was never checked. A per-threadCallStackreserves for the maximum and commits on demand;--call-depthandOBJECK_CALL_DEPTHtake 256 to 1,048,576 (default 16,384); the compiled call site checks the native stack against a per-thread floor, so running out of stack is a recoverableRuntimeErrorcompiled or interpreted. CLBG benchmarks moved within noise (#1377) - Callbacks, threads and the collector — calls back into Objeck from C++ run on the thread's checked call stack, where a recursion through a callback ended in 0xC00000FD on Windows (#1386); on POSIX dates and file times are broken down in the calling thread's own buffer (#1388); VM thread stacks avoid transparent huge pages on Linux, so 100 idle threads cost 7.9 MB rather than 37.0 MB (#1390); objects the traps build run the write barrier for the young objects they hold, which had left reflection results, socket addresses and error messages dangling after a minor collection (#1392); a
Float[]field read back by the Deserializer is aFloat[]to the VM (#1393) - A conditional's value survives a collection — a conditional (
c ? a : b) leaves its value in the method's untyped and/or slot until it is used, and the collector rooted that slot nowhere in interpreted frames, nor in compiled frames on ARM64; when another thread collected in between, a constructor stored a dangling reference. The slot is now marked and relocated (#1436). The gap predates v2026.10.1; more frequent collections under--gc-thresholdmade it reproducible, and the nightly heap verifier caught it on five tests - Blocking I/O parks for the collector — a thread blocked in TLS, HTTP/2, HTTP/3, DTLS, UDP, a named pipe, console input,
Runtime->Commandor a DNS lookup held up every collection in the process; with an in-process peer that is a deadlock. Native libraries could not park at all:VMContextgainsbegin_blocking/end_blockingandlib_api.hanAPITools_Parkedguard, with the ODBC, SDL and OpenCV waits bracketed. TCP and TLS accepted sockets shared one class-id cache, so a process serving HTTP and HTTPS handed the wrong class to one of them (#1300, #1302, #1317, #1319, #1320) - DTLS works for the first time — the parser accepted all 18 DTLS directives and the emitter had a case for none, so every
DTLSSocketmethod compiled to nothing. With the cases emitted, accept never completed a handshake,ReadBufferwaited to fill a buffer a datagram never fills, a second client was never served, and the server listened on one address family.DTLSSocketServer->New(cert, key, passwd, address, port)binds one address and keeps to it, and a write after the peer has gone fails with the reason (#1318, #1333, #1376) - Servers take IPv4 and IPv6 clients on every platform, or bind one address — on Windows an HTTPS server refused 127.0.0.1 while its HTTP sibling refused ::1; both now listen dual-stack.
TCPSocketServer->New(address, port),TCPSecureSocketServer,UDPSocketServerandWebServer->Serve(callback, address, port)bind one address, with"localhost"always 127.0.0.1.UDPSocket->Newresolves names and IPv6 and tries each address. A server bound to port 0 reports its port throughGetPort()andWebServer->GetBoundPort(), andMcpServer->Serveaccepts"http_port"0 withGetBoundPort()(#1322, #1326, #1372, #1373, #1376, #1380) - Every socket failure says why — a server on a taken port reported "The operation completed successfully." on Windows, and
SO_REUSEADDRlet a second Windows server bind and listen on a port a server already held;TCPSecureSocket->GetLastError()always returned Nil. Every plain, TLS and DTLS call records its outcome per thread as it happens, a failed connect reports the most informative reason, a verification failure lists mbedTLS's reasons, andWriteBytereturns whether the byte was written.SIGPIPEis ignored from VM start on POSIX, so a write to a peer that hung up fails instead of killing the process. On Linux a client connecting by IP address refused a certificate naming that address in an iPAddress SAN; a server'sGetIssuer/GetSubjectread the wrong context (#1323, #1335, #1348, #1349, #1371, #1373) - HTTP —
Web.HTTP.Serversent every status code other than a handful as 400 and dropped the handler's headers and body on all but 200; any code from 100 to 599 now goes out as written, with no body on 1xx, 204 and 304, which the clients no longer wait 30 s for.Url->EncodeandDecodeare UTF-8, withEncodePathandDecodePath; query parameters split at the first=(#1300, #1328, #1340) - Non-ASCII text everywhere on Windows —
données.txtwas created asdonnées.txtand a file another program named could not be found, because every file trap passed UTF-8 bytes to an ANSI API; arguments, environment variables,OBJECK_LIB_PATH, the native-library loader and certificate loads went through the ANSI code page too, so an install directory with a non-ASCII name loaded no library. Every tool,obu,obband theobnlauncher included, enters atwmainon MSVC and MinGW alike;obd's console mode, the launcher'sSetObjEnv.cmdandobu's console messages carry non-ASCII text. Found on the way:Runtime->CommandOutput(command)crashed its caller on Windows on every call, one of threelang.obsmethods that shipped with no return (#1313, #1327, #1357, #1362) - A quote inside
{$...}is a compile error, not a hang — the compiler ran until it was killed on such a string; it now reports the open interpolation and how to fix it (#1439) - Generics and interpolation — a program's own bounded generic class returns its type argument:
Holder<T : Compare>was rewritten to its bound when the class was analyzed, soHolder<String>->Get()was typedCompare,Holder<String>->Get()->Size()was undefined andSet()accepted anyCompare; a literal directly in an interpolation ("{$0x1F}","{$42}","{$'a'}","{$true}") was looked up as a variable and now compiles (#1445) - Compiler fixes — a float literal outside the double range compiled silently and is now an error;
-9223372036854775808is accepted;010was read as octal with no diagnostic and is now an error that suggests0o10or10, with0o17as octal. An unqualified name two used bundles declare is an error naming both candidates; bundle-level enums and aliases are named with their bundle, which is the new library format; constructors are no longer inherited by accident.["a", "b", v]crashed the program at every-optlevel; a 2-D String literal had its dimensions swapped and 3-D literals were refused;a->Fill(7)pushed the array after its arguments;obcsegfaulted on aforwhose condition was not a<comparison; an inherited library instance method could not be called without a receiver; a merged label at-opt s2/s3could take another's id in a linked library method (#1299, #1309, #1312, #1324, #1332, #1336, #1339, #1343, #1345, #1346, #1347, #1350, #1355). A Float or function-reference?:now meets at the join as what it is: the JIT abandoned a method with a Float conditional, and a compiled function-reference conditional could call through the other branch's closure; a subscript on a later link of a call chain no longer crashesobc(#1397, #1426) - JIT — a compiled Float division by NaN raised
Divide by zeroon x64 (#1399);Float->NaN(),Float->Inf()andFloat->NegInf()were not compiled, so every method that started a search fromFloat->Inf()ran interpreted (#1423); a two-dimensional array access leaked its index register and, after eight of them, the method went back to the interpreter, 10 to 20 times slower (EllipticEnvelope's distances 1.68 s to 0.14 s, #1424); and a value pending when an inlined loop began was lost at the loop's collection safepoint, a rare Nil dereference or segmentation fault in compiled multithreaded code (#1425). UnderOBJECK_JIT_REPORT=1a failed compile now names the instruction, its opcode and the reason - System.ML and System.NLP lab work —
KernelSVMandOneClassSVMon LIBSVM's SMO solver; outlier detectors (ZScoreDetector,IsolationForest,LocalOutlierFactor,EllipticEnvelope,DbscanDetector,OneClassSvmDetector, andAutoencoderDetectoron the new multi-layerDenseNetwork) withConfusionMatrixandSensitivitySweep; forests withmin_samples_leaf, unlimited depth and a sorted split sweep (a depth-12 tree on 2,000 x 41 rows: 52 s to 0.04 s); BERT embeddings throughWordPieceTokenizer,ApiSequenceTokenizer,BertEmbedder(the newnlp_onnxlibrary) and a trainableEmbeddingClassifier; andSystem.ML.Lab(the newml_lablibrary) withPartition,Resample,Stopwatch,Labels,Experiment,ResultTableand SVGChart.System.Time.Timermeasures wall-clock time on Linux and macOS, and-lib @visionlinks again (#1426) - Libraries —
System.NLPgains Porter's reference stemmer (8,559 of 8,559 words agree with NLTK), a real tokenizer and VADER-style sentiment (95.5% agreement with NLTK's VADER on a 10,662-sentence corpus given its lexicon). A JSON number with an exponent failed the whole document and the lexer now follows RFC 8259; the CSV reader is RFC 4180 and names the bad row; regular expressions gain character classes,\b, empty matches and capture groups.Softmaxnormalizes each row. OpenAI'sGetTextreturned Nil for every reasoning-model reply; a blocked Gemini prompt crashed;API.Ollamais brought up to the current REST API with tool calling, structured output and/api/embed. SDL2 game controllers worked on no platform. An ODBC prepared statement run twice read freed memory, and every macOS package shipped aDatabase.ODBCthat could load no driver.Byte[]->ToHexString()is a digest;ByteBuffer->New(Byte[])copies;XmlElementkeeps attribute order and a self-closing tag no longer serializes to nothing.Data.JSONdecodes string escapes when it parses and escapes once on output, so a document reads back as it was written:GetValue()returns the text itself,/is no longer escaped, an invalid escape is a parse error naming the offset, andJsonElement->Decodeis deprecated and must not be called on parsed text.McpServeranswers a malformed request with a JSON-RPC error and refuses an incomplete configuration instead of ending the process (#1286, #1287, #1288, #1289, #1290, #1292, #1293, #1294, #1331, #1337, #1341, #1348, #1352, #1356, #1359, #1370, #1394, #1396, #1403) - Library fixes —
RSSReaderno longer raisesNilErrorwhen the network fails or a local file is missing (IsOk()is false);sdl_game'sAddClipscuts each frame at the real frame height, which it took from the width; aData.XMLself-closing root such as<a title="x y"/>is a document, an empty document and input that ends in whitespace or mid-name are ordinary parse failures, and[n]or[attribute]below a leaf element no longer raises;FindElements"[n]"is the n-th match, as in XPath, not the first n; andQuery.Structuredrefuses an unknown column in a single-table select list orORDER BY, as it already did in joins,WHERE,GROUP BY,HAVINGand aggregates (#1444) - The language server is about twice as fast per edit — each edit parsed and analyzed the program twice, once for diagnostics and again for hover and completion; a request whose file texts and libraries match an analyzed program now reuses it. On the server's own 8,800-line workspace an edit's native work went from about 1.3-1.5 s to 0.6 s and hover from 1.6-1.9 s to 0.8-0.9 s (#1437)
- 32 new shipped examples, in learning order — the language (0-13), data (14-21), networking (22-24), AI and machine learning (25-30) and an SDL2 game (31), each with its compile and run lines and the output it prints, written for people new to Objeck and verified by compiling and running every one (#1440)
- Tooling and CI — a failed DAP
evaluateansweredsuccess: truewith<error>and now fails with the reason;stackTracepages. The editor index held no enums; hover and completion now cover 90 library enums. The playground infers libraries fromuselines with their dependencies and has 42 demos in a rebuilt UI. 85 of 281 example programs that no longer compiled are ported. ODBC tests run on every CI leg; 32 regression tests that collided on fixed ports now bind port 0, so two suites on one machine pass together;TESTS.mdis regenerated on master; Debian packages are built and signed intoSHA256SUMSafter every publish;obdsends every output event of a run beforeterminated, and an.obefrom another toolchain version is refused with a message that names both versions and says to recompile (#1281, #1305, #1330, #1387, #1404, #1342, #1344, #1360, #1363, #1370, #1372) - Known issue — a compiled
-opt s3method can keep a dead object alive until it returns: an inlined call's spill slot is not cleared after its reload. Nothing is freed while in use. The fix is planned for the next release. - Known issue — on Windows, a burst of local connections can stall one for about 21 seconds (#1443, #1461). The same loss reproduces between plain Python sockets, where a packet capture shows the Windows stack dropping the client's closing packet, so the server's end stays open and a later connect that reuses the client's port is not answered. Why the stack drops it is not yet known.
- Upgrading — every
.oblis a new format (magic0xffb9): rebuild your own libraries. An.obecompiled by an earlier release is refused by this runtime, which requires an exact toolchain version match (the message names both versions): recompile the source. A v2026.10.1oburun from an install directory with a non-ASCII name crashes before doing anything, so that install must be upgraded to v2026.10.2 by hand; from v2026.10.2 onobuhandles it.Directory->Listdrops.and..on Windows.010is an error and0o10is octal.System.Time.Datemust be written in full besideDatabase.ODBC.CompressBrisCompressDeflate.Byte[]->ToHexStringis a digest.ByteBuffer->New(Byte[])copies.Hashiteration order changes.Softmaxis per row. Malformed JSON numbers and over-long CSV rows fail. InQuery.Structured's new engine NaN matches only<>and sorts last.Serializecompresses at level 1. A Nil interpolates asNil. The call stack defaults to 16,384 frames.--gc-thresholdholds as given while a major leaves a quarter of it free and scales with the live heap otherwise. On POSIX only, a write to a closed stdout pipe fails instead of ending the program.McpServertakeshttp_port0.GetLastError()is Nil after a call that worked.Data.JSONdecodes string escapes when it parses, so stop callingJsonElement->Decodeon parsed text (it is deprecated, and an invalid escape no longer parses).TF_IDF->New()smooths IDF and normalizes to unit length by default.System.Time.Timermeasures wall-clock time on Linux and macOS. InQuery.Structured,where a = bcompares two columns, and a program that changes tables published by aTableServermust bracket the changes withBeginWrite()andEndWrite().McpServer->Serverefuses an incomplete configuration. InData.XML,FindElements"[n]"is the n-th match, as in XPath, not the first n. InQuery.Structured, an unknown column in a single-table select list orORDER BYmakesQueryreturnNilwithGetError()naming it, where it used to read as empty. Against v2026.10.1 no class is removed from the editor index and the only functions removed areCompressBrandUncompressBr. The CHANGELOG has the full list
v2026.10.1
- Errors you can raise, catch by type, and clean up after — System.Error and its subclasses are raised with Runtime->Raise and caught with try { } on(e : ParseError) { } finally { }. Clauses are tested in order, an error no clause names goes on after finally, and return, break and continue leave through finally. The runtime's own faults are NilError, IndexError, DivideByZeroError, CastError and RuntimeError, and a failed Runtime->Assert or library call now recovers instead of ending the program. ?-> still recovers from anything, and Runtime->GetLastError() says what it was (#1267, #1273, #1274)
- Named arguments — F(data, rate: 0.1, epochs: 50) in any order, skipping any defaulted parameter, for the program's own methods and constructors and for library ones: every .obl records its parameter names, so standard-library parameter names are now public API. Arguments are still evaluated in the order written (#1263, #1268)
- Method-level generics — function : Max<T : Compare>(values : Vector<T>) ~ T, inferred from the arguments and checked against the bound, in the program and in libraries. Vector, List and CompareList gain Map<R>, so a map can change the element type: words->Map(\(s) => s->ToUpper()) is a Vector<String> (#1266, #1275)
- Reference parameters — function : Swap(ref a : Int, ref b : Int) and Swap(ref x, ref y): copy in, copy out, as Swift's inout, with 'ref' at the call site too. A local, a parameter or a field can be passed (#1277)
- Array literals hold expressions; jagged arrays — [x, x * x, Square(x + 1)] is built when evaluated, and objects of several classes make a Base[]. T[][] is an array of rows of any length, as a local, parameter, field or return, with ragged literals (#1264, #1265)
- The language server, rebuilt around LSP 3.17 — pull diagnostics, real completion documentation and MarkupContent hover, rename with validation and organize imports, hierarchical document symbols, one configuration per workspace folder, semantic token ranges and deltas, a Run code lens, links for 'use', progress reporting, and one server per VS Code window over stdio. Analysis is reused until the text changes and edits are debounced; positions are UTF-16 on every platform (#1221-#1259)
- Debian packages for Ubuntu 24.04 — sudo apt install ./objeck-ubuntu24.04-x64_2026.10.1.deb (or -arm64) installs the toolchain under /usr/lib/objeck with the commands on PATH, and apt installs the system libraries it needs; OpenCV, SDL2, unixODBC and LAME are recommended rather than required, since only the libraries that wrap them load them. The package holds the release's own Linux binaries, unchanged; apt remove takes it all out
- Libraries — Condition, Semaphore, CountDownLatch and Barrier; set algebra; Hash, Heap and sort additions; String helpers; System.Math.Rational and Complex; System.Base->ToString for every class (#1108, #1169, #1251, #1262)
- JIT and recovery fixes — a deferred load materialized in one branch arm; an error in a tail-call loop and a bounds error mid-argument-list crashed recovery; more than 16 nested guarded calls lost their inner handlers; a NaN compared as equal (x64) and as less (ARM64); negative array sizes; ?-> deferred correctly from a bridge interpreter (#1190, #1198, #1205, #1260, #1271, #1272, #1273)
- Compiler fixes — wrong code in call chains and closures, generic type arguments through chained calls, primitive receivers, unary minus on a parenthesised operand, critical() locks released on return, a tail-call label that collided with an inlined callee's (an infinite loop at -opt s3), a returned literal swapped with a leaving block's, and typos that used to declare a variable silently (#1168, #1197, #1204, #1207, #1208, #1249, #1261)
- VM and library fixes — Float->ToString of large values, GMT dates and pre-1970 times, file I/O edge cases (Flush, ReadLine, empty files), multi-dimensional serialization, reflection metadata, String edge cases, "\e" as ESC, Byte arithmetic, and Ints no longer printed with a locale's digit grouping on macOS and Linux (#1192, #1193, #1195, #1199, #1200, #1201, #1211, #1212, #1240, #1257, #1268)
- Linux ships an environment helper and an optional desktop entry — the Windows and macOS launchers set up an environment and open a shell, and the Linux tarball had no equivalent. Sourcing
env.shsetsPATHandOBJECK_LIB_PATH, which the README previously asked you to export by hand, andinstall-desktop.shadds an “Objeck” entry to your application menu — writing only underXDG_DATA_HOME, so it needs no root and cannot collide with a distribution package (#1088) obucan verify a release manifest again — Windows signing rewrites the installers, soSHA256SUMSis rebuilt over them, which invalidates the signatureobuchecks before it reads a line of the manifest. The workflow meant to repair that had never once completed: it signed the manifest, verified it against the committed public key, and then could not upload it, because it had changed directory out of its checkout (#1081)- The MSYS2/MinGW toolchain compiles again — five independent defects, four of them the same mistake:
_WIN32used where_MSC_VERwas meant. MinGW-w64 defines_WIN32and compiles with GCC, so MSVC-only constructs behind that guard reached a compiler that never had them. The deploy scripts also had no failure handling at all, and now reach 18 of 18 stages (#1087, #1089, #1091) - The ONNX and OpenCV bindings build against OpenCV 5 — six functions moved into
opencv2/geometry/2d.hppand3d.hpp, neither of whichopencv.hppincludes. Nothing left namespacecv, so this is two include lines rather than the Homebrewopencv@4pin an earlier release reached for (#1091) - The JIT archive compiled one source twice, with different flags — each backend's makefile named
../jit_common.oas a prerequisite and also carried a rule that could build it, while the parent makefile already built it. Run serially the second copy wins and the archive carries an object built with the wrong flags; under-jthe two race (#1092) - Every Sourceforge link in the repository returned “Page not found” — the project's unix name is
objeck-lang, notobjeck. The real listing was complete the whole time (#1085) - objeck.org offered the previous release — the deploy script only ever deployed the generated API reference, so the site's own pages needed an undocumented hand-upload. It now deploys both halves by default, per file and hash-verified at both ends, and refuses a page whose Download button names a version other than the one being deployed (#1084)
- Release verification runs on all five platforms from one dispatch — each from a clean checkout, refusing to pass unless every leg reports the same commit. It also caught that a checkout made on Windows cannot build the POSIX ONNX library at all: nine paths here are git symlinks, and a Windows clone writes them as text files (#1095, #1094)
v2026.10.0
Try()recovers from an error raised inside compiled code — whether a guarded chain recovered or ended the program depended on how many times the failing method had been called. The handler stack is now per-thread so a JIT callback can see it, the callback reports a status instead of exiting, and a compiled method calling a compiled method that fails carries the status outward instead of printing and exiting. Compiled recursion that overruns the native C stack stays fatal (#925)- A recovered
?->compares correctly againstNil—if(x?->y() = Nil)took the wrong branch once the failing method was hot, while the same value through a local was right. Recovery was never at fault; the value was read before the handler's store was visible (#1067) obu's install lock no longer follows a symbolic link — anything able to write to the install root could plant a symlink at.obu.lockandobuwould follow it, creating the target. Nothing is written through that descriptor, so the reach was unexpected file creation rather than disclosure (#1075)- The release key is published where this repository cannot vouch for it — the key is now served from objeck.org as well as committed here, and a weekly job checks the two still match. A key obtainable only from the thing you are verifying proves nothing (#723)
- A program could compile to an infinite loop at the default optimization level — two helper methods containing the same construct were inlined into one shared label space, so the second body’s jump resolved to the first body’s label: a backward jump into already-executed code. Two helpers that each evaluate
->Abs()was enough to trigger it, the program was correct at every lower optimization level, and-opt s3is whatobcuses when no level is given, so no flag was needed to reach it. One shipped library,misc.obl, was built wrong by it - A classifier can be evaluated against a false-positive budget, end to end —
CrossValidation->Evaluatenow returns the pooled out-of-fold score for every row, so a decision threshold can be chosen from scores no model saw its own row in, and applied unchanged to held-out data. Folds can be stratified by any key rather than only the binary label, which matters when the positive class is a union of rare categories.LogisticRegressionimplementsScoreModel, so a linear baseline goes through the same evaluation path as the tree classifiers Metrics->AtThresholdreports what a threshold actually did — recall, false-positive rate and precision at one given cutoff, the inverse ofRecallAtFprand the only way to check whether a budget chosen on one sample still holds on another.Metrics->Bootstrapputs a percentile confidence interval around any of them; a resample that draws a single class cannot support the statistic, so those are discarded rather than averaged in, and the surviving count travels with the interval- Reporting on rare categories —
Metrics->RecallByGroupbreaks recall out per group and carries the count each rate rests on, because a recall of 1.0 over two positives is not the claim a recall of 1.0 over two thousand is.UnseenGroupsidentifies categories a model was never trained on,PrecisionAtBaseRatereprojects a measured operating point onto an assumed prevalence, andShuffleLabelsgives the shuffled-label control a seed - One interface over both inference backends —
API.Onnxruns a model in-process,API.Inferencesends it to a server, andAPI.Modelsnow holds theTensorand theEngineinterface they share. Upgrading: add-lib models, or programs using either library no longer compile — dependencies are not transitive, so this applies even to a program that never mentions a tensor linux-arm64shipslibobjk_onnxfor the first time —API.Onnxwas unavailable there because only an x86-64 ONNX Runtime was vendored. Never a platform limitation: upstream publishes an aarch64 build for the version already pinned- Releases ship a signed manifest —
SHA256SUMSsits beside the assets it describes, so replacing both together defeated it. There is now an Ed25519 signature, checked against a public key committed to the repository - Any ONNX model can be run, not only the eight with a hand-written wrapper —
API.Onnx.Sessiontakes named tensors and returns the model's outputs as named tensors, andGetModelInfo()reports the names, element types and shapes a model expects, with a symbolic dimension reported as-1rather than guessed at. The caller never states an element type: tensors cross asFloat[]and the model's own declaration decides what each input becomes. Preprocessing and decoding move into Objeck, where they can be written once and reused. It agrees exactly withResNetSessiononresnet34, and a Phi-3 prefill runs through it with 67 inputs API.Inferencereaches a model server over HTTP — a new library, the sibling ofAPI.Onnx: the same models, served rather than loaded. For a model that is not an ONNX file you have locally — one on a GPU machine, a TensorFlow model you would rather not convert, or anything already behind Triton, KServe, TorchServe or TF Serving. Speaks KServe v2 and TF Serving v1, andDescribeRequestprints the body it would send- The FP16 ONNX input tensor wrapped memory that had already been freed — the helper built the halves in a vector local to itself and handed back a tensor wrapping it, so inference read whatever had replaced it. The FP32 path is correct, which is why it survived: no model in this tree is FP16. The buffer is now a required parameter, so the signature enforces its lifetime
- Closing an ONNX session twice corrupted the heap — the native close deletes the session and nulls its own local copy, which the caller never sees, so none of the seven session classes cleared the handle.
IsOpen()stayed true forever after the first close — the very thing it was added to report — and a second close was a double free --nurserynow reduces memory on Windows — the young region was reserved and committed at its full 128 MB, so lowering the limit moved the collector's boundary without changing what the process charged to the system. POSIX got this for free from lazy commit- A native library could store an object the collector tracks without a write barrier —
AllocateObjectNativeputs a native allocation in the old generation, where nothing scans it, so a native library storing an object it received left the collector unaware of the reference. Three sites in the ONNX binding had it wrong. The VM now exposes a barrier native code can call, and CI holds every native store to it - A failed ONNX session was undetectable, and two families then crashed on it —
onnx_new_sessionwrote its return slot only when it succeeded, so a failed session returned whatever the caller had left there, and nothing exposed the failure. YOLO and ResNet then called a method on the Nil result. Every session class now answersIsOpen(), and inference returns Nil rather than calling into a null handle - Every ONNX inference printed to the program’s stdout — progress and timing went to
std::wcoutat thirteen sites across every model family, four of them behind a#ifdef _DEBUGthat had been commented out and never restored. They now go to stderr, where every error path in the same file already wrote API.Ollamaadvertised streaming completions and had none — every request it can make sends"stream": falseand there is no alternative path. The comment now says what actually happens: a request completes before returning, so a long generation produces nothing until it finishes- A generic array parameter did not resolve across a library boundary —
Vector[]<T>as a parameter compiled inside a library and callers in that same library reached it, but a program linking the library was told the method did not exist. The array dimension was dropped reading the signature back out of the.obl, which is why the same type worked as a return value and failed as a parameter - Build and test plumbing — the generated POSIX
Makefiles are treated as build output rather than tracked source; a missingexpectlet the debugger suite skip every test and still report success; andcov_scan.shreported a submission Coverity had refused, which also deleted the archive it had just promised to keep
v2026.9.7
- A model can be evaluated honestly, end to end —
System.MLcould fit a model but not measure one. Nothing held a scaler’s statistics across a train/test split, so test data was scaled by its own numbers, which leaks the test distribution into the result.FeatureScalerandTableEncoderlearn from the training split and reapply it,StratifiedKFoldkeeps each class’s ratio in every fold from a seed, andCrossValidation->Evaluateruns the folds over a commonScoreModelinterface - Metrics that take a score rather than a decision —
RecallAtFpr,ThresholdAtFpr,AucRoc,AveragePrecision,RocCurveandPrCurve. ABoolarray is already thresholded, so it cannot say what recall would be at a different false-alarm rate - Classifiers that split continuous features directly —
DecisionTreeClassifier,RandomForestClassifierandGradientBoostedClassifier. The existing trees takeBool[,], so data had to be quantile-binned first — and the binning discards the very thresholds a tree exists to find - A
Bool[]returned from a method was mishandled in three separate places — comparing such a call againstNilwould not compile, subscripting the result read several bytes instead of one, andBool->New[src]returned the source array rather than a copy. ABool[]held in a local was correct throughout, which is what disguised all three - Every comparison involving NaN returned true on Windows — NaN compared equal to 1.0 while being both less than and greater than it, and the same program answered differently on Linux and macOS. The VM is built with
/fp:fast, which permits assuming operands are not NaN, and the amd64 JIT read the zero flag for equality without the parity flag that separates equal from unordered - Nineteen library divisions aborted the VM on ordinary input — a division by zero raises a runtime error rather than yielding infinity, so an unguarded one ends the program.
CsvColumn->Average(1, 1), the average of an empty range on a populated table, was confirmed as a live crash before anything was changed - The collector’s old generation moved to open addressing — Windows
binarytreeswent from 2.392s to 1.789s obu verify <archive> <SHA256SUMS>— the integrity checkupdatealready performs, exposed for anyone who downloads withcurl. A mismatch and a check that could not be carried out are different exit codes- An update no longer aborts because something briefly held a file —
obu updaterenames the install tree aside, and Windows denies renaming a directory while another process holds a handle inside it, which antivirus does to a binary whose bytes just changed. One attempt saw “Access is denied” and unwound the whole update; it now retries - A toolchain-version mismatch said the wrong side was stale — the error read “the LIBRARY appears to be compiled with a different version”, which sends you to rebuild libraries that are already current, when the stale side is usually the tool reading them. It now names which side is which, and both versions
obcnames the library that would supply an unresolved class — “Unable to resolve external library class” was true and unactionable: the path is almost always right, one entry is missing from-lib, and finding which one meant grepping the library sources. It now saysAdd it with '-lib net_server'- The
@weblibrary group never worked, and@groups now expand anywhere in the list —-lib @webfailed on any program, even one that never touched HTTP, because the group omittednet_server.obl. Separately, when building a library,-lib @stdworked while-lib @std,misctried to open a file named@std.obl. Both fixed, and the groups are now documented —obc’s usage had never mentioned@at all
v2026.9.6
System.MLstopped returning wrong numbers — column sums and averages truncated every fractional value, soLinearSolverreported the wrong R-squared;KMeans->Groupcould hand back empty groups depending on the order of its labels, and the Dunn index then divided by zeroMatrix2Dsays no instead of stopping the program — operations on shapes it cannot combine returnNil, aNiloperand no longer crashes the native code,Inverseof a non-square matrix no longer hangs, andNeuralNetwork->Trainrefuses an input or target that is not a column of the right heightobiand the embedding API speak HTTP/2 and HTTP/3 — both run code through the module build, which never got the flags or the librariesobrhas, so they quietly used HTTP/1.1- Two ARM64-only crashes —
obiaborted with “double free or corruption” on Linux ARM64, because the REPL’s module and the VM it links were built with different macros; and a program using function references could be killed at exit by a race between the collector’s marking threads API.OpenAIanswers, and sends the picture — a textRespondposted its request and never read the reply, so the call was billed and returnedNil; every image call sent its request as textobiexits when its input ends — piping a program into the REPL, or closing its input, left it running forever
v2026.9.5
- Linux ARM64 runs on every ARM64 CPU — v2026.9.4 needed SVE instructions and stopped with “Illegal instruction” on a Raspberry Pi 4/5, Graviton2, Snapdragon X or Apple silicon in a Linux VM; it now targets ARMv8-A, at no measured cost
- Threads exit and join safely — a runtime error or
Runtime->Exitwith another thread running no longer crashes the VM, andThread->Joinno longer fails after a garbage collection - Garbage collector — a closure's captured values could be freed while still held; plus nursery-end, thread-exit and allocation-size fixes, and a heap verifier (
OBJECK_GC_VERIFY) run nightly - Sorting — primitive sorts can no longer exhaust the call stack and are about 15% faster;
ArraySort->Sortsorts in place;Data.CSVmedians are about 12× faster - Compiler — dozens of fixes for lambdas, enums and conditional expressions, found by differential testing and fuzzing
- Integer arithmetic — one definition across interpreter, compiler and JITs;
INT64_MIN / -1no longer stops the program, and>>>takes its shift count modulo 64
v2026.9.4
- Integer division by a power of two rounded the wrong way at
-opt s2ands3— strength reduction turnedn / 2^kon a local into an arithmetic shift, which rounds toward negative infinity where division truncates toward zero:-7 / 2gave-4. Division is no longer rewritten; both JITs already compile a constant divisor correctly. Recompile programs built ats2ors3with v2026.9.3 or earlier 1 / nevaluated tonat-opt s3— a peephole pattern meant forx / 1matched the left operand instead, so1 / 5gave5. The pattern is gone- The compiler crashed folding
INT64_MIN / -1—obcexited with no message and no output file. That fold is left to run time now - Deserializing an object array with a Nil element corrupted its object — each Nil element was written into the object's next field instead of the array, so the array read back as Nil and later fields shifted
v2026.9.3
- macOS installs need nothing else — every macOS release since v2026.6.3 linked Homebrew's GnuTLS and ngtcp2, plus an ngtcp2 GnuTLS backend Homebrew does not ship, so
obrstopped at launch on any Mac but the build machine; v2026.9.2's OpenCV, ONNX and LAME bindings needed Homebrew formulas too. HTTP/3's TLS moves to AWS-LC, linked statically intoobron Linux and macOS with ngtcp2, nghttp3 and nghttp2, and the.pkgcarries OpenCV, ONNX Runtime, mbedTLS, libiodbc and LAME. It runs on macOS 13.3 or later, the ONNX binding on macOS 14 - ARM64: a collection could corrupt an object under multithreaded load — the collector set the mark bit below any nursery address its conservative scans found, including the stale and interior pointers compiled ARM64 code leaves on the stack. For a map's tree node that turned an empty
@rightinto 1, and a later lookup crashed: silently or with “Invalid object cast” on Windows arm64, with SIGSEGV on macOS and Linux arm64. It marks only real object starts now - Linux archives install their whole runtime —
install_deps.shinstalled SDL2 alone, so the other bindings failed to load on a fresh machine; it now maps every library the binaries link to its package, and--checkreports what is missing - ODBC says why a connection did not open —
Connection->GetLastError()was empty after a failed connect; it returns the driver manager's diagnostic, e.g.[IM002] ... Data source name not found - Licenses ship with the code they cover — the AWS-LC, ngtcp2, nghttp3 and nghttp2 code inside
obr, and the libraries the macOS package carries, ship their license files indoc/licenses - Every platform is verified before a tag — one script per machine builds a clean checkout the way the release does and runs the regression suite with the default JIT and with every method compiled, plus the VM flag, debugger and DAP tests; install instructions are checked against the libraries the binaries link; a dispatched Release Build can no longer publish; and a test that did not run no longer counts as a pass
v2026.9.2
- macOS ships OpenCV and ONNX again — v2026.9.1's
.pkg,.zipand.tgzcarried neitherlibobjk_opencvnorlibobjk_onnx. Homebrew's defaultopencvis now 5.0, which movedcontourArea,boundingRect,approxPolyDPand the affine estimators out ofcv::, and the release build installed it while CI stayed onopencv@4. The release build is pinned too - Linux x64's ONNX loads without
LD_LIBRARY_PATH—libobjk_onnx.sohad no$ORIGINRUNPATH, so it found the ONNX Runtime shipped beside it only where CI's environment pointed there - Linux ARM64 no longer ships an x86-64 ONNX Runtime — only an x86-64 runtime is vendored, so ONNX is declared optional on ARM64 and the 16 MB x86-64 library is gone from the tarball
- A deploy that cannot build a required native library now fails — the Linux and macOS deploys verified their native libraries and ignored the result, so v2026.9.1 printed verification failures on three platforms and published anyway; CodeQL now also builds the OpenCV, ONNX and LAME bindings
gl_crystal.objships — the modelgl_model.obsloads had never been committed, because.gitignore's*.objrule for MSVC object files matched it too. Every deploy copies it now, the MSYS2 builds gain the OpenGL examples, and a deploy missing a file an example opens by name failsImage->Normalize()could write past its output array — the OpenCV binding sized it asrows * cols * 3in 32-bitint, which wraps above about 716 megapixels: a crash up to about 1.43 gigapixels, an out-of-bounds write on the VM heap beyond that. It is sized insize_tnow (CodeQL #362)- Deploy scripts show live progress — a banner, stage progress and quiet tool output with the full log kept, and
-vstreams everything instead - The Windows API-docs search-index check runs — it existed only in the generated
code_doc64.cmd, which every deploy regenerates from its template; it is in the template now, and CI checks the templates
v2026.9.1
- Compiled code now calls compiled code directly — a call between JIT'd methods used to cross a C++ bridge: an eleven-argument entry, a pooled frame, a release. The caller now builds the callee's frame on its own stack and enters its native entry, with inline caches for
virtualand func-ref sites. A bound call went from 26.5 ns to 5.5 ns, avirtualcall from 125 ns to 6.0 ns, andFib(32)from 0.208 s to 0.043 s on AMD64; on an M4 Max a call went from 17.1 ns to 7.4 ns andFib(32)from 0.135 s to 0.050 s. A denseselectcompiles to a jump table on both backends - Every hash of a string was wrong — Hash->SHA256("abc"->ToByteArray()) digested "abc" plus a zero byte. A Byte[] carries its element count in the word native libraries read, and the JIT plus thirteen trap producers wrote count+1 for the NUL pad; the interpreter's Byte->New wrote the count. [0] is the element count everywhere now, and a test hashes arrays from every producer against known digests
- JIT arithmetic matches the interpreter — IMUL wrote its product to the wrong register (its one caller passed the arguments backwards to compensate), native-call temporaries were never spilled so 7 + x->Pow(5.0) + Bump(x) compiled differently than it interpreted, 64-bit multiply immediates were truncated, and relinking could retarget a select's default arm. The equivalence fixture now diverges on the old VM and matches on this one, on every platform
- The JIT is 2–8× faster on common loops — a->Size() is inlined (an array-summing loop 8×), a constant divisor is a multiply (2.5×), array addressing is one instruction, and AMD64 allocates from eight registers instead of four. Two shipped bugs found on the way: >> was a logical shift on AMD64 (every negative operand wrong), and ?-> on a nil receiver in JIT'd code exited the process instead of yielding Nil. OBJECK_JIT_REPORT=1 names the methods the JIT hands back to the interpreter and why
- Breakpoints fire inside threads, and threads are real — spawned threads were invisible to obd and DAP answered every threads request with a fabricated single thread. The model is all-stop with stable thread ids, an obd 'threads' command, DAP reporting the thread that actually stopped, and conditional breakpoints that evaluate in the stopping thread's frame
- Nine debugger commands reported success while doing the wrong thing — unwatch removed every second watchpoint, delete removed the current line's breakpoint, set stored 0 for a string, p n / 0 took the debugger down, string comparisons compared pointers; DAP evaluate ignored frameId. Hex literals scan (0x2a was an unknown variable); setVariable through an expanded object or Int[]/Float[] handle assigns the field or element it names instead of a top-frame local; the CLI set and DAP share one assignment path
- The language server crashed at startup — a garbage-collector range test accepted an unaligned pointer; root-caused with a hand-built debug loop, 0 crashes in 200 runs after
- Game.OpenGL — Skybox (a procedural sky, no assets), Quaternion (slerp and composition, caught wrong by a headless test), tangent-space normal maps with no vertex or native change, Material->SetEmissive so a surface can be visible where no light arrives; the overlay no longer draws every label and HUD bar upside down
- VM flags with checked values — --jit=off|
and --lib-path= (the lib root: native libraries and cacert.pem for obr, .obl files for obc); every flag states its valid values and refuses others; a 'g' suffix on --gc-threshold means a gigabyte, not a terabyte - Libraries — JSON escapes string values and keys on serialize, so a value holding a quote or newline produces valid JSON without callers pre-encoding; the Ollama client reports {"error": ...} replies instead of swallowing them; POSIX Pipe->WriteByte, Runtime->Command() stderr, File->Owner() and CommandOutput() now match Windows
- macOS ships an uninstaller — the .pkg wrote to four system locations and shipped no way to undo them; the shell edit carries a marker so removal cannot match a line the user wrote
- Compiler — name resolution stopped copying the library maps per lookup and AddMethod's duplicate check is indexed -- about a fifth of a large program's compile time; the scanner's keyword table is the one source of truth
- Release process — signing regenerates the checksum manifest it invalidates, a manual step is declared once and printed as a to-do, an open issue must be fixed or explained before a tag, POSIX deploys verify every native library they built, the weekly secret scan can be green, and the signing-credential check verifies the certificates the release actually uses
- Tests — TLS verification is tested for what it refuses (self-signed without a trust anchor, a trusted certificate that does not name the host), the interpreter and the JIT are compared byte for byte on every platform, and every fix above ships with a test that fails on the v2026.9.0 binaries
- Three ways compiled code could corrupt memory — a frame holding a declared-but-unreferenced local was laid out from its references but scanned by declaration, so the collector read every lower slot under the wrong type; a loop that parked at a GC safepoint kept a stale
selfafter another thread's collection moved it (#746); and a constant character stored into aChar[]wrote eight bytes on ARM64 and Linux x64, overwriting its neighbours and running past the end of the array (#781) - The compiler mis-built two common shapes — every string concatenation in a method shared one accumulator, so
F(a+b) + cproduced the wrong string or crashed (#750, #752); and the-opt s3inliner shifted onlyIntandFloatslots, so a method taking a func-ref parameter stored the reference over its caller's locals once inlined (#763) - Runtime properties, locales and exit codes —
Runtime->SetPropertydropped every set after a property's first, and on Linux and macOS a first set kept the runtime's own directories from ever loading;SetLocalerefuses a name the system cannot supply; andobron POSIX exits non-zero after a VM-reported error, as it always did on Windows - Console->WriteBuffer(Char[]) corrupted every write after it — the VM encoded the buffer to UTF-8 itself and wrote the bytes into a stdout already in a wide CRT mode, so the data was encoded twice (
'A','B'arrived as U+4241) and the invalid sequence left the stream unusable for the rest of the program; it also ignored the count it was given. Found throughfasta, which had never compiled - The standard libraries are rebuilt by the compiler that ships with them — the committed
.oblpredated four compiler correctness fixes, including the func-ref inliner that library code is compiled with (-opt s3); 30 of 32 libraries changed
v2026.9.0
- A server that wrote a response and closed could lose all of it — on Windows loopback the reader got a connection reset and zero bytes, even though every byte had been accepted and delivered.
TCPSocketandTCPSecureSocketgainCloseGracefully(), which reads until the peer hangs up and then closes, so the client owns the teardown. Measured over 180 transfers of a 16KB response:Close()lost 21,CloseGracefully()lost none - The language server serialized every request behind one lock — concurrent analysis was correct only because of it, with
TreeFactoryandTypeFactoryas process-wide singletons underneath. They are now bound per thread through a scope guard, so each analysis gets its own and the coarse lock gives way to per-program locking - Four publish steps reported success while doing nothing — Sourceforge, the Marketplace, the playground and the API docs each skipped on an absent credential and passed, so v2026.8.4 published with all four green while the playground served a three-month-old engine. A missing credential now fails and names the secret, or is declared manual in one place that also prints as a to-do, and a pre-flight gate checks the pipeline can do what it advertises before the tag is pushed
v2026.8.4
Game.OpenGL— 3D graphics for Objeck — OpenGL 3.3 core over SDL2 on Windows, Linux and macOS. 26 classes covering windowing and frame pacing, built-in shaders, meshes and OBJ loading, textures, cameras, materials, up to eight directional/point/spot lights with Blinn-Phong specular, shadow maps including omnidirectional cube shadows, render-to-texture, instancing through a one-callPropBatch, frustum culling,Scene->Raycastfor hitscan and picking, gamepad input, a transform hierarchy with keyframed animation, particles, billboards, a pixel-space text overlay, and a scene that answers collision. The examples got shorter as it grew — the minimal window demo went from 105 lines to 25, and per-frame allocations in both original draw loops went to zero. Verified by 453 checks that read pixels back rather than merely exiting cleanly, and two demos ship in the distributionWeb.Servercould not be used by anyone — it shipped in every release with 13 native entry points that existed in exactly one file: the binding itself. No.cpp, no build target, no library in any deploy tree, andRequest/Responsedeclared no constructor, so a program could not obtain an instance at all. Writing the missing native library was never an option — the design is a per-host bridge for Nginx, IIS and Apache, whose request structures differ entirely, so one generic library cannot exist. It is now implemented in pure Objeck overWeb.HTTP.Server: same bundle, same class names, same signatures, no native library. Coverage went from 0 of 13 methods to 13 of 13- The JIT silently computed the wrong answer above 231 — 64-bit immediates were truncated to 32 bits: on AMD64 for
and,or,xor,addandsub, and on Windows ARM64 for every one of them, wherelongis 32 bits under LLP64. No crash and no diagnostic, just wrong arithmetic. A stored float compare also clobbered a callee-saved register on AMD64. Windows ARM64 had shipped untested since February, which is why its variant survived - A server that wrote and closed could lose the response — on Windows loopback, roughly 47% of responses, because the sender tearing down first discards what the receiver has not read. HTTP now uses keep-alive, removing the exposure rather than hiding it. Alongside it: a short
send()silently dropped the rest of the buffer on both platforms, a real HTTP 500 lost its body while a dead socket reported one, and one failed name lookup calledWSACleanupand shut Winsock down for the whole process — every open socket on every thread - Three ways a live object could be collected — an array returned by a VM trap held elements a minor collection could destroy (measured at 395 of 395 entries lost in one collection: arrays are born old, objects young, and the trap array was never dirtied through the write barrier); a value returned by a native library could be collected out of a reused argument buffer; and the JIT's
Int[]copy dropped the write barrier entirely - Windows ARM64 installs shipped without their runtimes — no C++ redistributable, because
VCToolsRedistDiris empty on the ARM64 runner, and OpenCV without its image codecs. Nothing checked either, so both failed on the user's machine rather than in CI. Cross-architecture native dependencies are now verified during the build - A server that returns normally from
Mainno longer segfaults — a thread blocked in a syscall never observes the halt request, so teardown freed the program image while that thread was still live, andWSACleanupon the way out then unblocked it into freed memory — losing all buffered output, so it looked as though the program had done nothing. Linux was always clean for one reason: it has no equivalent call. Exit also stopped taking half a minute, since the drain countedsleep_for(1ms)iterations as 1ms each against Windows' ~15.6ms granularity - The debugger had the same defect, and there it was not Windows-only —
obdhosts the debuggee's VM in-process and freed the program image and the whole GC heap after every run, halting and waiting for nothing. Becauseobdreturns to its prompt rather than exiting, an ordinary client connecting to the port the parked thread sits on wakes it with noWSACleanupinvolved: 6 access violations in 6 runs on Windows, 2 in 2 on Linux obdcould not debug any multithreaded program — compiled with-debugit segfaulted on the first instruction a spawned thread executed. Those threads are built by a constructor that never initialized the debugger pointer, and the per-instruction hook called through it. Onlyobdcompiles that hook in, soobrwas never affected- Native calls got materially cheaper — a string literal allocates on every evaluation, and the literal naming the native function turned out to be 92% of a call's cost: 1655ns down to 130ns. Resolved entry points are now cached too, on every platform, removing a
GetProcAddress/dlsymlookup and a wide-to-narrow conversion from every single call. Both are guarded by CI so they cannot drift back - SDL2 loads on Windows without a hand-set
PATH— the DLLs shipped inlib/sdl, but Windows resolves a dynamically-loaded library's imports against the executable's directory, never the library's, solibobjk_sdl.dllfailed to load for anyone who had not added it themselves. Every SDL program was affected, and the regression runner hid it by prepending the directory first. macOS now bundles SDL2 rather than asking users to install it - The API reference stopped omitting whole libraries — five files hard-code the library list and had drifted apart, one short two libraries while still naming a deleted third, so the counts matched and nothing looked wrong. Underneath, the doc parser was reading prose as code: the word "bundle" in a comment re-filed every class after it
obu updateandobu rollbackon Windows — the in-place swap needed no copy-self-and-re-exec dance: Windows forbids deleting a running image but permits renaming it.obu checkalso gained the offline test coverage it had on no platform
v2026.8.3
- A corrupt library could crash the compiler —
TypeParser::ParseTypeandParseParametersswitch on the first character of a type string and had no default case, so anything outside the known set left the type null and was dereferenced immediately. An empty string reaches this too, sinceoperator[](0)on an emptywstringyields a null character. The linker calls both on type strings read straight out of.oblfiles, so the input is not the compiler's own - A
}on the first line hung the REPL — an unsigned indent counter decremented at0wrapped toSIZE_MAX, and the indent loop below then ran about 1.8e19 times. Listing and saving both hit it - One malformed request no longer ends a debug session — only JSON parse errors were guarded, so a message that parsed but carried an unexpected type threw from inside the handler, unwound out of
Run()to amain()with no handler, and terminated the process — losing every breakpoint and the running program over one bad request. Seven flags shared between the DAP and VM threads are atomics now: they were written under a mutex and read without one at every instruction, so nothing stopped an-O3 -fltobuild hoisting those loads out of the dispatch loop, and a disconnect or step could go unseen indefinitely - A connect that never completed could report success —
getsockopt(SO_ERROR)was unchecked on both the POSIX and Windows connect-with-timeout paths, and both could hand back a socket still in non-blocking mode, so a caller expecting a blocking read got a spuriousEAGAIN/WSAEWOULDBLOCKinstead of data. The uncheckedF_GETFLbehind the POSIX case also restored garbage flags onto the socket. The same shape in the REPL editor's child-process plumbing could stall the poll loop insideread(), hanging the editor rather than returning an error - One ONNX call reformatted every float for the rest of the run — both generation reports applied
std::fixedwithsetprecision(1)directly tostd::wcoutand never restored it, and nothing on the Objeck side can clear a leaked floatfield, so every float an Objeck program printed after one SLM or vision call rendered in fixed notation at one decimal.StdErrFloatcarried the mirror-image bug: it read the saved state fromstd::wcout, modifiedstd::wcerrand restored onto narrowstd::cout— three different objects - Two silent compiler mistakes — a lambda whose signature collided with an existing method was dropped with no diagnostic at all, because
AddMethod's false return was ignored while the code carried on encoding and associating it; and one ofMethodCall's five constructors leftfunc_ref_unwrapindeterminate, so non-null garbage meant emitting a bogus call - Entry points survive what they throw —
obc,obr,obdandobieach had a long unprotected prologue (locale and codecvt construction, and the usage-string building that is abad_allocpath) where anything thrown calledterminate()with no message. Every entry point is now wrapped - Windows installers are signed — and the notes claim it only when true — every Windows MSI from v2026.4.0 through v2026.8.2 shipped unsigned while the generated notes asserted otherwise:
signtoolwas configured, ran, failed on every artifact, and the build warned and continued. The key is on a hardware token, so CI can never sign; signing is now an explicit local step, and a checker reports the realGet-AuthenticodeSignaturestatus rather than inferring it from the file existing - Coverity Scan on Windows as well as Linux — the first Windows scan turned up twenty real defects in cross-platform sources that MSVC compiles differently than GCC, so the Linux scan had never reached them. The scan token now lives outside the tree, and
linux-arm64— a native runner that had never been exercised before publication — is now smoke tested too
v2026.8.2
- Subscript the result of a method call —
GetItems()[0]->GetName()now works. It had never been implemented, and the grammar swallowed the attempt:[after a call was read as a fresh static-array literal, so the call was evaluated and discarded.GetArr()[0]->Size()silently returned1andGetArr()[0]->PrintLine()printed[0]; with an object array the same cause surfaced as "Undefined function/method call". Behaviour change: code that compiled and returned the wrong value now returns the correct one - The release build proves the toolchain works — every earlier gate asserted only that files existed, so a release could ship binaries unable to compile or run anything and still go out green. Both platforms now compile and run a real program from the shipped tree and assert the reported version matches the tag.
deploy_windows.cmdalso re-ranupdate_version.ps1, regeneratingversion.hfrom a hardcoded version — a disagreement meant Windows built a different version whose binaries rejected the committed.oblset, failing every program - Face detection never returned a single face —
FaceSession->Detectand->Recognizeproduced zero results for every image at every confidence threshold, on every platform shipping the ONNX native library, since v2026.5.3. Inference itself ran normally, which made it look like a model or threshold problem.scrfd_decodecompared a row count against an element count: each SCRFD output is[N, cols]andnis alreadyN, but the bbox and keypoint tensors were tested againstexpected * 4andexpected * 10, so at 640×640 stride 8 the guard read12800 < 51200and every stride group was skipped. Only the score tensor, withcols == 1, compared correctly, which disguised it. Verified with the InsightFace buffalo_l models: 2 faces in the sample group photo, 512-dimensional embeddings, same-person similarity 0.767 and different-person -0.023. YOLO and ResNet inference were unaffected obuwas missing from every release archive — v2026.8.0 shipped the updater as a headline feature and delivered no binary.release-build.ymlnever referencedobu, and none of the three deploy scripts built or copied it, sobin/heldobb obc obd obi obron Windows, Linux x64/ARM64 and macOS alike. The source, its POSIX makefiles and its.vcxprojhad existed the whole time — only the packaging was absent. CI did not catch it becauseci-build.ymlexercisesobusolely throughtest_update.sh, which builds its own copy with test hooks: the updater was tested continuously while never being shipped. It is now built and installed tobin/by all three deploy scripts, and both "Verify required binaries" gates list it, so a future omission fails the build before a tag is pushedHeaderCheckdocumentation was largely invisible — the class landed in v2026.8.0 with onlyIsValidRequestTargetdocumented.IsValidNameandIsValidValue, the two functions guarding everyAddHeadercall, carried no doc comment, and the API index records only documented members — so hover and completion showed nothing for the security fix's primary entry points.Flatten's doc block also sat aboveIsValidRequestTargetrather than aboveFlatten, documenting the wrong function. All four are now documented and correctly bound- Full-screen editor in
obi—/eopens raw-mode terminal editing over the REPL buffer: syntax coloring driven by the compiler's own scanner, damage-diffed rendering, CJK/tab-correct widths, undo/redo with coalesced typing, Shift-selection and a clipboard, plus an opt-in vi profile (F2). F5 compiles and runs the buffer as a subprocess, streaming its output into a pane that Esc can cancel, and F8 walks the cursor through compile errors. Header-only, with no build-system changes on any platform - HTTP/3 on Windows —
Http3Clientnow works on Windows 11 / Server 2022 and later, backed by WinHTTP over MsQuic. It had shipped documented-and-dead: the trap handlers compile unconditionally, so the API was present and every request simply failed. WinHTTP treats HTTP/3 as a preference, so every request asserts the protocol actually used and fails rather than silently downgrading. No vendored QUIC library, no second TLS backend, no new DLL to deploy - Five HTTP request-injection fixes — the most severe needs only a URL:
Url->Newdoes not sanitize, and the path and host were appended verbatim into the HTTP/1.1 request line, so a CR/LF split the request line itself. Caller-supplied header values and content types were injectable the same way across HTTP/1.1, HTTPS, HTTP/2 and HTTP/3; a newWeb.HTTP.HeaderCheckvalidates names, values and request targets per RFC 9110/9113 at every serialization site. Separately, HTTP/3 connection IDs could be uninitialised stack memory when the CSPRNG failed, since thegnutls_rndreturn value was ignored — a memory disclosure in the cleartext QUIC Initial header obuupdater —obu checkcompares the installed version against the latest GitHub release;obu updateandobu rollback(Linux/macOS) download the platform archive and itsSHA256SUMS, verify the digest before touching disk, then do an all-or-nothing staged swap with a post-install check and automatic rollback. No shell is used for the download, extract or swap. Every release now ships aSHA256SUMSassetAddHeadernow actually sends headers on HTTP/2 and HTTP/3 — both clients stored headers on the Objeck side and then dropped them, because the trap signature had no headers argument and nothing ever wrote the map the native backends were already reading. Verified by a server echoing the value back, not by a status code. HTTP/1.1 was never affected- ARM64 JIT clobbered a general register on every float compare —
move_freg_fregaddressed the general register file rather than the FP file, because theRegisterenum restarts float numbering atD0 = 0. When the clobbered register held a live pointer, the next use followed a float bit pattern as an address — the long-open "memory corruption of free block" crash, whose faulting PC0x3F947AE147AE147Bis the IEEE-754 bits of0.02. Correcting the encoding then exposed a stray copy that zeroed the divisor of every JIT float division. AMD64 was correct throughout v->Pow(10)computedPow(10, v)— 100 instead of 1024 — whenever the receiver was a variable, instance variable or array element; literals were correct, so the two spellings of one call disagreed. All 29 multi-argument primitive functions were affected. A calculated receiver in an expression,(1 + 1)->Pow(10), corrupted the heap outright because the emitter dropped the call arguments- Divide by zero crashed at default optimization — the constant folder kept a zero-divisor division for its runtime trap but emitted it before its operands, turning a clean trap into a silent crash. Modulus by zero never trapped at all, and now traps exactly as division does
- Runtime feature reporting —
runtime.feature.http2andruntime.feature.http3report which protocol engines were actually compiled in, so a caller can tell not supported from the network failed. Relatedly,obdhad shipped with HTTP/2 and HTTP/3 compiled out, and HTTP/3 was silently unavailable on Linux ARM64 - ONNX inference hardening — fixed an out-of-bounds read when a model exported mismatched KV key/value tensor counts, guarded the logits rank/offset access, surfaced an unsupported logits dtype instead of silently sampling token 0, and made the token sampler safe on empty/degenerate distributions
- Debugger String rendering — the DAP formatter read a String's backing-array capacity instead of its length, returning NUL-padded values on POSIX platforms; both front ends now read the length from the String itself via a shared layout header
- Nil-safe operators —
a?->b()callsbonly whenais non-Nil, yieldingNilinstead of faulting, anda ?? bsuppliesbwhenaisNil(evaluatingbonly when needed). A single?->guards the whole rest of a chain, somaybe?->Trim()->ToUpper()is safe throughout, and the two combine:maybe?->ToUpper()->Size() ?? -1. Both desugar onto the existingTry()/Otherwise()intrinsics, so no new bytecode is emitted and the JIT backends and VM are unchanged. Spelled?->rather than?.because Objeck's member accessor is-> - Language server crash fixes — five requests took the server process down rather than returning an error: go-to-implementation, semantic tokens, inlay hints, and both call-hierarchy directions. Each returned a
Result[]through the local argument array and failed its cast; they now write into the analysis instance the way find-references and document-symbols already did - Language server resolved the wrong method — a method's line range was converted to the editor's 0-based numbering at its start but not its end, and the end records the token after the closing brace, so every method overran onto the next declaration. Any cursor past the first method of a class resolved to the first method, affecting go-to-definition, find-references, hover, rename and call hierarchy
- Chained calls after a nil default — anything written after
Otherwise()was silently dropped, sox->Otherwise("abc")->ToUpper()returned"abc".Try()/Otherwise()also now resolve on an indexed receiver, soarr[i]?->m()compiles - Formatter no longer breaks source — the formatter scanned
?one character at a time, so formatting a file that used??emitted? ?and produced code that would not compile - Editor tooling is tested in CI — the formatter, language server and VS Code extension now run on every push. Two of those suites had never executed: the formatter's runner pointed outside the repository, and the tooling scripts appended the build tree to
PATHso a system-wide install shadowed it
v2026.6.4
- Multithreaded GC stability fix — fixed an intermittent crash (
0xC0000005) in the generational minor garbage collector during thread startup: a thread being spawned held itsselfand argument as untracked raw pointers, so a moving collection during the spawn handoff could relocate the object and leave the new thread a stale reference. These are now tracked and relocated across collection. Surfaced only under heavy multithreaded churn
v2026.6.3
- Generational minor garbage collection — minor (nursery) collection is now enabled: a nursery-full collection scans only the remembered set plus roots and recycles the young generation without sweeping the old generation, falling back to a full major GC under old-gen pressure. JIT and interpreter reference stores emit the write barrier on AMD64 and ARM64, and the nursery is zeroed at allocation time instead of inside the stop-the-world pause
- Closure ergonomics — call a
FuncRefdirectly withv()(no explicit->Call()); write bare lambdas with an inferred return type (\(x) => x * 2) that auto-wrap intoFuncRef<R>when assigned, returned, passed as a method argument, or stored as a collection element; and give a lambda a block body (\(x) => { ... }). A multi-capture closure heap-corruption bug is fixed (captures now use closure-local ids) - New
System.Concurrencylibrary — structured concurrency withTaskScope,Task, andMonitor, plusruntime.*process/GC/CPU diagnostics (GC pause, promotion, allocation rate, lock contention, thread/STW/nursery counters) read throughRuntime->GetProperty
v2026.6.1
- String interpolation —
"{$...}"now accepts arbitrary expressions ("{$i + 1}","{$a * b - c}","{$x > y}"), Python/.NET format specifiers for precision, width, alignment, and radix ("{$pi:.2}","{$n:05}","{$s:<10}","{$v:x}"), and a positionalString->Format("{0} = {1}", a, b)helper - Generics — bounds and variance — compound bounds (
T : A & B), F-bounded constraints (T : Compare<T>), and declaration-site variance (out Tcovariant,in Tcontravariant), checked soundly and preserved across the.obllibrary boundary; readable generic type-mismatch diagnostics - Multithreaded garbage collection — the generational collector is now cooperative stop-the-world: mutator threads park at safepoints (interpreter dispatch, JIT back-edges on AMD64/ARM64, allocation, and blocking
join/sleep/socket I/O) so the collector always marks a complete root set; fixes freed-live-object corruption and use-after-free under thread churn - Debugger overhaul — command line and VS Code —
obdgains frame navigation (frame/up/down) withlocals, live editing (set x = 5), method breakpoints (b Class->Method), temporary and conditional breakpoints with ignore counts, data breakpoints (watch), and run-to-line (until); the VS Code adapter (DAP) adds editing variables, function breakpoints, logpoints, in-process restart, and exception breakpoints - Secure sockets verify certificates by default — TLS and DTLS clients validate the certificate chain and hostname instead of accepting any certificate; set
OBJECK_TLS_INSECURE_SKIP_VERIFY=1for self-signed/dev servers - Serialization & memory-safety hardening — 64-bit
Int/Int[]values no longer truncate to 32 bits or drop half the array, and function-reference fields (de)serialize without desync (note: the integer wire format widened to 8 bytes); object deserializers bounds-check attacker-supplied sizes and aChar[]read-trap heap overflow is fixed - New
Web.Serverlibrary (-lib web_server) — a lightweight HTTP server bundle for simple request/response and multipart handling - Reproducible builds & ONNX — compiling unchanged library source now produces byte-identical
.obloutput; on macOS the compiled CoreML model is cached across runs (~35× faster warm starts)
v2026.6.0
- New
System.AIlibrary (-lib ai/@ai) — classic AI in the standard library: graph search (Dijkstra,AStar,BreadthFirst,DepthFirst), adversarial game search (Minimaxwith alpha-beta,MonteCarloTreeSearch), metaheuristics (GeneticAlgorithm,SimulatedAnnealing,HillClimbing), and tabular reinforcement learning (QLearning,Sarsa,MarkovDecisionProcess); all stochastic algorithms are seedable System.MLoverhaul — 13 new estimators (regularized regression, SVM, perceptron, PCA, Gaussian naive Bayes, AdaBoost, DBSCAN, Gaussian mixture, KD-tree, gradient-boosted trees); real recursiveDecisionTreeand votingRandomForest;NeuralNetworkbias vectors; seedableSystem.ML.Random; a uniformFit/Predict/Score/Store/LoadAPI. Breaking:RandomForest->Trainis nowFit; storedNeuralNetworkmodels must be regeneratedrecordtypes — generate constructor and accessors from field declarations;record : readonly :omits setters and rejects field assignment outside constructors; supports generics and inheritance- JIT & compiler fixes — frame-dependent traps stay interpreted past the auto-JIT threshold (AMD64 + ARM64); ARM64 stale-
selfreload after callbacks; float equality on array elements no longer mis-compiled; bool array literal-pool corruption fixed - Library improvements — library aliases (
@std/@ml/@ai/@game) documented; Data.XML rejects truncated documents, fixes'decoding, and addsEncodeText/SetEncodedContent/GetDecodedContent/GetDecodedValue
v2026.5.4
- Debugger test reliability — Windows CI debugger tests fixed;
.obe/.oblformat detection now correctly handles the edge case where a new-format size-header LSB collides with the0x78zlib CMF byte - LSP shell script permissions — all
tools/lsp/shell scripts now carry the execute bit in git, fixingPermission deniedin the LSP release CI job - Release workflow hardening —
git checkout -f masterprevents dirty-tree abort when committingapi.zipfrom a tag-based build
v2026.5.3
- JIT
selectdispatch — dense integerselect(6+ cases) emits a native O(1) jump table; small sets use a linear scan; sparse/string falls back to BST — best strategy chosen automatically on AMD64 and ARM64 - API documentation overhaul — bundle overview panels, 500+ inline code examples, global search index, two-column TOC, method badges, and anchor links across all 32 library pages
- ODBC improvements — live SQLite integration test; transaction support (
Commit/Rollback/SetAutoCommit) verified;GetColumnsmetadata - Bug fixes —
HttpRequestHandlerNil safety on dropped connections;String->Split(Char)trailing token fix;bench_spectralnorm_nativeJIT stack-balance fix - Performance —
bench_spectralnorm_native: incremental FP denominator eliminates per-elementI2Fconversions from the inner loop
v2026.5.2
- HTTP/2 client —
Http2Clientwith persistent TLS connections, GET/POST/PUT/DELETE/PATCH, andQuick*one-liners via nghttp2 + ALPN - HTTP/3 / QUIC client —
Http3Clientover UDP with connection reuse and the sameQuick*API (ngtcp2 + nghttp3 + GnuTLS) - HTTP/1.1 improvements — PATCH method, redirect handling fixes for POST/PUT, retry parity across
HttpClient/HttpsClient - OpenAI Moderation & Batch —
Moderation->Check()per-category flags/scores;Batch->Create()/Get()for async 50%-cost batch requests - Gemini Files, Cache, Grounding, BatchEmbed — upload/list/get/delete files; server-side prompt caching; Search Grounding; batch embeddings in one round-trip
- WebSocket hardening — 8 bug fixes + bulk
ReadBufferI/O replacing per-byte reads - MCP server fixes — hang on shutdown and crash-on-stop resolved
- Socket reliability —
SO_REUSEADDRonTCPSocketServer::Bind();IPSocket::Open()falls through to next address on failure - ARM64 Windows — OpenCV and ONNX now fully supported on ARM64 Windows
- Improved release process — self-contained Windows builds; CI verifies all binaries and API docs on all platforms before publishing
v2026.4.3
- DAP debugger hover — hovering an object shows
ClassName { field=val, ... }with one-level instance field expansion - DAP instance/class variable scopes — Variables pane shows separate Locals, Instance, and Class scopes
- DAP stepping + crash fixes — fixed step-into crash, step-over/out scoping, stdout corruption, disconnect access violation
- Editor setup refresh — updated VS Code, Sublime Text, and gvim DAP+LSP setup for Windows, Linux, and macOS
- LSP crash fixes — null guards for
textDocument/codeActionwith inferred locals, hover position fix - Configurable JIT threshold — auto-JIT invocation count can now be tuned
- Fixed JIT S2F callback param count causing segfault on
String:ToFloat - Hardened HTTPS client against null ReadLine on connection failures
v2026.4.2
- JIT local variable register cache (AMD64 + ARM64) — ~3x speedup across all benchmarks
- DTLS support — secure UDP via
DTLSSocketandDTLSSocketServer - AI libraries — Gemini 2.5, Ollama options/tools, OpenAI embeddings, ML fixes
- Hardened JSON/XML parsers, LTO, ARM64 native CPU tuning
v2026.4.1
- Debug Adapter Protocol (DAP) for VS Code with conditional breakpoints and ANSI colors
- 3.3x binarytrees speedup — young-gen bump allocator, direct JIT-to-JIT calling
- GC thread safety with memory barriers to fix intermittent threading segfaults
- macOS .pkg installer — signed and notarized with PATH auto-configuration
- Networking, ODBC, OpenCV, Phi-3 Vision improvements
v2026.2.1
- Added
try/otherwiseerror handling framework - 4.38x nbody speedup, CSE, dead code elimination
- 14 debugger and 16 runtime regression tests in CI
v2025.7.0
- Added
Hash->Dict(),Map->Dict(), andVector->Zip()to collections - Updated style (docs, logos); bug fixes
v2025.6.3
- Support for user-provided HTTPS PEM files
- Multi-statement pre/update support in
forloops
v2025.6.2
- New API documentation system
- OpenAI Responses API; improved JSON schema support
Quick Start — API Docs — All Releases — Rosetta Code — Report an Issue
Tested on Windows 10/11, Ubuntu 24.04 LTS, and macOS 15 (ARM64 + x64). Licensed under BSD-2-Clause. Source on GitHub.