Repository navigation
sysl 0.0.161 — a --lib root stands in for its package, and large values stay where they are
A --lib root stands in for its package, and large values stay where they are
Two packaging changes, two code-generation changes, and three fixes. A --lib root that is a dependency's package now overrides it, so a coordinate that cannot be fetched no longer stops the build. A dependency's own imports are now answered by its own manifest and never by the project's modules. Separately, a large self or by-value parameter is now read where it lies, and a large result is built in the caller's storage. A board program's deepest stack along boot → synth falls from 30,104 B to 13,440 B.
Behaviour changes
Four of the changes alter what an existing build does. Two of them can turn a build that worked into a refused or different one, so they come first.
- A
--libsource root that is a dependency's package now overrides that dependency (a76a3e9). Before, it was refused as a collision. A root stands in for a coordinate when itspackage.nameis the coordinate's repository name: the last path segment, with any/vNsuffix set aside. The coordinate is then dropped before selection wherever the graph names it, in the project's manifest or in any dependency's. Nothing is fetched for it and nothing is written tosysl.sumfor it. A coordinate that cannot be fetched (unpublished, a bad tag, no network) therefore no longer stops a build that has a--libcopy of it. This works like Cargo's[patch]and Go'sreplace, written as one flag. A root that merely holds a module a coordinate also offers, without being that package, is still refused, and the refusal now says what would have made it an override.reference/packages.md § A source root stands in for the package it is.- Behaviour change: a build that used to be refused for a
--libroot colliding with a coordinate now builds against the root.
- Behaviour change: a build that used to be refused for a
- A dependency's own import no longer reaches the project's modules (8b4818c). When a dependency wrote
import geom, the import used to be answered by a--libroot'sgeom, or by the project's owngeom/, before thegeomits own manifest declared. A program could then build and run the wrong package's code with no warning: the regression case printed 42 where the right answer is 28. The dependency now gets the module its manifest bound. A dependency whose manifest reaches nogeomat all is refused the name instead of borrowing the project's. The project's own imports are unchanged.reference/packages.md § Imports are transitive.- Behaviour change: a package that relied on reaching one of its consumer's modules now gets
undefined nameand has to declare what it imports.
- Behaviour change: a package that relied on reaching one of its consumer's modules now gets
- A large by-value
selfor parameter is read in place (a0221b5, a9dee9e). It is no longer copied at entry when the function only reads it: no assignment to it or to a part of it, no&of it, no*selfcall on it, no tail self-call, and nothing outside the program can call the function.reference/declarations.md's "the method gets a copy" still holds. The caller hands over storage that nothing can change while the call runs: a temporary, a local nobody else can name, or a snapshot it stages. A write through an alias in the middle of the call therefore still does not show throughself.- A caller stages no snapshot at all for a callee that can write nothing. That test (
BorrowedParams) now reaches past a leaf: a body may call functions that pass it, recursion included, and may write its ownvars. - A staged snapshot is released at its address (
arc.dispose_at.T(ptr)). It used to be loaded whole and passed toarc.dispose.Tby value, which put a second copy of the struct on the stack. - A view or a slice written through counts as a write to what it views (a9dee9e).
var v = self.table[..]; v[0] = 9keeps the parameter's own copy. A writable view of a local handed to a call counts as letting that local out, so the local is snapshotted. A write through a slice local (var o = out; o[0] = 7) is no longer counted as the function's own storage. Before this fix, each case changed the caller's value (9 9,7 7); they now print9 0and0 7. - On
thumb-freestanding-softfp, musicbox'sSynth.renderframe goes from 11,128 B to 104 B. A*selfmethod calling aselfmethod over a 4 KB struct goes from 8,224 B to 0.
- A caller stages no snapshot at all for a callee that can write nothing. That test (
- A large result is built where it is going (4fc425a, e52c90e). A local returned on every path is built in the caller's storage. In
var s = Synth(…); s.rewind(); Ok(s),slives in the payload of the caller'sResultfrom its declaration, so theOkwrites the tag and nothing else. This coverssreturned alone or as one argument of a variant or struct (Ok(s),Some(s),Held(s, n)), with anyreturnbeforesexists returning anything.- A copy is kept wherever the difference could be seen: another value returned after
sexists; another argument of the result mentionings;s's address going anywhere but straight into a call; adefer; or, where its address does go into a call, a postcondition or a release that could run a destructor between thereturnand the end of the function. - A
?aftersexists keeps the copy (e52c90e). Its failure leaves through the same storage, and would write overswith its counts still owed and its destructors never run. - A
matchorifproducing a large value builds each branch's value in place, with no merge slot. An armV(x) -> xover a local copies the payload straight from the matched value, soResult.unwrapandOption.unwrapno longer stage the whole value twice. - A large call result read through its address, as a receiver is in
synth(…).unwrap(), is written into the slot the read uses and released there. It used to be loaded whole, stored again, and released by value. - On
thumb-freestanding-softfp, musicbox'ssynthframe goes from 7,544 B to 1,976 B,Result[Synth, MusicError].unwrapfrom 5,568 B to 8 B, and a board program'sbootcalling them from 22,560 B to 11,464 B. The deepest stack alongboot → synthgoes from 30,104 B to 13,440 B.
- A copy is kept wherever the difference could be seen: another value returned after
Fixes
- A
build-carchive no longer leavessysl_wall_usundefined (09c6124). Before, any program reachingsysl.time.now(), which includes everysysl.logcall, failed at the consumer's link. Wherever the standard library is compiled from source (build-c,--no-std-lib), the library's own supplier of a seam the program calls is now analyzed and kept:sysl.posix.time'ssysl_wall_usandsysl_monotonic_us. It is taken only on a target whose operating system hasposix, and never where the program or a package supplies the same symbol. Tests:LibrarySupplierCliTests. - An
#ifin a dependency's file no longer drops the module for importers (d290e63, 6144e68). Which package a file belongs to was keyed by the source as collected, but#ifgating and literate tangling hand the parser a new source whenever they change the text. A dependency's file with any#ifin it, and any.lsyslfile, was therefore filed as the program's own, and its module became a second, unprefixed copy that answered imports with none of the package's other files. A prepared source now records what it was prepared from. Tests:DependencyConditionalTests. sysl.fsno longer names libc symbols that Android's Bionic lacks (4fc7352, d1b155c). Anaarch64-androidprogram reachingwrite_text_atomic, or anysysl.fscall that readserrno, failed at its link. On Android,errnois now read through Bionic's__errnorather than glibc's__errno_location, and the pending name's token comes fromarc4random_bufrather thangetentropy, which Bionic has only from API 28 on. macOS (__error) and Linux (__errno_location,getentropy) are unchanged. Tests:LibraryAndroidLibcCliTests.
Library
sysl.log.message_text(r, out)renders a record's message and fields alone, such asunderrun frames=512. Fields are quoted exactly astextquotes them, with no time, no level and no newline. It is meant for a sink whose destination stamps its own time and level (logcat, syslog, journald).textnow shares its field rendering and writes the same bytes as before (b4be242).
Tests: ReceiverInPlaceTests, ReturnSlotTests, AggregateLoweringTests, PackageBuildTests, and library/sysl/log/tests.sysl.
Verification
- Full Native gate on
50dbec81(./run-gate.sh): GATE: GREEN, 12461 succeeded, 0 failed, no retries, nothing timed out. The release is that sha plus two commits: a comment-only pointer fix inTypeChargingTestsand the version bump. - Warnings census clean (JVM / JS / Native / syslDocJVM / syslDocNative): after
clean, two / three / three / one / two. Every warning is named, and none is in this repository:Reader.scala:26:6comes from scala-parser-combinators,Set.scala:62:15from the Scala.js scaladoc, and the rest are the build-infra-Xpluginand-classpathlines. check-pointers.pyagainst the site: 2240 pointers, 0 unresolvable.- The darwin tarball was extracted to a scratch prefix and checked there:
sysl --versionreports 0.0.161,sysl runworks, andsysl docdispatches tosysl-doc.