Luce
Luce BaseSourceLuciaOS

Luce

The application language of the Luce project

Luce is Python's ease with a compiler's guarantees: one integer, one float, text, values that copy, classes that share, memory that manages itself, failure that is visible, and nothing about machines. Everything about machines is Luce Base (base.md), the systems language this compiler is written in and the only door to C. A Luce program reaches Base by import, and it compiles to Base, so every backend, optimiser and target Base has is Luce's.

The language sentence:

Values copy. Classes share. Nothing is freed by hand. Failure is a type. The machine is a Base package away.

The product sentence:

Readable like Python, checked like a compiler, fast like the systems language under it.

This document is the complete contract of the language. base.md is the contract of the language under it, and chapter 16 is the contract between the two. Where an implementation and this document disagree, the document is right and the implementation is a bug; where this document is silent, the behaviour is not promised.

1. Principles#

Eight concepts. Every Luce program is made of bindings, functions and control, values, classes, collections, failure, abstraction, and workers. Arrays, strings, files, sockets and windows are types and libraries built from those; methods are functions inside a type; closures are functions with an environment; iteration is an interface plus for; errors are one value carried by T!; tests are registered fallible functions; packages are modules plus a manifest. Nothing else is a concept.

One number of each kind. int is a 64-bit signed integer and float a 64-bit IEEE double. There is no other width, no unsigned integer, no wrapping or saturating arithmetic, and no bit operation. Code that needs them is Base code.

The machine is elsewhere. Luce has no pointer, span, fixed array, union, allocator, asm, atomic, or foreign declaration. A Base package has all of them and exposes a Luce program only the crossable types of chapter 16. This is what keeps Luce small: a need for the machine is a reason to write a Base package, never a reason to add a feature.

Memory is not the programmer's. Objects are reference-counted and a cycle collector reclaims what counting cannot, exactly Python's model. There is no word for allocation, release, ownership or weakness in the language. Resources close with with.

Failure is visible. A function that can fail says so in its type, a caller handles it or passes it on, and a violated rule is a trap with a source trace, never an exception.

A feature enters only when it removes more complexity than it adds, counting syntax, semantics, the compiler, the runtime, diagnostics, tooling, documentation and what a programmer must remember. When a need appears it is solved at the cheapest correct layer: a diagnostic, a library, a tool, then the language.

Two executions must agree. The interpreter is the definition of behaviour, and the Base the compiler emits must print the same bytes through every generator Base has. A feature is not implemented until they agree on its programs and its traps.

Contents#

1. Principlesclasses, collections, failure, abstraction, and workers. Arrays, strings, files, sockets and windows are types and libraries built from those; methods are functions inside a...2. Source textSource is UTF-8. A byte-order mark is accepted only at byte zero. NUL bytes, invalid UTF-8, the Unicode bidirectional format characters (U+202A to U+202E and U+2066 to U+2069),...3. Literalstrue, false, and none. none takes its optional type from context and is never a universal null.4. TypesThere is no implicit conversion between any two of these. int(x), float(x), str(x) and bool(x) convert explicitly (§6.5).5. Bindingslet limit = 10 var count = 0 count += 1 let point: Point = Point(x = 1.0, y = 2.0)6. ExpressionsOperands, arguments and elements evaluate left to right, once. and and or short-circuit. A conditional expression evaluates only the arm it picks.7. Functionsfunc area(width: float, height: float = 1.0) -> float: return width * height8. Control flowif n < 0: sign = -1 elif n == 0: sign = 0 else: sign = 19. Valuesstruct Point: var x: float var y: float10. Classesclass Document: let title: str var dirty: bool = false var pages: list[Page] = []11. Collections and textlist is a growable ordered collection with identity: two bindings of one list are the same list, is says so, and .copy() makes an independent shallow copy. Indexing is checked.12. Absence and failurelet found: User? = find(users, id) let name = found.name if found != none else "nobody" let user = find(users, id) else return let count = counts[key] else 013. Interfaces and genericsinterface Shape: func area(self) -> float func name(self) -> str14. Workerslet work = spawn render(scene) let other = spawn render(other_scene) let (a, b) = (wait work, wait other)15. Modules and packagesOne .luc file is one module; its path under the package's source root is its name: src/image/color.luc is image.color. A file's name is an identifier. A .lucb file in the same...16. The Base boundaryA Luce module imports a Base module by the same import, a .lucb file under the source root. It sees the module's pub functions, pub let constants, pub structs and...17. ToolingEvery diagnostic is file:line:column: message, one per line, the first one first, and a rejection exits with status 1. A declaration that does not check is reported and the...18. Deliberate exclusionsNot in Luce, with the reason: integer widths and unsigned integers (one number of each kind); bit operations, shifts, wrapping and saturating arithmetic (Base); char (a scalar...19. Grammar summarymodule = {import} {declaration} import = "import" path ["as" NAME] | "from" path "import" NAME {"," NAME} declaration = ["pub"] (func | struct | enum | class |...