Skip to content

Releases: Cob-Software-Foundation/Cob

Cob v0.0.5

Choose a tag to compare

@github-actions github-actions released this 15 Sep 21:05

Cob Language v0.0.5

Cob v0.0.5 -- Codename C!

Overview

Three new capabilities for cob_interp, all opt-in and none of them
affecting the interpreter's original zero-dependency build:

  • SQLite (sql_open/sql_exec/sql_query/sql_close) and
    _cobwindow, a native-window GUI backed by raylib
    (window_open/window_label/window_wait/window_close) with
    real, interactive raygui widgets (window_button/
    window_slider/window_textbox), are now baked into
    cob_interp_full -- the binary plain make builds by default.
    Both build with a plain Makefile, no configure/autoconf step for
    either, so a clean make from a fresh checkout builds everything
    itself in well under a minute.
  • Tcl/Tk (tcl_eval/tk_eval) are still available, but no longer
    part of the default build -- make cob_interp_db builds a separate
    binary with them, for anyone who specifically wants that and is
    willing to accept a much heavier, autoconf-based Tcl/Tk source build
    (see "Fixed" below for what that build fights through on some
    Windows toolchains).
  • make cob_interp remains the original lightweight interpreter --
    no SQLite, no _cobwindow, no Tcl/Tk, no vendor build at all.

Also new this release: a stress-test suite (tools/stress/), a
Dockerfile to run it in a reproducible container, and both a
ci.yml GitHub Actions workflow that runs it in Docker and natively,
and a build.yml workflow that now also round-trips the widget
keywords through the .strawberry cache.

Added

SQLite bindings

sql_open(<path>)           -> handle (int, 0 on failure)
sql_exec(<handle>, <sql>)  -> rc (int, 0 on success)
sql_query(<handle>, <sql>) -> string (first column of first row, "" if none)
sql_close(<handle>)        -> 0
set h = sql_open("scores.db")
set rc = sql_exec(h, "CREATE TABLE IF NOT EXISTS t (name TEXT)")
set rc = sql_exec(h, "INSERT INTO t VALUES ('cob')")
set name = sql_query(h, "SELECT name FROM t LIMIT 1")
pop("got: " + name)
set rc = sql_close(h)

Builds via a single-file amalgamation (vendor/SQLite/sqlite3.c) --
no configure step, compiles the same way on every platform.

_cobwindow -- a native-window GUI backed by raylib, now with real widgets

window_open(<title>)             -> handle (int, 0 on failure)
window_label(<handle>, <text>)   -> 0 (sets/replaces the in-window text)
window_wait(<handle>, <seconds>) -> 0 (keeps the window responsive for ~<seconds>)
window_close(<handle>)           -> 0

window_button(<h>, <label>)        -> 1 if clicked since the last read of
                                       that label, else 0
window_slider(<h>, <label>, <max>) -> current value, 0..<max>, as an int
window_textbox(<h>, <label>)       -> current string contents of the box
shuck cobwindow
set h = window_open("Cob Window Demo")
set rc = window_label(h, "Hello from Cob!")
set clicked = window_button(h, "OK")
set volume = window_slider(h, "Volume", 100)
set name = window_textbox(h, "Name")
set rc = window_wait(h, 5)
set rc = window_close(h)

Backed by vendor/raylib (real 2D/3D graphics, proper anti-aliased
text rendering) instead of raw Win32/Xlib calls -- one build recipe
and one code path for every platform, rather than hand-maintained
separate Win32 and Xlib implementations. raylib's own build is a
plain Makefile: no configure, no autoconf, so none of the
busybox-ash/vendor-tree fragility documented under "Fixed" below
applies to it.

vendor/raygui (a header-only immediate-mode widget library that
draws on top of raylib) is now wired up to Cob syntax as
window_button/window_slider/window_textbox. Each widget is
identified by its own label text -- the first call with a new label
creates it, auto-stacked on screen below the window_label() text;
every later call with that same label (and kind -- a button and a
slider can share a label without colliding) reads or updates that
same widget. Declaring and reading happen in the same call, since Cob
has no separate "declare once, poll every frame" mechanism -- a
button's click flag resets on read, so a click is reported exactly
once; a slider re-ranges (and clamps) if called again with a
different <max>; a textbox is always in raygui's edit mode, since
Cob has no click-to-focus concept to hook a toggle to.

raylib only supports one native window per process (InitWindow()/
CloseWindow() are process-global, not per-handle) -- window_open()
called again before the first window is closed warns and returns 0,
same "0 means failure" convention every other handle-returning keyword
here uses. The close button ([X]) is intentionally swallowed -- Cob
has no callback mechanism to notify a running script that the user
clicked it, so the window keeps running until window_wait()'s timer
runs out or window_close() is called explicitly, the same
"explicit close only" model harvest()/trash() already use for
memory.

Verified for real, not just built: ran a .cob script against
cob_interp_window/cob_interp_full on a live (headless, via Xvfb)
X11 display and confirmed with actual screenshots that a real window
opened showing the label text, a button, a slider (with a readable
caption -- see "Fixed" below), and an editable text box with a
blinking cursor, all rendered with proper anti-aliased text.

cob_interp_full -- SQLite + _cobwindow, the new default

make (no target, i.e. make all) now builds cob_interp_full
instead of the lightweight cob_interp. It lists $(SQLITE_LIB) and
$(RAYLIB_LIB) as real Make prerequisites, so a single make builds
SQLite and raylib from vendor/ itself, with no separate build steps,
no configure/autoconf anywhere in the chain, and (confirmed) well
under a minute on a clean checkout.

make cob_interp still builds the original lightweight binary --
zero vendor dependency, builds in under a second -- for anyone who
wants that explicitly instead of the new default.

Kept as opt-in: cob_interp_db (SQLite + Tcl + Tk)

tcl_eval(<script>) -> string (Tcl's string result)
tk_eval(<script>)  -> string (same interpreter as tcl_eval, plus Tk)

Still available via make cob_interp_db for anyone who specifically
wants tcl_eval()/tk_eval(). This needs a real Tcl/Tk source build
(make sqlite tcl tk, or cob_interp_db triggers it automatically
the same way cob_interp_full triggers SQLite/raylib) -- see "Fixed"
below for the autoconf/busybox-ash issues that build can hit on some
Windows toolchains, now resolved for the two specific failures
reported so far. _cobwindow is not part of this binary; use
cob_interp_full for that.

Stress-test suite, Dockerfile, ci.yml, and build.yml

tools/stress/run_stress.sh builds cob_interp_full and runs three
.cob scripts designed to catch regressions that only show up under
sustained load, not a single quick smoke test:

  • stress_arithmetic.cob -- 200,000-iteration loop (interpreter
    overhead/stability)
  • stress_sqlite.cob -- 2,000 sequential INSERTs + a query (SQLite
    under load)
  • stress_window.cob -- 20 open/label/wait/close cycles (resource
    leaks in the raylib backend would show up as the loop slowing down
    or crashing, not just "does it open one window")

Dockerfile builds cob_interp_full in a clean Ubuntu 24.04
container with exactly the dependencies it needs (X11 + OpenGL dev
headers, Xvfb) and runs the stress suite as its entrypoint:

docker build -t cob-stress .
docker run --rm cob-stress                    # one pass
docker run --rm cob-stress --iterations 20    # repeat 20x

.github/workflows/ci.yml runs the same suite two ways -- once via
the Dockerfile (docker-stress job), once directly on the runner
(native-stress job) -- on push/PR to main, nightly on a schedule,
and on manual dispatch with a configurable iteration count.

.github/workflows/build.yml's test_extensions job now also opens
a real headless X11 window and round-trips window_button/
window_slider/window_textbox through the .strawberry cache --
write once, run again to force a cache hit, diff the two runs' output
-- specifically to catch a broken write_expr()/read_expr() pair
for the three new widget expression kinds (see "Fixed" below for why
this matters more than it might sound like).

Legal: raylib/raygui licenses

legal/license_raylib.terms and legal/license_raygui.terms added
(both zlib License). LICENSE.md's "THIRD-PARTY LICENSE NOTICE"
section was also out of date -- it only mentioned TinyCC, which isn't
even in this repo anymore -- rewritten to list every vendored
component actually present (miniz, SQLite, Tcl, Tk, raylib, raygui)
and where its license text lives.

cpi.cob.pixel-pulse.work.gd: fixed the "Package registry" 404 (separate repo)

docs/index.html's footer nav links "Package registry" to
.../download.html, which never existed on the cpi registry site
(Cob-Software-Foundation/cpi, a separate repo) -- only index.html
did, so the link 404'd. Added docs/download.html there: fetches
api/v1/packages/index.json and each manifest client-side, renders
them as cards matching the site's styling. This is a change to the
cpi repo, not this one -- shipped as its own small zip alongside
this release, not included in the main source zip.

Fixed

popcorn_comp: .strawberry magic constant was three format bumps stale

Repro: any plain .cob script, no SQL/window keywords required --
./cob smoke.cob then ./popcorn_comp smoke.strawberry -o smoke_native
failed with:

[popcorn_comp] error: 'smoke.strawberry' is not a valid .strawberry v3 file

Root cause: popcorn_comp.c keeps its own independent, byte-for-
byte-compatible copy of the .strawberry reader (documented in its
own header comment as deliberately duplicated from cob_interp.c),
including its own STRAWBERRY_MAGIC constant. cob_interp.c's magic
has mov...

Read more

Cob v0.0.3-bug-fix-1 (EOL)

Choose a tag to compare

@github-actions github-actions released this 13 Sep 21:04

⚠️ ARCHIVED / END OF LIFE (EOL)

NOTICE: This version is preserved strictly for historical reference. It will not receive future patches. Please migrate to the secure v0.0.3 bug fix 2 Release.


ℹ️ Hey There is a new version out v0.0.3 bug fix 2 available, we recommend upgrading to that version.

Cob Language v0.0.3-bug-fix-1

Fixed

popcorn_comp: Windows system() quoting bug in bundled-Zig auto-resolve

find_bundled_zig_cc() returns a pre-quoted compiler string ("path" cc).
cob_spawn_compile() then appends further quoted arguments (-o "out" "in"),
producing a command line with multiple separate quoted tokens that starts
with a quote.

On Windows, system() hands this to cmd.exe /c <string>. cmd.exe strips
only the first and last " of a command line that starts with a quote —
not matching pairs — which corrupts multi-token quoted strings like this
one. This meant auto-resolving a bundled zig/ folder next to the binary
failed with '...' is not recognized as an internal or external command,
even though the equivalent compiler invocation worked fine when passed
explicitly via --cc (which isn't pre-quoted).

Fix: on Windows, if the built command starts with a quote, wrap the whole
command in one more pair of quotes before calling system() — the standard
workaround for this cmd.exe behavior. --cc/$CobCC paths are untouched.

Only popcorn_comp (src/popcorn_comp.c) changed in this release; cob_interp
and farmer are unchanged from v0.0.3.

Not yet verified: on a real Windows machine with a genuine bundled Zig
folder. Verified so far: compiles clean, no regression to the --cc/$CobCC
explicit-compiler path, which was already unaffected by the bug.


Cob Language v0.0.3 — Project Obsidian Falcon

A corn-themed hybrid language with Python-style indentation, an interpreter, a native compiler, and a package manager.

What's new in v0.0.3

popcorn_comp: dropped embedded TCC, now spawns a real compiler

Earlier versions statically linked TCC's own compiler source (libtcc.c) directly into popcorn_comp. That's gone — popcorn_comp now transpiles a .strawberry file to plain C and spawns a real C compiler as a subprocess to produce the native executable.

  • Default backend is Zig's zig cc — a Clang-based drop-in C compiler that bundles libc/CRT files for essentially every target in a single install. That's what makes CobOS/CobArch cross-compiling a plain -target flag instead of needing a separately installed cross-toolchain per platform.
  • Compiler resolution order: --cc <path> → $CobCC → $CobOS/$CobArch (looked up in a table of Zig target triples) → plain zig cc on PATH for native builds.
  • Linux targets default to musl libc, not glibc — produces fully static binaries with no runtime libc dependency.
  • Windows ARM32 is not supported (cut this cycle — it was also the target we were least confident Zig fully supports).
  • --emit-c <path.c> still works, for inspecting the generated C.
CobOS=windows CobArch=amd64 popcorn_comp prog.strawberry -o prog.exe
# -> spawns: zig cc -target x86_64-windows-gnu ...

farmer: real in-process zip extraction via miniz, plus zip-slip protection

farmer harvest used to shell out to unzip (Unix) or Expand-Archive (Windows) to extract downloaded packages. It now extracts in-process using the statically-linked miniz library instead — one less external tool required on the system.

  • Every extracted archive entry's path is checked against zip-slip path traversal before anything is written to disk. A malicious ../../../../etc/whatever entry is rejected outright, with nothing written outside the destination directory.
  • Nested directories inside a package zip are now handled correctly regardless of whether the archive includes explicit directory entries.
  • The package registry now lives in its own dedicated repo, pixel-pulse-labs/cpi — farmer's default base URL was updated to match. Override anytime with $COB_FARMER_BASE_URL.

Documentation site

docs/index.html in this repo is now real language and tool reference documentation — every keyword (pop, set, while, shuck, harvest/trash, the _MakeCache directive) and all three CLI tools, each with usage and flags. The package-registry landing page that used to live here moved to the cpi repo, where it belongs.

Vendored libraries (not yet wired into Cob's language)

Added under vendor/ as embeddable/linkable libraries, per project decision. None of these have Cob-facing keywords yet — that's a separate design step.

  • SQLite 3.53.4 — the single-file amalgamation build (sqlite3.c/sqlite3.h).
  • Tcl 9.0.4 and Tk 9.0 — full source distributions, built via their own configure/make (make tcl, make tk targets added to the Makefile). Tk requires real X11 development headers on the build machine.
  • miniz 3.1.1 — backs farmer's zip extraction (see above).

CI

  • cob_interp, farmer, and popcorn_comp all build across the full 9-target matrix (Windows/Linux/macOS × amd64/386/arm64/arm as applicable — down from 10 after cutting Windows ARM32).
  • A real end-to-end smoke test now runs for popcorn_comp on native Linux amd64: compile a .cob program, run it through popcorn_comp, diff the output against the interpreter.
  • Fixed a bug in the TCC upstream-sync workflow where a conftest.c file ./configure genuinely needs was being silently dropped on every sync, because TCC's own vendored .gitignore has a conftest* pattern that collaterally matched the tracked source file. (Now moot for this repo specifically, since popcorn_comp no longer depends on TCC at all — but the underlying .gitignore-collision lesson is worth knowing if vendoring other C projects.)

Known gaps, stated plainly

  • You need Zig installed for popcorn_comp's default backend to work. This wasn't testable end-to-end in the environment these notes were written in (no network access to ziglang.org) — the command-construction logic was verified against a stub, but real compiles need verification on an actual machine with Zig installed.
  • SQLite/Tcl/Tk are buildable, not usable from Cob yet. No sqlopen, no Tcl shuck-equivalent, no Tk widget keywords. Proving they build and link was this cycle's scope.
  • popcorn_comp isn't smoke-tested on the other 8 targets in CI — only native Linux amd64, since that's the only target whose output can actually execute on the CI runner without emulation.

Upgrading from v0.0.2

If you have scripts calling popcorn_comp and relying on the old CobOS/CobArch → cross-gcc-binary-name behavior, note that resolution now targets Zig triples instead. Install Zig, or pass --cc <path>/$CobCC to keep using a specific compiler directly.


Binaries are provided per-platform in this release. Verify downloads against checksums.txt.

Cob v0.0.4 (EOL)

Choose a tag to compare

@github-actions github-actions released this 06 Sep 01:26

Cob Language v0.0.4

Added

Strings — a real second value type

Cob variables were integers only, full stop, since the language's
first release. This adds a second kind of value: strings. This is a
new capability, not a bug fix, which is why it's versioned 0.0.4
rather than another 0.0.3-bug-fix-N.

What's new, concretely:

  • pop(<expr>) now accepts any expression, not just a string
    literal. pop(x) prints an int variable's decimal value or a
    string variable's contents. This was the single most-requested gap
    in the language up to this point — there was previously no way to
    print a computed value at all.
  • set accepts string literals: set name = "world". A
    variable's "type" is just whatever it was last set to; Cob still
    has no type declarations.
  • String concatenation via +: "hello, " + name. If either
    side of + is a string, the other side is stringified (an int
    becomes its decimal digits) and the two are joined. -, *, /
    still require two numbers, same as before, and now report a clear
    warning (result treated as 0) rather than silently doing something
    undefined if given a string.
  • String comparison in while/conditions: ==, !=, <, >,
    <=, >= all work on two strings (strcmp-based ordering) exactly
    as they already did on two numbers. Comparing a string to a number
    is a warning, evaluating to false, rather than an implicit,
    surprising conversion either direction.
  • Truthiness for a bare condition now applies to strings too: a
    non-empty string is truthy, matching non-zero for numbers.

What did NOT change

harvest()/trash(), shuck, while loop semantics and the
10,000,000-iteration safety cap, and the --no-gc/--no-cache flags
are all unchanged and re-verified below.

popcorn_comp also compiles string-using programs now

Originally shipped as cob_interp-only in this same release, with
popcorn_comp support called out as follow-up work. That follow-up is
done: popcorn_comp now compiles .cob programs that use strings into
real, standalone native binaries too.

popcorn_comp has its own separate copy of the expression AST and its
own C code generator (it doesn't share code with cob_interp), so this
needed a real second implementation, not a shared fix. Every Cob
variable is now emitted as CobValue — a small tagged struct (int or
string) — instead of a plain long, and every operator becomes a
call into a small hand-written C runtime embedded at the top of the
generated file (cob_add, cob_eq, cob_pop, etc.) instead of a raw
C operator. That runtime deliberately mirrors cob_interp's
eval_expr/eval_cond logic, including the exact warning wording, so a
compiled program's behavior matches its interpreted behavior — same
results, same warnings, same fallback-to-0 on a type mismatch. The
one intentional difference: compiled-code warnings are tagged [cob]
rather than [cob_interp], since a compiled binary is its own
standalone program, not the interpreter.

popcorn_comp's own .strawberry reader was updated to the same v3
format (EXPR_STR, STMT_POP holding a general expression) so it
can read caches cob_interp now writes.

A real bug found and fixed before shipping this: the first
version of the string runtime used the platform's strdup(), which
isn't part of strict C99 — under -std=c99 it has no declaration, so
GCC implicitly assumed it returned int, truncating the returned
pointer and segfaulting on the very first string literal. Fixed by
hand-writing a small portable duplicate (cob_strdup_, malloc +
memcpy) instead of depending on a POSIX extension — the same pattern
cob_interp's own cob_strdup already used for exactly this reason.

A real leak found and fixed before shipping this: the first
version of the code generator never freed a variable's final string
value when the compiled program exited — cob_interp does this via
vars_free() at shutdown, but the generated C had no equivalent.
Fixed by emitting a cob_free() call for every declared variable
right before return 0 in generated main().

Also fixed in the same pass: pop(x) — printing a variable —
wasn't being scanned for variable names to declare in the generated
C, since the old codegen assumed pop() could only ever take a fixed
literal with no variables in it. A compiled program using pop(x)
would have referenced an undeclared C variable and failed to compile.

Verified this release, for popcorn_comp specifically:

  • Every test used to verify cob_interp's string support was re-run
    through the full pipeline — cob_interp produces a .strawberry
    cache, popcorn_comp compiles it, the resulting binary is run, and
    its output is diffed against cob_interp's own interpreted output
    for the identical source. All matched exactly: the original
    all-integer countdown example, string literals, concatenation
    (string+string and string+int), pop() of both an int and a string
    variable, string equality and ordering comparisons, both
    type-mismatch warning paths, harvest()/trash() including a
    dynamic (variable) byte count and a negative-size warning, the full
    math package (which exercises shuck, six PASS assertions, and
    the tally display), and the 2,000-iteration string-reassignment
    stress test.
  • Every one of those, compiled and run, was also checked with
    valgrind --leak-check=full — 0 leaks, 0 errors, including after
    fixing the shutdown-cleanup leak above.
  • gcc -std=c99 -Wall -Wextra on popcorn_comp.c itself: zero
    warnings.

Known gap, pre-existing and not addressed in this pass: compiled
trash() has no double-free or invalid-handle detection at all — it
was already a direct, untracked free() call before strings existed,
and still is. cob_interp catches this and warns; a compiled binary
silently allows it, same as before this release. Worth its own
follow-up, unrelated to strings.

Known scope limit: cross-target string support is unverified

Everything verified above was compiled natively (Linux amd64 host,
Linux amd64 target, via plain gcc). The string runtime embedded in
generated C is written in portable C99 with no platform-specific
calls — it should cross-compile via Zig the same as any other
generated Cob program — but that hasn't actually been run and tested
on a genuine Windows or macOS target, or through the Zig backend
specifically, the way the native-gcc path in this release was. Treat
cross-compiled string support as "should work, not yet proven,"
consistent with how earlier releases have flagged untested
cross-platform paths.

The .strawberry cache format changed (v2 → v3)

The on-disk AST format changed shape to represent the new string
expression kind, so the cache's magic bytes were bumped from
COBSTRW2 to COBSTRW3. A cache written by this version is
correctly and safely rejected by anything still expecting v2 (falls
back to reparsing from source, the same as if no cache existed at
all) rather than being misread. This was verified directly: a
hand-corrupted file with the old magic and new-format bytes behind it
was confirmed to be rejected cleanly, with a fallback to reparsing,
not a crash or garbage output.

Verified this release

  • Full rewrite of the value representation (Var/VarTable,
    eval_expr, eval_cond, execute()) from raw long to a tagged
    Value (int or string) — compiles clean with
    gcc -std=c99 -Wall -Wextra, zero warnings.
  • Regression: the original all-integer countdown example and the
    full math package test suite (factorial/gcd/power/abs/min/max/
    tally, 6 assertions) both produce byte-identical output to before
    this change.
  • New features, each actually run against the real interpreter:
    string literals, pop() of an int variable, pop() of a string
    variable, string+string concatenation, string+int concatenation,
    string equality in a self-terminating while, string ordering
    comparison, and the type-mismatch warnings for -/*// on a
    string and for comparing a string to a number.
  • harvest()/trash() regression: allocate, free, double-free
    warning, and the --no-gc gate all still behave identically now
    that handles flow through Value instead of a bare long.
  • Memory correctness: every test above, plus a 2,000-iteration
    loop reassigning a string each pass, run clean under
    valgrind --leak-check=full — 0 leaks, 0 errors, allocations and
    frees exactly balanced in every run.
  • Cache round-trip: a string-using program produces identical
    output whether freshly parsed or loaded from its own .strawberry
    v3 cache.

Not verified

  • popcorn_comp's string support on a real Windows/macOS target, or
    through a cross-compile (Zig) build rather than native gcc — see
    above.
  • No testing on Windows or macOS for this change; verified on Linux
    only, same as the source-level verification pattern in earlier
    releases.

Cob Language v0.0.3-bug-fix-2

Changed

Project moved from pixel-pulse-labs to Cob-Software-Foundation on GitHub

All three repositories (Cob, cpi, and the new Cob-Docs) now live
under the Cob-Software-Foundation GitHub org instead of
pixel-pulse-labs. This release updates every reference that was
hardcoded to the old org:

  • include/common.h: COB_REPO_URL and the file header comment
    now point to https://github.com/Cob-Software-Foundation/Cob.
  • docs/index.html and Release.txt: GitHub/license links
    updated to the new org. (Historical mentions of the old
    pixel-pulse-labs.github.io/cpi URL inside the bug-fix-2 changelog
    entry above were left as-is deliberately — that's a factual record
    of what the URL used to be, not a live link.)

COB_FARMER_DEFAULT_BASE_URL itself (`...

Read more

Cob v0.0.3-bug-fix-2 (EOL)

Choose a tag to compare

@github-actions github-actions released this 02 Sep 23:27

Cob Language v0.0.3-bug-fix-2

Changed

Project moved from pixel-pulse-labs to Cob-Software-Foundation on GitHub

All three repositories (Cob, cpi, and the new Cob-Docs) now live
under the Cob-Software-Foundation GitHub org instead of
pixel-pulse-labs. This release updates every reference that was
hardcoded to the old org:

  • include/common.h: COB_REPO_URL and the file header comment
    now point to https://github.com/Cob-Software-Foundation/Cob.
  • docs/index.html and Release.txt: GitHub/license links
    updated to the new org. (Historical mentions of the old
    pixel-pulse-labs.github.io/cpi URL inside the bug-fix-2 changelog
    entry above were left as-is deliberately — that's a factual record
    of what the URL used to be, not a live link.)

COB_FARMER_DEFAULT_BASE_URL itself (cpi.cob.pixel-pulse.work.gd)
was already unaffected by the org rename, since it's a custom domain,
not a github.io URL — no change needed there, still correct from
bug-fix-2.

Also fixed while in there: cpi registry's zip_url fields were still on the old github.io URL

Separately from the org rename, cpi's own package metadata
(docs/api/v1/packages/*.json) had zip_url values pointing at
https://pixel-pulse-labs.github.io/cpi/packages/... — the raw
GitHub Pages URL from before the custom domain was set up in
bug-fix-2. farmer's own default base URL got updated to the custom
domain then, but the registry's self-referencing zip URLs were missed.
Updated both greeter.json and math.json to
https://cpi.cob.pixel-pulse.work.gd/packages/..., matching the
domain farmer actually resolves against by default.

Verified this release:

  • Rebuilt farmer from the patched source — compiles clean.
  • Re-ran the full local harvest test (local HTTP server standing in
    for the registry, real farmer binary, real miniz extraction): metadata
    fetch, sha256 verification, and extraction into cob_modules/math/
    all passed against the corrected zip_url.
  • Grepped the full source tree, both doc sites, and both published
    Cob packages (math, seed) for any remaining pixel-pulse-labs
    reference — none left outside the deliberate historical changelog
    mentions noted above.

Not verified: an actual farmer harvest against the live
cpi.cob.pixel-pulse.work.gd domain with the corrected zip_url from
a real machine — this environment's network doesn't reach that domain.
The local-server test above exercises the identical code path, but a
real end-to-end run on the live domain is still worth doing before
calling this fully verified.


Cob Language v0.0.3-bug-fix-2

Changed

farmer: default package registry URL updated to the custom domain

COB_FARMER_DEFAULT_BASE_URL (include/common.h) now points at
https://cpi.cob.pixel-pulse.work.gd instead of the previous
https://pixel-pulse-labs.github.io/cpi.

The cpi registry itself hasn't moved — it's still served from the
same GitHub Pages site (Cob-Software-Foundation/cpi, docs/ on main).
Only the domain in front of it changed, via a CNAME record on that
repo. This release just updates farmer's compiled-in default so a
plain farmer harvest <package> resolves against the new domain
without needing $COB_FARMER_BASE_URL set manually.

If you were already overriding the URL with
$COB_FARMER_BASE_URL=https://pixel-pulse-labs.github.io/cpi, that
still works — GitHub Pages doesn't stop serving the old
github.io URL just because a custom domain was added, it's just no
longer the default farmer uses.

No other change. cob_interp and popcorn_comp are unchanged from
v0.0.3-bug-fix-1.

Verified this release: grepped the full source tree for any other
reference to the old github.io URL — none found; common.h was the
only place it was hardcoded.

Not verified: an actual farmer harvest run against the live
cpi.cob.pixel-pulse.work.gd domain from a real machine outside this
environment (this environment's network egress doesn't reach that
domain to test directly). The URL was confirmed correct by inspection
of the compiled-in default, not by an end-to-end network fetch.


Cob Language v0.0.3-bug-fix-1

Fixed

popcorn_comp: Windows system() quoting bug in bundled-Zig auto-resolve

find_bundled_zig_cc() returns a pre-quoted compiler string ("path" cc).
cob_spawn_compile() then appends further quoted arguments (-o "out" "in"),
producing a command line with multiple separate quoted tokens that starts
with a quote.

On Windows, system() hands this to cmd.exe /c <string>. cmd.exe strips
only the first and last " of a command line that starts with a quote —
not matching pairs — which corrupts multi-token quoted strings like this
one. This meant auto-resolving a bundled zig/ folder next to the binary
failed with '...' is not recognized as an internal or external command,
even though the equivalent compiler invocation worked fine when passed
explicitly via --cc (which isn't pre-quoted).

Fix: on Windows, if the built command starts with a quote, wrap the whole
command in one more pair of quotes before calling system() — the standard
workaround for this cmd.exe behavior. --cc/$CobCC paths are untouched.

Only popcorn_comp (src/popcorn_comp.c) changed in this release; cob_interp
and farmer are unchanged from v0.0.3.

Not yet verified: on a real Windows machine with a genuine bundled Zig
folder. Verified so far: compiles clean, no regression to the --cc/$CobCC
explicit-compiler path, which was already unaffected by the bug.


Cob Language v0.0.3 — Project Obsidian Falcon

A corn-themed hybrid language with Python-style indentation, an interpreter, a native compiler, and a package manager.

What's new in v0.0.3

popcorn_comp: dropped embedded TCC, now spawns a real compiler

Earlier versions statically linked TCC's own compiler source (libtcc.c) directly into popcorn_comp. That's gone — popcorn_comp now transpiles a .strawberry file to plain C and spawns a real C compiler as a subprocess to produce the native executable.

  • Default backend is Zig's zig cc — a Clang-based drop-in C compiler that bundles libc/CRT files for essentially every target in a single install. That's what makes CobOS/CobArch cross-compiling a plain -target flag instead of needing a separately installed cross-toolchain per platform.
  • Compiler resolution order: --cc <path> → $CobCC → $CobOS/$CobArch (looked up in a table of Zig target triples) → plain zig cc on PATH for native builds.
  • Linux targets default to musl libc, not glibc — produces fully static binaries with no runtime libc dependency.
  • Windows ARM32 is not supported (cut this cycle — it was also the target we were least confident Zig fully supports).
  • --emit-c <path.c> still works, for inspecting the generated C.
CobOS=windows CobArch=amd64 popcorn_comp prog.strawberry -o prog.exe
# -> spawns: zig cc -target x86_64-windows-gnu ...

farmer: real in-process zip extraction via miniz, plus zip-slip protection

farmer harvest used to shell out to unzip (Unix) or Expand-Archive (Windows) to extract downloaded packages. It now extracts in-process using the statically-linked miniz library instead — one less external tool required on the system.

  • Every extracted archive entry's path is checked against zip-slip path traversal before anything is written to disk. A malicious ../../../../etc/whatever entry is rejected outright, with nothing written outside the destination directory.
  • Nested directories inside a package zip are now handled correctly regardless of whether the archive includes explicit directory entries.
  • The package registry now lives in its own dedicated repo, Cob-Software-Foundation/cpi — farmer's default base URL was updated to match. Override anytime with $COB_FARMER_BASE_URL.

Documentation site

docs/index.html in this repo is now real language and tool reference documentation — every keyword (pop, set, while, shuck, harvest/trash, the _MakeCache directive) and all three CLI tools, each with usage and flags. The package-registry landing page that used to live here moved to the cpi repo, where it belongs.

Vendored libraries (not yet wired into Cob's language)

Added under vendor/ as embeddable/linkable libraries, per project decision. None of these have Cob-facing keywords yet — that's a separate design step.

  • SQLite 3.53.4 — the single-file amalgamation build (sqlite3.c/sqlite3.h).
  • Tcl 9.0.4 and Tk 9.0 — full source distributions, built via their own configure/make (make tcl, make tk targets added to the Makefile). Tk requires real X11 development headers on the build machine.
  • miniz 3.1.1 — backs farmer's zip extraction (see above).

CI

  • cob_interp, farmer, and popcorn_comp all build across the full 9-target matrix (Windows/Linux/macOS × amd64/386/arm64/arm as applicable — down from 10 after cutting Windows ARM32).
  • A real end-to-end smoke test now runs for popcorn_comp on native Linux amd64: compile a .cob program, run it through popcorn_comp, diff the output against the interpreter.
  • Fixed a bug in the TCC upstream-sync workflow where a conftest.c file ./configure genuinely needs was being silently dropped on every sync, because TCC's own vendored .gitignore has a conftest* pattern that collaterally matched the tracked source file. (Now moot for this repo specifically, since popcorn_comp no longer depends on TCC at all — but the underlying .gitignore-collision lesson is worth knowing if vendoring other...
Read more

Cob v0.0.3 (EOL)

Choose a tag to compare

@github-actions github-actions released this 31 Aug 01:01

⚠️ ARCHIVED / END OF LIFE (EOL)

NOTICE: This version is preserved strictly for historical reference. It will not receive future patches. Please migrate to the secure v0.0.3 bug fix 1 Release.


ℹ️ Hey There is a new version out v0.0.3 bug fix 1 available, we recommend upgrading to that version.

Cob Language v0.0.3 — Project Obsidian Falcon

A corn-themed hybrid language with Python-style indentation, an interpreter, a native compiler, and a package manager.

What's new in v0.0.3

popcorn_comp: dropped embedded TCC, now spawns a real compiler

Earlier versions statically linked TCC's own compiler source (libtcc.c) directly into popcorn_comp. That's gone — popcorn_comp now transpiles a .strawberry file to plain C and spawns a real C compiler as a subprocess to produce the native executable.

  • Default backend is Zig's zig cc — a Clang-based drop-in C compiler that bundles libc/CRT files for essentially every target in a single install. That's what makes CobOS/CobArch cross-compiling a plain -target flag instead of needing a separately installed cross-toolchain per platform.
  • Compiler resolution order: --cc <path> → $CobCC → $CobOS/$CobArch (looked up in a table of Zig target triples) → plain zig cc on PATH for native builds.
  • Linux targets default to musl libc, not glibc — produces fully static binaries with no runtime libc dependency.
  • Windows ARM32 is not supported (cut this cycle — it was also the target we were least confident Zig fully supports).
  • --emit-c <path.c> still works, for inspecting the generated C.
CobOS=windows CobArch=amd64 popcorn_comp prog.strawberry -o prog.exe
# -> spawns: zig cc -target x86_64-windows-gnu ...

farmer: real in-process zip extraction via miniz, plus zip-slip protection

farmer harvest used to shell out to unzip (Unix) or Expand-Archive (Windows) to extract downloaded packages. It now extracts in-process using the statically-linked miniz library instead — one less external tool required on the system.

  • Every extracted archive entry's path is checked against zip-slip path traversal before anything is written to disk. A malicious ../../../../etc/whatever entry is rejected outright, with nothing written outside the destination directory.
  • Nested directories inside a package zip are now handled correctly regardless of whether the archive includes explicit directory entries.
  • The package registry now lives in its own dedicated repo, pixel-pulse-labs/cpi — farmer's default base URL was updated to match. Override anytime with $COB_FARMER_BASE_URL.

Documentation site

docs/index.html in this repo is now real language and tool reference documentation — every keyword (pop, set, while, shuck, harvest/trash, the _MakeCache directive) and all three CLI tools, each with usage and flags. The package-registry landing page that used to live here moved to the cpi repo, where it belongs.

Vendored libraries (not yet wired into Cob's language)

Added under vendor/ as embeddable/linkable libraries, per project decision. None of these have Cob-facing keywords yet — that's a separate design step.

  • SQLite 3.53.4 — the single-file amalgamation build (sqlite3.c/sqlite3.h).
  • Tcl 9.0.4 and Tk 9.0 — full source distributions, built via their own configure/make (make tcl, make tk targets added to the Makefile). Tk requires real X11 development headers on the build machine.
  • miniz 3.1.1 — backs farmer's zip extraction (see above).

CI

  • cob_interp, farmer, and popcorn_comp all build across the full 9-target matrix (Windows/Linux/macOS × amd64/386/arm64/arm as applicable — down from 10 after cutting Windows ARM32).
  • A real end-to-end smoke test now runs for popcorn_comp on native Linux amd64: compile a .cob program, run it through popcorn_comp, diff the output against the interpreter.
  • Fixed a bug in the TCC upstream-sync workflow where a conftest.c file ./configure genuinely needs was being silently dropped on every sync, because TCC's own vendored .gitignore has a conftest* pattern that collaterally matched the tracked source file. (Now moot for this repo specifically, since popcorn_comp no longer depends on TCC at all — but the underlying .gitignore-collision lesson is worth knowing if vendoring other C projects.)

Known gaps, stated plainly

  • You need Zig installed for popcorn_comp's default backend to work. This wasn't testable end-to-end in the environment these notes were written in (no network access to ziglang.org) — the command-construction logic was verified against a stub, but real compiles need verification on an actual machine with Zig installed.
  • SQLite/Tcl/Tk are buildable, not usable from Cob yet. No sqlopen, no Tcl shuck-equivalent, no Tk widget keywords. Proving they build and link was this cycle's scope.
  • popcorn_comp isn't smoke-tested on the other 8 targets in CI — only native Linux amd64, since that's the only target whose output can actually execute on the CI runner without emulation.

Upgrading from v0.0.2

If you have scripts calling popcorn_comp and relying on the old CobOS/CobArch → cross-gcc-binary-name behavior, note that resolution now targets Zig triples instead. Install Zig, or pass --cc <path>/$CobCC to keep using a specific compiler directly.


Binaries are provided per-platform in this release. Verify downloads against checksums.txt.

Cob v0.0.2 (EOL)

Choose a tag to compare

@github-actions github-actions released this 25 Aug 21:36

⚠️ ARCHIVED / END OF LIFE (EOL)

NOTICE: This version is preserved strictly for historical reference. It will not receive future patches. Please migrate to the secure v0.0.3 Release.


ℹ️ Hey There is a new version out v0.0.3 available, we recommend upgrading to that version.

Cob Language v0.0.2 -- Project Obsidian Falcon

A corn-themed hybrid language with Python-style indentation, an
interpreter, a native compiler, and a package manager.

WHAT'S NEW IN v0.0.2

  • while : now really loops, with real nested block bodies
    and a safety cap against runaway/infinite loops.
  • set = supports integer variables and arithmetic
    (+ - * /, with standard precedence) and comparisons
    (== != < > <= >=).
  • shuck <library_name> loads <library_name>.cob (checking the current
    directory, then cob_modules/<library_name>/<library_name>.cob -- the
    layout farmer harvest installs into) and splices it into your
    program. Circular and too-deep shucks are rejected with a clear
    error instead of hanging or crashing.
  • harvest() / trash() are real now: harvest allocates
    raw memory and returns an opaque handle, trash frees it. Both are
    locked behind the --no-gc flag -- a program using them without it is
    refused outright, not silently ignored.
  • A .cob file whose literal first line is _MakeCache = False
    (whitespace/case-insensitive) disables the .strawberry fast-boot
    cache entirely for that file.
  • popcorn_comp is a real native compiler now. It reads a .strawberry
    file, transpiles it to plain C, and compiles that to a standalone
    native executable using TCC's own compiler source statically linked
    directly into popcorn_comp -- no external compiler, no dynamic
    linking to a system TCC install. CobOS/CobArch environment variables
    are validated against what this specific popcorn_comp binary was
    built for; cross-targeting a different OS/arch requires a
    popcorn_comp built for that target (see .github/workflows/build.yml).
    Currently built for native Linux amd64 in CI; other targets need a
    matching TCC runtime (libtcc1.a) built for them first.
  • farmer is the package manager. farmer harvest <package> fetches
    metadata from a static JSON API (hosted free on GitHub Pages),
    verifies the package name matches what was requested, downloads the
    package zip, verifies its sha256 if one was provided, and unzips it
    into cob_modules// -- ready for shuck <package>. All
    values that reach a shell command line are validated and quoted
    before use.
  • A real, working example package ("greeter") and static registry are
    published under docs/ and served via GitHub Pages.

SCOPE NOTES

  • popcorn_comp's cross-compilation story is honest, not aspirational:
    a single statically-linked libtcc build only targets the one
    platform it was compiled for. True cross-target support means
    building separate popcorn_comp binaries per target, each with a
    matching TCC runtime -- that's still a work in progress beyond
    native Linux amd64.
  • cob_interp and farmer build for all 10 target platforms
    (Windows/Linux/macOS x amd64/386/arm64/arm as applicable).

Binaries are provided per-platform in this release. Verify downloads
against checksums.txt. A popcorn_comp release also ships a runtime/
folder (libtcc1.a + TCC's bundled headers) alongside the binary --
keep them together, or point popcorn_comp at another copy via the
POPCORN_TCC_RUNTIME_DIR environment variable.

Cob v0.0.1 (EOL)

Choose a tag to compare

@github-actions github-actions released this 24 Aug 00:55

⚠️ ARCHIVED / END OF LIFE (EOL)

NOTICE: This version is preserved strictly for historical reference. It will not receive future patches. Please migrate to the secure v0.0.2 Release.


ℹ️ Hey There is a new version out v0.0.2 available, we recommend upgrading to that version.

Cob Language -- Project Obsidian Falcon

Corn-themed.

This release ships cob_interp, the v0.0.1 interpreter. Its scope is
intentionally narrow: pop("text") is the one fully working statement.
while, set, shuck, harvest, and trash are recognized by the
parser but not yet executed.

Binaries are provided for Windows, Linux, and macOS across
amd64/386/arm64/arm as applicable. Verify downloads against
checksums.txt in this release.