Skip to content

Releases: joagre/ernest

Ernest 0.9.0

Choose a tag to compare

@joagre joagre released this 03 Nov 06:04

Ernest 0.9.0 is the release of the first program built against an installed Ernest by a repository of its own: ernest-httpd, which serves ernest-lang.org over TLS since 2026-11-02, and what it asked of Ernest on its way, TLS in Tcp, a program under a pseudo-terminal in Os, four libraries, base64, crypto, time and http, and seventeen lines of feedback decided the days they came. With it come what the release review before it decided, a constructor shown with its module's name, a read given no time that has run out as it begins, and the report's sentences for every silence its readers found.

A program written for 0.8.0 changes these things. Its modules are built again, since ern run, ern test and Code.load refuse a compiled form another build of ern wrote. A node of 0.9.0 and one of 0.8.0 do not connect, as two minor releases never do. Io.show writes a constructor outside the prelude with its module's name, Io.Timeout for what was Timeout, so a program that reads show's text, or a test that compares against it, sees the name. Tcp.read and Os.read given no time answer Left(Timeout) whatever has arrived, as every wait does; a poll gives them a millisecond.

Json.parse's UnexpectedByte and UnexpectedSequence carry where they begin, at = Position(line, column), and the sequence is a String. Http.render is Http.renderResponse, Time.civil is Time.toCivil, and Time.weekday takes a Civil. A module named ernest.ern, or under ernest/, is refused, the namespace being the toolchain's own. A clause whose guard is the literal false is refused as a redundant clause.

Until 1.0 a release may refuse a program the previous release accepted, as the plan says. The report of this release is what holds. What changed since 0.8.0 is the report's diff, git diff v0.8.0 v0.9.0 -- report/, and why is the decision log's entries after The Release Review Before 0.8.0 in docs/log.md.

What changed:

The language and the report

  • Ernest a taken namespace, the shell standing under it as Ernest.Shell: §4.2, §11.1, §12.7; the log's Four Lines From the Deployment.
  • A clause whose guard is the literal false redundant: §5.9; The Release Review Before 0.8.0.
  • The caller of Os.exit neither told nor waited for, a termination once the end has begun cutting the wait short, and a program under a terminal counting as a computation: §8.6; A Program After Its Exit, The Release Review Before 0.9.0.
  • A value reclaimed by its process's collection, in the host's two generations: §10; Four Lines From the Deployment, The Release Review Before 0.9.0.
  • An archive's version text naming its commit: §11.7; An Archive Says Its Commit.
  • A listener's family, and a node's: §12.5, Appendix E.18; Four Lines From the Deployment.
  • The toolchain's own units listed, and an attach refused by a node that could not load them: §11.2, §12.7; Four Lines From the Deployment, The Release Review Before 0.9.0.

The toolchain and the shell

  • An IPv4-mapped listen refused by ern config and the node: §12.5; The Release Review Before 0.9.0.
  • ernest.pid made for its owner alone, and ern stop and ern reload checking the directory as the node does: §12.5; The Release Review Before 0.9.0.
  • The shell's modules under src/shell/ernest/, Ernest.Shell: §11.2; Four Lines From the Deployment.
  • The terminal tests' harness an Ernest program over Os.startTerminal: The Harness in Ernest.

The library

  • Tcp.listenTls and Tcp.connectTls, one socket over TLS or not, Verified(caFile) and Unverified: Appendix E.18; TLS in Tcp and a Terminal in Os, Two Lines on TLS.
  • Os.startTerminal, Os.resize, closeInput as a hangup, a program's process living on after its exit, Os.user, Os.exit's caller: Appendix E.23; TLS in Tcp and a Terminal in Os, A Program After Its Exit, The Hangup's Order.
  • Tcp.write as the host's send, the endpoints of a closed connection, a read or an accept whose caller ended: Appendix E.18; A Close, an Exit and a Write, Three Flakes Read.
  • libs/base64, libs/crypto, libs/time and libs/http: Appendix G.8 to G.11; The Four Libraries.
  • Json's errors carrying a Position, a broken literal or escape named at the byte that breaks it, and a too-long number found in one pass: Appendix G.6; The Error's Place, The Release Review Before 0.9.0.
  • Io.show writing a constructor outside the prelude with its module's name: Appendix E.1; The Release Review Before 0.9.0.
  • A read given no time having run out as it begins, in Tcp and Os as everywhere: Appendix E.0 shape rule 8, E.18; The Release Review Before 0.9.0.
  • Fs.setMode, a path through a file, a loop of links and a long name: Appendix E.17; A Path Through a File.
  • Io.writeError, Terminal.width, Supervisor.child, Random.nextFloat's bounds: Appendix E.1, E.19, E.21, E.12; Three Lines From the Server.
  • Path.join writing its segments as given: Appendix E.14; A Path Through a File.
  • Http's response readers reading a fold and a body to the close as RFC 9112 has a client read them, its renderers faulting on a value that would break the message, a status of three digits, one empty line before a request skipped: Appendix G.11; The Release Review Before 0.9.0.

The runtime

  • A program's process group killed when the program is reaped, a pinned certificate taken sent alone or at a chain's end, and a CA file read before the dial: Appendix E.23, E.18; The Release Review Before 0.9.0.
  • A fault's trace keeping its callers' frames, which the host's type pass had cut: §7.3, Appendix E.21; The Release Review Before 0.9.0.
  • ernest.pid made for its owner alone, and a termination once the end has begun cutting the wait short: §12.5, §8.6; The Release Review Before 0.9.0.
  • resize answering Closed after the exit or the hangup: Appendix E.23; The Release Review Before 0.9.0.
  • A load's evaluator counting a running program and an open connection only: Appendix E.28; The Release Review Before 0.9.0.

What the review did not run: the service manager's checks under launchd, since no Mac was at hand; on macOS the archive is expected to work and is not yet verified.

The newcomer's program is pindex, a parallel inverted-index builder in four modules of 409 lines: a crawler runs a monitored worker for each file, at most a given number at once, an index process keeps each word's files and answers lookups by a call, the index is written to a file and renamed over it, and the command line answers a word a line from standard input with the files it is in; its tests cover the tokenizer, the index, a killed index and a crawl with an unreadable and a broken file. It built at the first try, its nine tests passed, and it ran; it is published beside the archive.

Ernest 0.8.0

Choose a tag to compare

@joagre joagre released this 01 Nov 11:00

Ernest 0.8.0 is the release of the pun: a field given or matched by the variable of its own name is written once, Desk(=local). With it come what its day decided, a receive that always receives with Clock.sleep as the one wait for a time, an alarm that can be canceled, a receive guard that reads a field, a doc example run at its own mailbox type, and what the release review before it decided. Its row in the plan is https://github.com/joagre/ernest/blob/v0.8.0/docs/plan.md, and what Ernest is and why is https://github.com/joagre/ernest/blob/v0.8.0/guide/why.md.

A program written for 0.7.0 changes these things. Its modules are built again, since ern run, ern test and Code.load refuse a compiled form another build of ern wrote. A node of 0.8.0 and one of 0.7.0 do not connect, as two minor releases never do. A receive with an after clause alone is refused and is written Clock.sleep(ms); a function that waited so receives nothing now, and a receiving e written on it is refused. Clock.alarm and Clock.alarmAt answer an Alarm, so a site that drops it writes let _ =. A request whose only field is its reply is declared positional and passed to Address.call bare, which the style asks for and the style test holds, as it holds the pun.

Until 1.0 a release may refuse a program the previous release accepted, as the plan says. The report of this release is what holds. What changed since 0.7.0 is the report's diff, git diff v0.7.0 v0.8.0 -- report/, and why is the decision log's entries after The Release Review Before 0.7.0 in docs/log.md.

What changed:

The language and the report

  • The pun, =f for f = f, in a construction, an update, a fill and a pattern: §5.6, §5.10, Appendix A; the log's The Pun.
  • Principle 2's sentence admitting a field paired with the name that gives or binds it: §0; The Pun, The Release Review Before 0.8.0.
  • A receive always receives, Clock.sleep the one wait for a time, a Never body sleeping: §3.9, §4.6, §6.3, §6.8, Appendix A; A receive Always Receives.
  • A guard reading a field selected from a variable in scope or a top-level let: §6.3; The Pun's Opening Round.
  • Alarm bound to its node, with the runtime's equality, a resource: §3.10, §3.11; An Alarm Can Be Canceled.
  • A restart and a foreign fault reaching a sleep and a load's wait: §6.9, §8.4; The Release Review Before 0.8.0.
  • A wait in a function the runtime applies being the applying process's own: §6.5, §6.9; The Release Review Before 0.8.0.
  • A sleep's cost growing with the messages waiting: §10; The Release Review Before 0.8.0.
  • What a load's undoing kills having ended before the load answers: Appendix E.28; make version, Appendix D Whole, the Settler's Restart.
  • Appendix D written whole, with made, owned and contains: Appendix D; make version, Appendix D Whole, the Settler's Restart.

The toolchain and the shell

  • A doc example running at the mailbox type of its function, and shape rule 6's one test for one that stays compiled: §11.2, Appendix E.0; Ernest 0.8.0, a Small Release.
  • The help for a receive with an after clause alone naming Clock.sleep: §6.3, §11.5; A receive Always Receives.
  • The shell's line at a binding's end naming the site alone: §11.2; The Pun's Opening Round.
  • The style test refusing f = f and a one-field request with a named reply: guide/style.md; The Pun, Ernest 0.8.0, a Small Release.
  • make version V=x.y.z, with VERSION naming the release the checkout works toward: docs/release_review.md; make version, Appendix D Whole, the Settler's Restart.

The library

  • Clock.sleep: Appendix E.15; A receive Always Receives.
  • Clock.Alarm and Clock.cancel, alarm and alarmAt answering an Alarm: Appendix E.15; An Alarm Can Be Canceled.
  • Utilization.schedulers receiving nothing: Appendix G.4; The Pun's Opening Round.
  • Receiving covering a process in Clock.sleep: Appendix E.21; The Release Review Before 0.8.0.
  • Nine examples of the library showing their values, the clock's among them: Appendix E.0; Ernest 0.8.0, a Small Release.

The runtime

  • Clock.sleep holding the timed mark, a restart asked for and a fault in the mailbox reaching it: §6.9, Appendix E.15; A receive Always Receives.
  • An alarm canceled by any process of its node, and ending with its setter's restart: Appendix E.15; An Alarm Can Be Canceled.

What the review did not run: the service manager's checks under launchd, since no Mac was at hand; on macOS the archive is expected to work and is not yet verified. make sanitize was not run, the helper being unchanged since 0.7.0.

The newcomer's program is scheduler, a job scheduler in two modules of 335 lines: a scheduler process runs at most capacity jobs at once, each in a monitored worker under a deadline by Clock.alarm, kills a worker that overruns and retries a failed job up to its attempts, keeping a caller's Reply until the job ends; the command line takes jobs as name=sleep/ms|sum/n|fail/text. Beside the archive as scheduler.ern and jobs.ern: ern build --build-root build . in their directory, then ern test build/scheduler.erc, then ern run build/jobs.erc nap=sleep/300 add=sum/100 slow=sleep/2000 bad=fail/boom quick=sleep/100.

Ernest 0.7.0

Choose a tag to compare

@joagre joagre released this 31 Oct 16:05

Ernest 0.7.0 is the release of a shell attached to a running node: ern shell --config-dir dir --attach name runs each input on a listed peer, lists its processes and loads and reloads its modules, while the operator's machine keeps the terminal and the files. It also brings the report pared to the language, with the runtime's mechanism a chapter of its own, and what the release review before it decided. Its row in the plan is https://github.com/joagre/ernest/blob/v0.7.0/docs/plan.md, and what Ernest is and why is https://github.com/joagre/ernest/blob/v0.7.0/guide/why.md.

A program written for 0.6.0 changes these things. Its modules are built again, since ern run, ern test and Code.load refuse a compiled form another build of ern wrote. A node of 0.7.0 and one of 0.6.0 do not connect, as two minor releases never do; a configuration directory 0.6.0 made serves as it is, but ern config now writes a listen only with --listen, so a directory that peers must reach is made with it.

ern test exits with status 1 where a process faulted during the run, a service binding starting under it as under ern run. A node whose carrier cannot start ends as a job that cannot start, with status 1 and no fault. In a shell, Os.exit faults a process an input started, a site carries its session's namespace, let p <- e is taken at the prompt, and :quit leaves an attached shell with its node running on. restarting called in a function the runtime applies faults, and a foreign function typed by its callback receives through it alone. Four library functions are new, each marked since 0.7.0.

Until 1.0 a release may refuse a program the previous release accepted, as the plan says. The report of this release is what holds. What changed since 0.6.0 is the report's diff, git diff v0.6.0 v0.7.0 -- report/, and why is the decision log's entries after The Release Review Before 0.6.0 in docs/log.md.

What changed:

The language and the report

  • The runtime's mechanism in chapter 12, §10 in toolchain.md: §10, §12; the log's The Report Pared, Built.
  • The Peer functions' contracts under E.27: Appendix E.27; The Second Cut, §8.7 to E.27.
  • §12.1's keys and §12.3's causes binding every runtime: §12; The Argument's Four Decisions.
  • A restart in a function the runtime applies refused: §6.9, §7.4; The Argument's Four Decisions.
  • A foreign function typed by its callback receiving through it alone: §4.7; The Argument's Four Decisions.
  • A deadlock while a load's evaluator waits faulting the evaluator: §8.6; The Argument's Four Decisions.
  • A session's namespace carrying its number, and on a node the node's key: Appendix H; The Attached Shell's Sentences, Sites, Sessions and Their Names.
  • An address the permission to send, a Process what Process.kill ends: §6.5; Reload, Services and Tests.
  • The report's paragraphs, none past 150 words: the log's The Report Pared, Built.

The toolchain and the shell

  • The attached shell, ern shell --attach name: §11.2 The attached shell, §11.7, §11.8; The Attached Shell's Cut, The Attached Shell's Sentences, The Attached Shell, Built, The Attached Shell, Tested.
  • The attach waiting twice a dial's time: §11.2; The Shell's Own Node.
  • Sessions numbered, a site carrying its session's namespace: §11.2 Faults, Startup and history; Sites, Sessions and Their Names.
  • A reload said at every session's prompt: §11.2 The attached shell; Sites, Sessions and Their Names.
  • :quit leaving every shell, :detach none: §11.2 Commands; One Word to Leave.
  • :processes with each process's activity: §11.2 Commands; The Shell's Second Round, Decided Again.
  • A binding input's process living while its name is in scope, and what it owned said at its end: §11.2 Inputs; The Shell's Second Round, Decided Again, The Input's Process.
  • let p <- e at the prompt, and it after a Left: §11.2 Inputs; <- at the Prompt, The Input's Process.
  • A prompt's binding read on the session's node: §11.2 Inputs; The Input's Process.
  • An expression's input one unit, an input's cost flat in the session: §11.2 Inputs; A Line-Mode Input's Cost, An Expression's One Unit, and an Input's Cost Flat.
  • A load evaluating in an evaluator that ends with its work: §11.2 Loading and reloading; The Argument's Four Decisions, Sites, Sessions and Their Names.
  • A compiled form taken by :load judged by its source's digest: §11.2 Loading and reloading; The Release Review's Code Fixes.
  • :doc documenting the code the node loaded: §11.2 Commands; The Claims, the README and the Tour.
  • Os.exit by session, and from the shell's own code ending the shell: §11.2, Appendix E.23; The Attached Shell's Sentences, The Library's Lines.
  • ern config without --listen writing no listen: §11.3; The Shell's Own Node.
  • A carrier that cannot start refusing the job, an end of the program with its subscribers told: §12.5, §8.6, §11.8; The Shell's Own Node, The Release Review Before 0.7.0.
  • The protocol's version moving at a release whose frames differ: §12.5; The Release Review Before 0.7.0.
  • ern test red where a process faulted, and a service binding started under it: §11.2, §11.8; Reload, Services and Tests.
  • ern run and ern test refusing a compiled form another build wrote: §11.2; One Function per Initializer.
  • A private function or binding refused as private: §11.5; The Claims, the README and the Tour.
  • A field read in a receive guard answered with a help naming the let before the receive: §6.3; The Release Review's Code Fixes.
  • A block's let whose initializer names its own name reported as a cycle: §4.6.
  • A standard library shim called as the host's function at the call site: §11.1; The Emitter's Calls Against the Host's, Built.
  • Each initializer a function of its own, and the build's cost linear in its functions: §11.1; The Build's Cost per Function, One Function per Initializer.

The library

  • Process.kill: Appendix E.21; Reload, Services and Tests.
  • Process.owned and Ets.owned: Appendix E.21, G.1; The Input's Process.
  • Test.until, yielding between its runs: Appendix E.24, E.0 shape rule 8; What the Newcomer's Feedback Left, Test.until, Built, The Library's Lines.
  • Code.load evaluating in an evaluator, the load undone where its caller ends while it waits: Appendix E.28; The Argument's Four Decisions, Sites, Sessions and Their Names, The Release Review Before 0.7.0.
  • Process.live and Process.faults leaving sessions' own processes, evaluators and a process that has ended out: Appendix E.21; The Session's Screen and the Toolchain's Units, Built, Sites, Sessions and Their Names.
  • A shim's raise traced from the caller's line: Appendix E.21; The Emitter's Calls Against the Host's, Built, The Release Review's Code Fixes.
  • Peer.compute never drawing an attached shell's own node: Appendix E.27; The Attached Shell's Own Node, Quiet.

The runtime

  • A session's screen, a write going to its writer's session: §12.1; The Session's Screen and the Toolchain's Units, Built.
  • The toolchain's own units loaded from the node's tree, the frame saying whose a unit is: §12.6, §12.7; The Session's Screen and the Toolchain's Units, Built, The Shell's Own Node.
  • An attached shell's own node telling no utilization and saying nothing of its session's node: §12.5, E.27; The Attached Shell's Own Node, Quiet.
  • A detached session's units that declare a function kept for the node's life: §11.2 What a node holds; The Detach Keeps What Declares a Function.
  • An attached shell's last lines on rows of their own, and a shell's end losing none: §11.2; The Attached Shell's Last Row, The End's Lines Reach the Screen.

What the review did not run: the service manager's checks under launchd, since no Mac was at hand; on macOS the archive is expected to work and is not yet verified.

The newcomer's program is auction, an auction house whose house process opens lots and takes bids by a call, and sells each lot to its highest bidder at its deadline, writing the sale to a ledger; one module beside the archive: ern build auction.ern && ern test auction.erc, then ern run auction.erc demo, where three robots bid for two lots. Run as a node with --config-dir, the house takes lots and bids from an attached shell's prompt, Auction.open("a lamp", 10, 60), its ledger sales.log in the node's working directory.

Ernest 0.6.0

Choose a tag to compare

@joagre joagre released this 25 Oct 21:37

Ernest 0.6.0 is the release after what the review before 0.5.0 and the release itself left was done: a
service monitor on a process of another node is now told of its restarts too, by the runtime's own
frames, so that monitorService means one thing wherever the process lives; the test harness counts
each test's steps; and a release review read what changed. Its row in the plan is
https://github.com/joagre/ernest/blob/v0.6.0/docs/plan.md, and what Ernest is and why is
https://github.com/joagre/ernest/blob/v0.6.0/guide/why.md.

A program written for 0.5.0 changes these things. A service monitor on a process of another node
is told Restarted at each of its restarts, where 0.5.0 told it nothing, and a restart of a process
that a process of another node monitors or calls waits for that node's answer, at the latest until a
loss. A node of 0.6.0 and one of 0.5.0 do not connect, since the protocol's version moved. ern format lays a lambda whose body does not fit on its line out with the body on the next line, so a
source formatted by 0.5.0 may move. A diagnostic's shown source line carries no trailing blanks.
FaultReport is unchanged.

Until 1.0 a release may refuse a program the previous release accepted, as the plan says. The
report of this release is what holds. What changed since 0.5.0 is the report's diff,
git diff v0.5.0 v0.6.0 -- report/, and why, the decision log's entries after The Release
Review Before 0.5.0
in docs/log.md.

What the review did not run: the service manager's checks under launchd, since no Mac was at
hand; on macOS the archive is expected to work and is not yet verified.

The newcomer's program is lending, a lending library whose desk process lends the copies of a
catalog read from a file, queues patrons and tells them as a copy comes back, and takes back what
a patron held when the patron's process faults; one module beside the archive with its catalog:
ern build lending.ern && ern test lending.erc, then ern run lending.erc catalog.txt ledger.txt.

Ernest 0.5.0

Choose a tag to compare

@joagre joagre released this 25 Oct 06:29

Ernest 0.5.0 is the release after the whole of Ernest was read once more, the report, the
guide, the code and the tools, each by a reader of its own, and what they found was fixed or
decided. It adds the service monitor, a monitor that is also told each time a process restarts;
compare, the one function form of every ordering, over tuples, lists, Optional and Either
too; the tour, one program grown through eight chapters; and the design of the runtime, the
nodes and the code written down beside the shell's. Its row in the plan is
https://github.com/joagre/ernest/blob/v0.5.0/docs/plan.md, and what Ernest is and why is
https://github.com/joagre/ernest/blob/v0.5.0/guide/why.md.

A program written for 0.4.0 changes these things. A member has one face: it is named in a
declaration and in a needs, and used through its operator or compare, so Int.compare(a, b)
is compare(a, b), Int.negate(x) is -x, Bool.not(b) is !b, and Prelude.List.size is
List.size. List.sort(list, f) is List.sort(list), whose elements have a compare, or
List.sortBy(list, key). A match on a Reason that lists every constructor gains Restarted,
the reason a service monitor delivers. A supervisor's mailbox type is Supervisor.GroupMsg, where it
was Supervisor.Msg. A FaultReport has three more fields, callee, peer and time, so a
pattern that named its fields by position changes. A receive with a pattern clause in a
function whose mailbox nothing fixes, spawn(fn() = receive { x -> Unit }), is refused, as the
report always said, since no message can reach it. ern build, ern doc and ern format no
longer take --short-errors. A node refuses a configuration directory, its ernest.conf or its
certificate.pem that its group may write, as it refused one anyone may write.

Until 1.0 a release may refuse a program the previous release accepted, as the plan says. The
report of this release is what holds. What changed since 0.4.0 is the report's diff,
git diff v0.4.0 v0.5.0 -- report/, and why, the decision log's entries after The Release
Review Before 0.4.0
in docs/log.md.

What the review did not run: the service manager's checks under launchd, since no Mac was at
hand; on macOS the archive is expected to work and is not yet verified.

The newcomer's program is kvd, a key-value server over TCP that keeps its values in a log file, four modules beside the archive with the script that drives it: ern build --build-root build kvd && ern test build, then ern run build/kvd/server.erc 7072 data.log in one terminal and a script of commands piped into ern run build/kvd/client.erc 7072 in another, as demo.sh does.

Ernest 0.4.0

Choose a tag to compare

@joagre joagre released this 18 Oct 11:19

Ernest 0.4.0 is the first release with nodes. A program runs on several nodes, each started
from a configuration directory that lists its peers by name, public key and address, and
talking to them over TLS. A process spawned on a peer brings its code along, every definition
known by the hash of its content, so a node with no program of its own takes part, and a
computation that names no node goes to one with room. A service is found by name across
nodes. The shell reloads a module as a new version beside the old, and Code loads a compiled
module into a running node. The release is MVP 3.2's row in the plan,
https://github.com/joagre/ernest/blob/v0.4.0/docs/implementation_plan.md, and what Ernest is
and why is https://github.com/joagre/ernest/blob/v0.4.0/guide/why.md.

A program written for 0.3.1 changes two things. A function that receives writes receiving M
where it wrote with M, and a function that only sends writes nothing. The ! on a function
type is gone, and so is the obligation on a reply it marked: a reply is a value, answered once.

What the shell does not yet do is attach to a running node with its inputs run there; an
operator reaches a node today as the deployment guide's section 6 says,
https://github.com/joagre/ernest/blob/v0.4.0/guide/deployment.md.

Until 1.0 a release may refuse a program the previous release accepted, as the plan says. The
report of this release is what holds. What changed since 0.3.1 is the report's diff,
git diff v0.3.1 v0.4.0 -- report/, and why, the decision log's entries after The Release
Review Before 0.3.1
in docs/decisions.md.

What the review did not run: the code's reader read the node's modules alone, the carrier, the
gateway, the peer, the exchange and the arrival, and the rest of the code waits for the full
review before 0.5.0; and the service manager's checks under launchd, since no Mac was at hand;
on macOS the archive is expected to work and is not yet verified.

The newcomer's program is pubsub, a broker of topics driven by a script on standard input,
beside the archive with the two scripts it was tried on. On one node:
ern build pubsub.ern && ern run pubsub.erc < script.txt. On two, a bare node foo and the
program's node, each made with ern config and listing the other as the deployment guide's
section 1 says: ern run --config-dir foo on one terminal, and
ern run --config-dir a pubsub.erc < script2.txt on the other.

Ernest 0.3.1

Choose a tag to compare

@joagre joagre released this 05 Oct 15:07

Ernest 0.3.1 is a documentation release, from MVP 2.99d: the manual pages of the standard
library, the prelude and the libraries rewritten to teach, the examples made to teach and
listed in an order to read them, the guide staged for its reader, and the report's contracts
stated more precisely, with no rule of the language changed.

Until 1.0 a release may refuse a program the previous release accepted. The report of this
release is what holds. What changed since 0.3.0 is the report's diff,
git diff v0.3.0 v0.3.1 -- report/, and why, the decision log's entries of 2026-10-05 after
The Release Review Before 0.3.0 in docs/decisions.md.

What the review did not run: its readers, since this release changes the documentation and
not the language; a cold reader, briefed as a newcomer, read the rewritten pages instead. And
the service manager's checks under launchd, since no Mac was at hand; on macOS the archive is
expected to work and is not yet verified.

No newcomer wrote a program for this release. taskrun, 0.3.0's, builds and runs under
0.3.1 as it did: ern build taskrun.ern && ern run taskrun.erc < build.tasks.

Ernest 0.3.0

Choose a tag to compare

@joagre joagre released this 05 Oct 10:38

Ernest 0.3.0 is the third release of Ernest, and the end of MVP 2.99c: the core language
argued sound and generated against, before peers build on it. Three machines run in every
make test: programs derived from the grammar of Appendix A, laws of the standard library
checked on cases drawn afresh, and well-typed programs held to an interpreter of the
report's rules. docs/soundness.md argues that a well-typed program does not go wrong. A
full review read every area, and its 570 findings were worked before the tag. The release
carries MVP 2.99b's work too: operations records, needs a.compare with a record filled
from a namespace and derives compare, OrderedSet and OrderedMap, and a program run
by the host's service manager.

Until 1.0 a release may refuse a program the previous release accepted. The report of this
release is what holds. What changed since 0.2.0 is the report's diff,
git diff v0.2.0 v0.3.0 -- report/, and why, the decision log's entries since 2026-10-01
in docs/decisions.md.

What the review did not run: the service manager's checks under launchd, since no Mac was
at hand; on macOS the archive is expected to work and is not yet verified.

The newcomer, who read the guide and wrote a program of their own, wrote taskrun, a task
runner: tasks read from standard input, each run in a monitored process once the tasks it
requires have finished, a few at a time, one that runs past its limit killed by an alarm,
and the tasks skipped and those caught in a cycle reported at the end. It is published
beside the archive with build.tasks, the tasks it was tried on:
ern build taskrun.ern && ern run taskrun.erc < build.tasks.

Ernest 0.2.0

Choose a tag to compare

@joagre joagre released this 01 Oct 16:47

Ernest 0.2.0 is the second release of Ernest, and the first after the principles review: the report and the guide
were read against the five principles of §0, and §0 against what it had decided, on
2026-09-30 and 2026-10-01. The review's product is sentences, not features: §0 gained a
paragraph on the host and one sentence for each principle, and ten sections one sentence
each, under which a family of exceptions became instances of a rule. Programs written for
0.1.0 change in the places below; each is in the report's revision of 1 October 2026, and
the log's entries of that day say why.

What changed for a program:

  • spawn(f) and spawnMonitored(f, wrap) take no placement; Local and Where are
    gone. A spawn on a peer is Peer.spawn(name, f), a module of MVP 3.0, refused until then.
  • via(addr, f) takes the address first.
  • A Down names its process: Down(process, reason, site).
  • Tests are Test.Case(name, run) with Test.Passed and Test.Failed(text), of the
    standard library's module Test (Appendix E.24); Test and TestResult left the prelude.
  • The built-in type Foreign is the library's foreign type Foreign.Term (E.12), with the
    runtime's exact equality; Foreign.toBytes reads any binary.
  • A constructor's named fields are stored, sent and shown in the order they are declared.
  • Io.debug writes to standard error; Io.show and Io.debug are resolved at a known type,
    a type error on a type variable, and write a foreign value as <foreign>.
  • A printed type marks a process-only effect variable m+, beside a= and a!.
  • Terminal's styled, cursor moves and erasures are the library Ansi (G.3);
    Terminal.size answers Either.
  • A reply may stand in a list, an Optional or an Either; §6.6 names no type.
  • A member is an operator, compare or negate alone; let declares no member.
  • Parentheses after |> change nothing; 1e10 is a float; a tuple has two or more
    components; a stray doc block is an error.
  • Tcp.write, Os.read and Os.write take milliseconds; Os.start takes none;
    Os.environment(name) asks by name; Os.give and Tcp.give pass a resource on; a
    listener has an owner.
  • Io.Error names its causes, NotAFile, Exists, NotUtf8, Invalid; Other holds the
    host's words.
  • Fs.makeFile, Fs.setMode and Fs.makeHardLink; Path.<> joins two paths and
    Path.join takes the segments; Path.name is None for the root;
    Path.withoutExtension; List.dropLast(xs, n); String.words; Float.pi;
    Io.writeError; Map.mergeWith's function takes the key; List.<> is Ernest.
  • Gone: Optional.orElse, Either.orElse, Char.isAsciiDigit, Fs.create,
    Fs.makePrivate.
  • The float + and - are no longer normalized for negative zero, which they cannot make.

The newcomer, who read the guide and wrote a program of their own, wrote a key-value cache whose
entries expire after a time or when the process that leased them ends; it is published beside
the archive, cache.ern, demo.ern and checks.ern.

Ernest 0.1.0

Choose a tag to compare

@joagre joagre released this 30 Sep 20:38

Ernest 0.1.0 is the first release of Ernest. It is a functional language for concurrent programs, running on the Erlang runtime. A program is made of pure functions, whose types the compiler infers, and of processes that talk through typed mailboxes. This release runs programs on one node. Programs across nodes, and code known by its hash, come in later releases.

What is in it

  • The language on one node, as the report defines it:
    • a function's mailbox type is part of its type, and every send is checked against its receiver;
    • a Reply is checked to be answered exactly once on every path;
    • Address.call waits with a deadline;
    • restarting and Supervisor restart processes;
    • typed boundaries check what crosses to and from Erlang code;
    • bitstrings;
    • and a foreign function interface for what only the host can do.
  • One command, ern:
    • build compiles;
    • run runs;
    • test runs a module's tests;
    • shell is an interactive shell with line editing, completion and documentation;
    • doc writes a module's page as CommonMark or a manual page;
    • format lays out a source;
    • config makes a node's configuration.
  • A standard library of 23 modules (Appendix E of the report), among them List, Map, Set, String, Bytes, Path, Io, Fs, Tcp, Clock, Terminal, Os, Process and Supervisor. Two libraries outside it: libs/ets and libs/markdown.
  • Manual pages: man ern, and man Ernest.List and the like for each module.
  • An Emacs mode.
  • The guide, Programming in Ernest, and example programs in examples/: a game at a terminal, a small web server, file synchronization, and a read-eval-print loop.

This is the first release, so there is no earlier one to compare it with.

What it does not do yet

  • Peers. spawn(Peer(...)) faults with peer unreachable, and a node's ernest.conf is not read. Distributed code and the node protocol are the next release's (the plan's MVP 3.0).

  • Known limits, stated in the report:

    • Through a type variable, Io.show writes a value by its runtime representation, an abstract type's included (§4.4).
    • A foreign function's result and a callback's arguments at a type variable are not checked at the boundary (§8.4).
    • A value made with Foreign.from crosses into foreign code unchecked (§8.4).

    All three close in the next milestone, MVP 2.99b.

Installing

The archive ern-0.1.0.tar.gz below needs Erlang/OTP 29 on your PATH, make, and a C compiler. The runtime has one helper in C: it runs the programs Os.start and Os.run start, and removes a tree for Fs.removeAll. In the directory the archive unpacks to:

make
sudo make install        # into /usr/local; `make install PREFIX=$HOME/.local` for you alone
ern --version
man ern

It is built and tested on Linux. macOS is expected to work the same way and is not yet verified.

A newcomer's program

Before the release, a programmer who knew other languages but not Ernest read the README and the guide alone, then wrote a program: findex, attached below. It indexes the words of every file under a directory with a pool of workers, one process per file, each under a deadline. It then answers queries, a word per line of standard input, with the files that hold the word and how often.

$ ern build findex.ern
$ printf 'cat\n' | ern run findex.erc data 4
cannot list data/closed: Denied
not text, skipped: data/blob.bin
Findex.startWorkers:222 faulted: cannot read: Denied
failed: data/locked.txt: cannot read: Denied
indexed 4 files, 21 words; 1 not text, 1 failed, 0 overdue
cat:
  2 data/cat.txt
  1 data/pets.txt

Where the language made the program harder to write went into the release review, and from there into the report, the guide, and the plan.