Skip to content

Releases: funlang/fun

v9.4.5 released

Choose a tag to compare

@funlang funlang released this 20 Oct 12:56
Fun 9.4.5

Manifest-driven packages and project-aware runs.

Highlights since v9.4.4:

- `fun package init/add/remove/tidy` manage a `package.fun` manifest, install
  exact git revisions into a shared `~/.fun` cache, verify git tree hashes,
  and record a generated `resolved` block. Path dependencies are used in
  place; only git dependencies need `git`.

- `fun run [args...]` runs the manifest `bin` from the project root with its
  dependencies available. In a package directory, a plain `fun <script>` takes
  the same project-aware path, and `FUN_PACKAGE_READY=1` opts out. Runs stay
  read-only and refuse a missing or stale dependency.

- `fun pack` now defaults to the manifest `bin`, resolves paths against the
  project root, and embeds resolved dependencies, so a bundle runs without
  `~/.fun`.

- Bundled console apps keep their output when stdout is redirected, unless
  `-gui` is requested.

- Packages are documented in both READMEs with a runnable
  `fun/demos/package-demo`, and covered by an end-to-end regression test.

Full list: CHANGELOG.md / CHANGELOG.zh.md.

v9.4.4 released

Choose a tag to compare

@funlang funlang released this 19 Oct 15:03
Fun 9.4.4

Single-file bundling with `fun pack`, plus Netif() and a macOS DNS fix.

Highlights since v9.4.3:

- `fun pack <entry.fun>` bundles the interpreter, project files and declared
  resources into one executable. It extracts to a temp directory at startup
  and shifts script arguments so 2.arg() is the first real argument. Builds
  can omit it (-dFunPack) or emit a consumer-only runtime (FUNPACK=user).
- Netif() enumerates IPv4 network interfaces on Linux and macOS.
- macOS DNS lookup no longer loses resolver pointers above 4 GB.
- Opt-in startup profiling via -dFunStartupTiming.
- The interpreter no longer links Classes (~120 KiB smaller on Linux x86_64);
  generated assembler tables use .fd2 so hosts stop counting them as roff.

Full list: CHANGELOG.md / CHANGELOG.zh.md.

v9.4.3 released

Choose a tag to compare

@funlang funlang released this 18 Oct 12:32
Fun 9.4.3

Variable declarations with initializers now reuse parse-time assignment specialization.

Highlights since v9.4.2:

- Variable declarations with an initializer now use the same parse-time
  assignment specialization as plain assignments. A var inside a loop resolves
  its slot once and reuses it instead of repeating the generic assign and
  scope-push chain. On the bundled Linux x86_64 build var d = i drops from
  ~57 to ~38 ns/iter, matching a plain assignment in the same scope.

Full list: CHANGELOG.md / CHANGELOG.zh.md.

v9.4.2 released

Choose a tag to compare

@funlang funlang released this 18 Oct 09:07
Fun 9.4.2

Regex matching and variable assignment stop repeating work on every run.

Highlights since v9.4.1:

- Regex patterns are compiled once. Compiled PCRE code is shared through a small
  LRU cache keyed by pattern text and options, with reference counting so a lazy
  match object always keeps its code alive; each regex literal holds its own
  reference, so the hot path skips the cache lookup. A pattern used a second
  time is upgraded to PCRE's JIT engine, with the upgrade deferred so a one-shot
  toRegex() pays no JIT cost.

- Global match/replace write into one growable buffer instead of splicing the
  subject once per match, turning the former O(n^2) replacement loop into a
  single pass. On the bundled Linux x86_64 build, 200 global replacements over
  a ~100 KB subject drop from ~7.3 s to ~0.24 s, repeated literal matching
  improves by ~1.4-1.5x, and a global match by ~3x. Literal replacements
  without $ or \ references skip the per-match replacement scan, making them
  another 25-40% faster.

- Global replacement computes $_ (and the other subject references) from the
  original subject. The old in-place loop rewrote the subject between matches,
  so 'abcabc'.replace(/b/g, '[$_]') produced a[abcabc]ca[a[abcabc]cabc]c; it
  now yields a[abcabc]ca[abcabc]c.

- Plain variable assignments are specialized at parse time. The first run
  resolves the target slot once; later runs read simple CId sources and write
  the scalar slot directly instead of repeating the virtual assign and scope
  push. On the bundled Linux x86_64 build, x = i drops from ~56 to ~38 ns/iter
  and a global gx = i from ~52 to ~33 ns/iter. Fields, indices,
  self-assignments and scope entries that still need a push keep the generic
  path.

Full list: CHANGELOG.md / CHANGELOG.zh.md.

v9.4.1 released

Choose a tag to compare

@funlang funlang released this 17 Oct 13:54
Fun 9.4.1

Bug-fix release for 9.4.0.

Highlights since v9.4.0:

- Integer comparison no longer overflows int32. varComp and the CalcOpt fast
  paths for <, >, <=, >=, <> and = computed a - b before testing the sign; that
  difference overflowed int32 and reversed the result, so for example
  2147483647 > -1 returned false. They now compare the operands directly.

Full list: CHANGELOG.md / CHANGELOG.zh.md.

v9.4.0 released

Choose a tag to compare

@funlang funlang released this 17 Oct 12:40
Fun 9.4.0

Performance and hot-path release.

Highlights since v9.3.4:

- Scalar values stay out of the Variant RTL: comparison and logical
  operators write varBoolean directly, scalar assignment fast-paths
  Boolean/Double as well as Integer, and CCtwo no longer builds a temporary
  CValue while keeping recursive re-entry safe.
- Integer div/mod gain guarded fast paths. Zero divisors and
  Low(Integer) div/mod -1 still fall through to the Variant RTL, preserving
  the existing exception behavior. On the shipped benchmark, 1>2 drops from
  about 193 to 130 ns/iteration, if 1>2 from about 166 to 130 ns, not 1>2
  from about 343 to 196 ns, and 7 div 3 roughly halves.
- Arithmetic fast paths are enabled on Linux x86_64; x/0 still raises on
  AArch64, and the CalcOpt fallback checks the divisor.
- More hot-path trimming for compare, assignment, and string concat.
- AArch64 assembler coverage: cmn, sp-relative access, imm12 boundary, and
  the bl label call.
- The HTTP server/client stack and the variadic getapi mark are included;
  funcmd reports the missing script by name.
- linux-arm64 snapshot and lib-asm-a64 test enabled; CI keeps the full diff
  in failure annotations.
- New calc-fastpath regression covers Boolean results, scalar copies, and
  integer div/mod edge cases.

Verified by the five-platform regression workflow:
https://github.com/funlang/fun/actions/runs/39031232338

Full list: CHANGELOG.md / CHANGELOG.zh.md.

v9.3.4 released

Choose a tag to compare

@funlang funlang released this 16 Oct 10:33
The HTTP stack lands in the standard library.

Highlights since v9.3.3:

- lib/http-server: a single-threaded, platform-neutral HTTP server. Route
  patterns (literal / :name / * tail, 405 with Allow, 404 otherwise), route
  groups, global / group / per-route middleware, params and query strings,
  static files, json / text / html responses and an access logger; driven by
  its own poll loop (run) or one step at a time (runOnce). HTTP framing and
  keep-alive live in lib-winsock-base.fun; the Linux/macOS poll backend is
  wired, the Windows message-pump driver is still a follow-up.
- lib/http-client: a one-call blocking client, HttpClient(args) ->
  [rc, code, message, headers, body], over the host's lib-ajax backend.
- lib-ajax.fun (Windows) gains the same Http(args) helper as lib-ajax-unx, so
  HttpClient is one call on every platform: it forces the synchronous
  transfer, exposes the final response block as Ajax.headers (lowercased
  keys) and returns the same five-field result set.
- getapi accepts a variadic: <n> mark (libffi ffi_prep_cif_var), required on
  Darwin arm64; curl_easy_setopt uses it, so the lib-ajax test runs on macOS.
- funcmd names the file it cannot find (not found: <file>) instead of failing
  silently; lib-winsock renames HttpServer -> HttpServerBase (kept as
  Server.HTTP / Server.HTP), fixing the duplicated HTP assignment.

See CHANGELOG.md / CHANGELOG.zh.md for the full list (the portability entries
before the HTTP work are still under Unreleased).

v9.3.3 released

Choose a tag to compare

@funlang funlang released this 15 Oct 16:40
Windows joins the gate, and the last portability gaps close.

Highlights since v9.3.2:

- win64 has regex. PCRE 8.45 is built there with the runner's MinGW gcc into
  pcre3.dll beside funcmd.exe and imported by name (-dPCRE_WinDLL), because
  neither FPC linker can pull in the bcc32 or the MinGW PCRE objects. Two
  engine fixes came with it: the __llmul stub is 32-bit only (win64 has no
  System.__llmul), and PCRE memory returns through pcre_free_substring, since
  the DLL allocates from its own CRT (FreeMem corrupted the heap after a
  match). The 8 regex tests and the portability probe run on Windows now
  instead of skipping.

- win64 has getapi. FPC's bundled ffi unit already targets WIN64, so -dWinFFI
  (mapped onto the engine's existing UnixFFI symbol) selects the libffi-backed
  lffi unit and CI copies ffi.dll from MSYS2 next to funcmd.exe; a bare
  library name now falls back to name + '.dll'.

- The portable FFI suite runs on win64 and earned its keep: four of the five
  cases use the shared snapshots, and the fifth found a real bug - kernel32
  exports GetCommandLineA/W, so lffi.pas now retries name + 'A' for unsuffixed
  Windows API names, as io.GetProc already did. windows-x64 is 55/55, 37
  skipped.

- Windows-only engine divergences fixed ({$IfDef FPC} branches, Delphi sources
  untouched by them): the ISO time literal parses directly instead of through
  FPC's locale-dependent VarToDateTime; DefaultFormatSettings is pinned to the
  Unix formats so date and number output is host-independent; stdout goes
  through a new raw-byte WriteOut instead of the RTL text file, which
  re-encoded every non-ASCII byte to the console codepage; and a named script
  forces console mode, so a redirected run prints again (AttachConsole is
  false without a parent console). Also: 0x literals stay 32-bit unsigned on
  Win64, and the FPC-only divergences that broke the Windows build are gone.

- macOS: the lib-proc backend (libproc + mach VM) lands with its test enabled
  (#14); lib-asm-a64 gains live JIT on arm64 (#13) and all b.cond condition
  codes (#4); the lib-crypt-unx hashes go through CommonCrypto (#6).

- CI: every platform gates the build (windows-arm64 stays disabled, FPC 3.2.2
  has no such target), the FPC toolchain is cached on all of them, and the
  Windows runner reports regex/getapi availability as annotations.

- pcrd's dynamic branch (-dPCRE_LINKDLL) no longer breaks the Delphi build:
  dynlibs is FPC-only and the non-FPC side keeps the same behaviour through
  the Win32 loading calls, so dcc32 builds funcmd.dpr again.

Verified: linux x86_64 regression 92/92. The Delphi (dcc32) build of
funcmd.dpr compiles again; -dPCRE_WinDLL/-dPCRE_LINKDLL paths are unchanged.

v9.3.2 released

Choose a tag to compare

@funlang funlang released this 13 Oct 12:57
Fun 9.3.2

macOS reaches the standard library, and Linux arm64 gets a build.

Highlights since v9.3.1:

- lib: macOS port. getapi works through the libffi backend (-dLinuxFFI
  generalises to UnixFFI, -dDarwinFFI selects Darwin), and the library layer
  that differed only by library name moves to lib-*-unx.fun (os, cmdline,
  unicode, ado, ado-schema, xml, crypt, ajax, winsock, jsonrpc, orm-rpc), with
  lib-*-lnx.fun kept as thin wrappers. lib-host.fun gains IsMac()/IsUnix();
  Darwin gets .dylib names, proc_pidpath, the Darwin sockaddr_in layout,
  __error and Homebrew/MacPorts libcrypto probing.

- build: fun/funcmd-linux-aarch64 is cross-compiled on x86_64 from a
  bootstrapped aarch64 RTL through Zig clang/lld shims, with no aarch64
  binutils or glibc. The artifact is static, stripped and reproducible; it is
  the core interpreter for now (no PCRE or getapi).

- darwin/ld forwards -dead_strip and the strip request to lld, shrinking the
  Mach-O binaries from 2.6/2.7 MB to 0.86/0.94 MB with LC_MAIN, the dylib
  loads and the arm64 ad-hoc signature intact.

- funcmd usability: no script argument prints the usage and exits 0 instead of
  trying to run its own executable, a named-but-missing script stays an error,
  and the usage line says fun rather than fun.exe on non-Windows hosts.

- test: fractal-asm-x64 exercises the x86_64 SysV lib-asm path against the
  fractal benchmark output.

v9.3.1 released

Choose a tag to compare

@funlang funlang released this 13 Oct 06:54
Fun 9.3.1

The interpreter cross-compiles for macOS on a Linux host.

Highlights since v9.3.0:

- bootstrap-darwin-cross.sh builds a full FPC 3.2.2 darwin cross toolchain
  (ppcrossx64/ppcrossa64 plus the RTL, the rtl-objpas/hash units and PCRE) and
  fetches Zig; make-darwin.sh compiles funcmd.dpr into fun/funcmd-darwin-<cpu>.

- Mach-O assembly and linking go through the darwin/clang and darwin/ld shims
  over Zig's bundled clang/lld, so no macOS SDK is required.

- The engine's {$IfDef Linux} guards that really meant "not Windows" now use
  FPC's built-in UNIX symbol: core/{base,fun,io}, parse/parse, utils/utils, the
  lib helpers, regex/pcre/* and funcmd.dpr. host.arg() reports os macos, Darwin
  gets clock_gettime/gettimeofday and cdecl PCRE externals.

- Linux is unchanged: the regression suite stays at 91/91. The Fun-level -lnx
  libraries and the getapi FFI backend are not ported yet.