Running programs
loom has two run paths. A compiled .lc needs only the runner.
A .luc source may need the separate luce compiler to
produce or refresh a cached library first.
| Form | Work performed |
|---|---|
loom run FILE.lc [ARGS] | Validate the artifact, load it, and call it. |
loom FILE.lc [ARGS] | Shorthand for
run. |
loom luce FILE.luc [ARGS] | Resolve the full source project, reuse or build its library artifact, then run it. |
loom FILE.luc [ARGS] | Shorthand for the source form. |
Arguments after the program path belong to the program. They arrive in
main(args: list(string)); a program that needs none may declare
func main():.
A .lc is a native library artifact
The compiler creates this form explicitly:
$ luce build app.luc --emit=library $ loom run app.lc one two
--emit=library matters: the default luce build
output is a standalone executable named after the source. The library form is
for loom or another compatible host.
Running a current .lc performs no compilation and needs neither
LLVM nor the luce binary. The artifact contains native code linked
to Luce's runtime and exports the one entry loom calls.
The tag is checked before loading
Every artifact records its tag layout, target machine, host ABI version, code-generator identity, and source/program hash. loom reads and validates that metadata before asking the platform loader to map the file.
A missing file, a non-Luce library, truncated metadata, a different target, an old host ABI, a different code generator, and a stale source hash are different failures and are reported as such. There is no interpreter fallback: an artifact that cannot be trusted is not run.
Source runs use a content-checked cache
loom luce FILE.luc resolves imports and packages, creates the
verified serialized hand-off, and checks for a matching native library. The
cache key covers every loaded source and the project/package resolution inputs,
not only the entry file's timestamp.
Where the artifact lives depends on the source:
- A standalone source with no governing
luce.yamlusesFILE.lcbeside the source. - A governed project mirrors the entry's path under
PROJECT/.luce/cache/. Deleting that cache is safe; the next run rebuilds it. - A source that has no writable named location uses a private directory under the user's temporary directory, addressed by its content hash.
A warm run invokes no external compiler. A cold run locates
luce, asks it to turn the verified .lcm hand-off into a
library, validates the result, and atomically places it in the cache. Temporary
hand-off and partial output files are removed on success and failure. Concurrent
writers use distinct temporary names, so a cache entry is never a half-written
library.
How loom finds the compiler
loom first looks beside its own executable, then on the PATH it
was given. This makes the checked installer self-contained even when an editor
or GUI process starts with a minimal system path. The compiler in turn reads
LUCE_LIB and LUCE_CC for runtime-library and linker
policy.
If no current cache entry exists and no compiler can be found, loom names
both places it looked. A direct .lc run does not perform this search
because it has nothing to compile.
What the invoking shell receives
The program's status passes through. The defined result classes are:
| Status | Meaning |
|---|---|
0 | The program returned normally. |
1 | The program trapped, or loom itself could not load/compile the requested program. |
3 | A recoverable Luce error reached the entry uncaught. |
70 | The runtime ran out of memory. |
71 | The host could not run the program or deliver its output. |
| another value | The program called exit(status). |
Debug artifacts carry source locations and function names for traps. Release artifacts keep function names but omit source locations; safety and status semantics do not change.