Repository navigation
v0.3.0
Install
curl -fsSL https://raw.githubusercontent.com/orelang/ore/main/install.sh | shor brew install orelang/tap/ore; then ore update keeps it up to date.
Each archive carries its LLVM and lld.
| For | File |
|---|---|
| Linux x86-64 | ore-v0.3.0-linux-amd64.tar.gz |
| Linux arm64 | ore-v0.3.0-linux-arm64.tar.gz |
| macOS arm64 | ore-v0.3.0-darwin-arm64.tar.gz |
| VS Code extension | ore-vscode-v0.3.0.vsix |
| Zed extension | ore-zed-v0.3.0.zip |
The editor extensions run ore lsp, so ore must be on PATH. VS Code:
install "Ore" (orelang.ore) from the Marketplace or Open VSX, or
code --install-extension ore-vscode-v0.3.0.vsix. Zed: unzip
ore-zed-v0.3.0.zip and pick its directory in zed: install dev extension
(Zed builds it with Rust, which must be installed with rustup).
What is in 0.3.0
Ore's own garbage collector, precise and concurrent; faster tasks, regular expressions and JSON; benchmarks against C, Go, Bun and Node.
- Benchmarks in plain C next to Ore, Go, Bun and Node:
bench/<name>/main.c
for every benchmark, C17 and libc only (pthreads forchannelsand
tasks, POSIXregex.hforregex), built bybench/run.shwith
$CC -O2 -march=native. The script's markdown now starts with the date,
the machine (CPU, cores and threads, memory, OS and kernel), the version
of each toolchain and the timing method;-o pathorRESULTS=path
writes it to a file as well, and the columns are always ore, c, go, bun,
node. - Each worker thread has its own run queue, as in Go: a lock-free ring that
tasks it spawns or wakes go to, with a slot for the task the running one
woke last (so two tasks that wake each other run in turn on one thread),
stolen from by idle workers, half of it moved to the global queue when
full; the global queue is looked at every 61 tasks. bench/channels runs
about 1.5–2x faster on 10 threads; bench/tasks is unchanged. - Spawning tasks is about ten times faster (
bench/tasks, 100000 tasks:
1.1 s to 0.09 s on a 10-core Mac). A task gets its stack when it first
runs, not when it is spawned, and gives it back when it ends to a cache
of the worker and a shared one, so mapping and unmapping stacks is rare;
the stacks are listed for the collector without its lock. AWaitGroup
of "ore:sync" counts atomically and locks only when its count drops to
zero. An idle worker is signalled only when there is one. JSON.parse<T>reads the text straight into aT, with no tree of
values in between: keys are compared in place with the field names and
strings without escapes share the bytes of the text. Only when that
fails is the text parsed into values, to report the same error as
before.JSON.stringifywrites integers into its buffer without a
string for each. bench/json runs about 3x faster in a quarter of the
memory.- The collector marks alongside the program: two short stops (scanning
the roots, then finishing) instead of one for the whole collection, with
a write barrier the compiler emits before stores of pointers into the
heap. It scans objects precisely, by a pointer map of their type, and
never scans arrays of numbers; it gives free pages back to the system;
and its pace is set byORE_GOGCandORE_MEMLIMIT.ORE_GCSTW=1
marks with the world stopped, as before. - Regular expressions are faster (
bench/regexabout 2.6 times): the
search skips bytes no match can start with and, after a failed try, the
rest of a leading loop's run; a greedy loop of one character runs as one
instruction, and keeps no choices when giving characters back could not
match;execandtestreuse the expression's matcher; a replacement's
$patterns are read once.indexOfcompares only where the first byte
is. ore doc [file.ore | dirs...]prints the API of modules: their exported
functions, classes with their public members, interfaces, type aliases
and variables, with their signatures as the hover shows them and their
JSDoc (@param,@returns,@exampleand other tags), after the//
comment the module starts with. On a terminal it is a colored listing;
--mdmakes Markdown (with-o dir, a file per module and an
index.md),--jsona JSON dump for tools.ore:testgrows towardbun:test:describegroups (their names prefix
their tests',math > adds), the hooksbeforeAll,afterAll,
beforeEachandafterEach,skip,onlyandtodo(Ore functions
have no properties, so nottest.skip),.not, and the matchers
toEqual(deep),toBeNull,toBeTruthy,toBeFalsy,toContain,
toHaveLength,toBeGreaterThan(OrEqual),toBeLessThan(OrEqual),
toBeCloseTo,toMatchandtoPanic(Ore'stoThrow: the function
runs in a task whose panic is caught). Failures show the matcher and the
expected and received values, as a diff of lines when they take several.
The tests of a file now run when its top-level code ends, so thatonly
can apply; a test declared in another task still runs at once.ore test -t <pattern>runs only the tests whose full names match. The summary
counts skipped and todo tests.- The type parameters of generic methods may have defaults
(size<U = T>(): int), as those of functions do; ORE5019 is no longer
reported. A generic method is checked only for the calls it has, so such
a method of a generic class can use what only some of its instances have. unknownas the type of values: any value converts to it, boxed with
its type, andconsole.logprints it as that type. It can be compared
with===, tested fornulland narrowed withtypeof(tostring,
f64,boolorbigint) andinstanceof(to a class), which unbox it;
anything else is an error,Object is of type 'unknown'.(ORE3078).- Numeric literal types are types of values:
const n: 1 | 2 = 1,
function rotate(d: 0 | 90 | 180 | 270),type Dice = 1 | 2 | 3 | 4 | 5 | 6.
Their values are numbers held as anf64; they widen tonumber, and
arithmetic and comparisons see numbers. A constant fits when it equals a
member (ORE2067);===andswitchnarrow them, and aswitchwith a
case for each is exhaustive. ORE2066 now concerns onlyneverinside
tuples and object types. - Generic nested functions (
function id<T>(x: T): Tin a function body)
and generic function literals of aconst(const id = <T>(x: T): T => x): each list of type arguments makes an instance, a closure that
captures the variables of the enclosing functions like other nested
functions. They can only be called; used as a value without a call, such
a function is an error (ORE6071), and one that calls itself needs a
return type annotation (ORE6072). - Getters and setters, of classes and of object literals, implement
interface fields: a getter areadonlyfield, a getter and a setter a
writable one. Reads and writes through the interface (and through a union
with interface members) call them. Fields of names that no accessor
implements are read and written through interfaces as before; the others
test the table entry first. console.logcolors follow Node's rules for the terminal too: with no
TERM, or one Node does not know, a terminal shows no colors, unless
COLORTERM,TERM_PROGRAM, tmux or a known CI service says it does.- The checker parses
builtin.d.oreonce per process instead of on every
check, which the language server runs on every change. - The language server tries a GitHub repository whose download failed
again a minute later, or at once when a document importing it is saved,
instead of never in the session. Math.min()andMath.max()with no arguments areInfinityand
-Infinity, as in JavaScript (they were ORE4019), or the extreme of the
integer type expected, as with only empty arrays spread in.- Regular expressions of the
vflag take string disjunctions
([\q{abc|d}x]), longest strings first, in their set operations too; a
negated class that may hold strings is an error. Withu(orv) and
i,\w,\W,\band\Bcountſand the Kelvin sign as word
characters, as in JavaScript. - Maps, sets and channels are scanned precisely by the collector: the
compiler passes the pointer maps of their keys, values and entries, map
entries and channel buffers are allocated with them (never scanned when
they hold no pointers), and the arrays ofkeys()andvalues()carry
the pointer map of their elements.