Parasol’s roadmap
Frozen on 2026-09-15. Its open entries were carried to Solveig’s roadmap that day as 7.1 to 7.10, and a line stands where each one was; what is kept here is what was settled on this page, the retractions and the refusals, and the plan that made Parasol a member of the toolkit, as the record of how. Nothing is appended below this note.
What is still outstanding, and what has been refused. Each entry says what would have to be true before it is worth starting.
The work that is finished is in two places: CHANGELOG.md names what landed and the commit that carried it, and COMPLETED.md keeps the case for each piece as it was argued before the work — the problem, the options, and why the shape chosen was the one taken. What went wrong on the way is in POSTMORTEM.md; what a day consisted of is in journal.md.
Two items on this page have been declined by a customer rather than by argument, which is worth more than either, and one has now been taken by one. See Settled by a customer at the foot of COMPLETED.md.
lib/arith.psol’s missing <=, >= and != left this page on 2026-09-02.
It is the entry the one customer is not enough rule was written down against,
and how it closed is worth carrying. programs/prose wanted <= and wrote
while i < doc:size + #1 around it; programs/basic wanted <= and >= five
times and != four. That is two customers for <= and one each for the other
two, so the bar was met for one of three and the family went in whole.
The rule was applied and not bent. An arith with <= and no >= is a worse
trap than an arith with neither, the missing one being missing for no reason a
reader can see. What the case actually shows is that a customer count is per
surface, and a comparison set is one surface — which nothing had had to decide
before. lib/arith.psol carries the argument at the declarations, and both
customers were rewritten to use them the same day, which is the check that the
customers were real.
Open, and undecided
The version entry stood here, and was carried to Solveig’s roadmap as 7.1 on 2026-09-15, the day this page froze. The plan below stays, being the record of how the move was made; what is left of it is 7.1 and 7.2 there.
A member of the toolkit, not a guest. Hans’s direction on 2026-09-14,
said while asking for --sob and held apart from it: that Parasol should in
time be a permanent member of Solveig’s tools rather than an experiment
lodged in its tree. Concretely, its C source laid out as solas/, solid/
and the others are, parasol/{cmd,include,src} at the root instead of
parasol/parasol/; its documents, Makefile, examples, library and tests
folded into the tree’s own, or as near to it as their jobs allow; one way to
build and to test and to install, so that working on Parasol feels like
working on the other four and using it feels like using them. The point is
as much the feeling as the layout: not some outside experiment any more,
in his words. Not now, and --sob was built so as not to depend on it,
which is why it runs solas and does not link it. The entry above is this
one’s first step and its gate: the version question decides dist and
install, and those decide the Makefile, and the Makefile decides where the
sources can sit. What would have to be decided on the way, in the order they
bite: one version for the tree or two; whether docs/programs.md’s counts
take Parasol’s documents in or keep them out, since a docs/ file is
counted and parasol/docs/ is not; what the no dependencies sentence on
Solveig’s front page says once the compiler that emits its source is in the
same make; and whether the Makefile’s first sentence, the build needs no
Solveig, survives as a check on a merged build, since it is the sentence
the experiment stands on and the move would be the moment it is easiest to
lose. What would fire it: the version decided, or a third contributor
finding the directory before finding the tools.
The version was decided the same evening, and Hans asked for the order.
Five steps, each leaving both suites green and the tree usable, each its own
day or less, and ordered by what each one needs from the one before it. The
rule for the order: move what the checker cannot see first, and the
documents last, because docs/ is counted, programs/expect.sol runs
what is fenced there, and the documents should describe the final layout
and be written once.
- Version, at the next Solveig release:
PARASOL_VERSIONbecomes the tree’s, without an include, so either a line in releasing.md beside the four files or a-Dfrom the Makefile;PARASOL_SOLVEIG_MINIMUMremoved;distremoved here, the root’s tarball of HEAD already holdingparasol/. Small, and independent of the rest; it is first because the roadmap said it gates the Makefile, and it does. - Makefile. Parasol’s rules move into the root’s under a section of
their own, paths prefixed
parasol/;check,SOLVEIG=andmake -C parasolgo, sincesolasis built by the same run; onetest, oneinstall(bin/parasolbeside the four,lib/*.psolunder the samePREFIX), oneclean. The claim the separate file kept mechanical is kept mechanical another way: aPARASOL_INCLUDESof-Iparasol/includeonly,bin/parasollinked againstlibparasol.aonly, and a check in the suite that no file under Parasol’s C source includes asolum/,solas/,solis/orsolid/header and thatbin/parasolexports nosol_symbol. The comment moves to the rules and says which experiment it is guarding. This is second because every later step is tested by the merged Makefile, and doing it once means every later path edit is in one file. Done, 2026-09-14, the same evening. The include check turned out not to need a grep: the compile rule is the check, since a Parasol object is built with Parasol’s include path and no other, and a probe file with#include "solum/common.h"was seen to fail. The symbol check isnm -goverbin/parasolintest, seen to matchbin/solasand notbin/parasol. One thing the scoping did not know: GNU make 3.81, which macOS ships, takes the first matching pattern rule rather than the shortest stem, so the Parasol section sits above the generic object rule and says why.sanitizeandexamplescame to the root as targets for the whole tree;runandcheckwent; the dialects install beside Solveig’s library rather than under a directory of their own, so that step 4’s look beside the binary finds one place. Parasol’sdistwent with the file, a release early. - The C source and its tests.
parasol/parasol/{cmd,include,src}toparasol/{cmd,include,src}, laid out assolas/is, bygit mv;parasol/tests/*.ctotests/, none of the five names colliding. One thing to decide there: root tests linklibsol.awhole-archive and these linklibparasol.a, so either every test links both, which is harmless and simplest, or the five keep a prefix or a subdirectory. A pure move with no checker involvement, which is why it is third and not fifth. Done, 2026-09-14, the same evening. Both halves of the decision, as it turned out: every test links both libraries under the one rule, and the five carry the prefix,tests/test_parasol_reader.cand so on, because atest_mapor atest_useamong forty Solveig tests would say nothing about whose map or whose@use. The rule linking both is not a hole in the boundary, which is about whatparasol/is built from; a test is a check on it. The Parasol documents had already been namingparasol/src/emit.crelative to their own directory, and from the root those paths are simply true now. One defect found on the way and fixed:test_useremoved the files it wrote from a hand-kept list that was seven short, sormdirfailed quietly and fifty-five of its directories were in/tmp; it reads the directory now. - Examples, library and programs.
parasol/examples/*.psoltoexamples/andparasol/lib/*.psoltolib/, no names colliding; the root.gitignorelearns*.sol.mapand ember’s*.sand*.out(a generated.solbeside a hand-written one is the trap here, and the ignore rule cannot tell them apart by name: the Makefile’s.SECONDARYand a naming rule for generated files decide it).parasol/programs/*toprograms/, wherebasiccollides with the SolaBasic corpus already there and one of them is renamed, Hans’s call which. With the library inlib/,parasollearns to look beside its own binary the waysolasdoes, soPARASOL_PATHbecomes whatSOLUM_PATHis, a fallback rather than a requirement. programs.md counts.solfiles inprograms/and says nothing underparasol/is counted; seven directories of.psolarriving there is a decision for that page, a section of their own or a second count, and it is taken in step 5 with the page. Done, 2026-09-14, the same evening. The naming rule the scoping reached for was not needed: everythingparasolgenerates goes underbuild/,build/examples/andbuild/programs/<name>/, which removes the trap rather than labelling it, and for a second reason found on the way that decided it alone:programs/expect.solreads everyexamples/*.solas a file of claims, and a generated one, whose; #14comments are that syntax exactly, would have been counted and checked as documentation.parasol/.gitignorewent with it.basicbecameminibasic, Hans’s choice of the two names put, the files inside renamed with the directory.parasollooks beside its own binary now,bin/../liband thenPARASOL_LIB_DIRfrom the generatedconfig.h, so@use "arith.psol"works from anywhere in a checkout or an install andPARASOL_PATHis the override it is forsolas.docs/programs.mdsays in a paragraph that the seven are there and not counted, ahead of step 5. -
Documents. Fifteen files, six of which collide by name with the root’s:
CHANGELOG,COMPLETED,GRAMMAR,journal,REFERENCE,ROADMAP. Two shapes: fold each into its root counterpart (the journal interleaves by date, the roadmap and completed become sections, the changelog merges once the version is one), or keep them whole under a prefix or adocs/parasol/. The first is the one that says member; the second is cheaper and keepsPOSTMORTEM.md, which the root does not have and says it should not. What every file pays on arrival:docs/programs.md’s counts move;expect.solruns fenced code, and a.psolfence needs a way through, for whichparasol --sobis now the obvious one, the first customer for it the day after it was built; the commit hashes in the changelog verify, since the history came in with the directory; relative links change. Also on this step: the rootREADME.mdrow andCLAUDE.mdparagraph that describeparasol/as a subproject,editors/vscode/messages.py, which readsparasol/docs/REFERENCE.mdby path, and the published site’s index. Last because it is the most entangled with the checker, the least in the way of using or developing the tool, and the step that should describe the layout the four before it made.Scoped on 2026-09-14, after step 4, in five sub-steps, each leaving the suite green. What the scoping found that the paragraph above did not know: Parasol’s pages hold about 150 fences with no language word, and
expect.solruns every such fence as Solveig, so a page cannot move intodocs/until each fence is either tagged or checkable; the house convention for a sub-language’s pages is already set bySOLABASIC.md,SOLABASIC-REFERENCE.mdandSOLABASIC-CHEATSHEET.md, flat indocs/under a prefix, where adocs/parasol/subdirectory would be read by the checker for links and for nothing else (true when written; since sub-step 1 the checker walksdocs/to the bottom, and a subdirectory is read for everything); every one of Parasol’s changelog hashes resolves in this history; the two LICENSE files are identical; andsolas/,solum/hold C and nothing else, which is whatparasol/becomes. And a reason to do it at all that step 4 supplied: forty-four links in the program READMEs and Parasol’s own pages were left pointing at the wrong tree or at nothing by the move, and the suite stayed green, because none of those pages is one the checker reads.- The checker first.
expect.sollearns aparasolfence: the block goes throughparasol --sobandsolvm, and its; #14claims are checked as asolblock’s are, so Parasol’s examples in prose become claims rather than pictures. The same change makes the checker read everyREADME.mdunderprograms/, so the forty-four cannot happen again. Its own step because it can be built and proved against the pages where they are now, before any of them moves. Done, 2026-09-15,ad4e33e. Three things the scoping did not know: the five.psolexamples carried 23 claims thatmake testran and never read, and they went in with the fence, four of their comments in the convention the checker dropped on 2026-09-01; a directory subject is now walked to the bottom, which is what put the READMEs in the set and is what makesextensionscheck anything; and the pages as they stood produced 3 findings under the checker, not 150, because a bare fence with no claim in it is quiet. The tag for a Solveig block is no tag, as everywhere else indocs/; thesolbelow was never one the checker read. - The reference pages.
REFERENCE.md,GRAMMAR.mdand the front page (parasol/README.md, 794 lines, withwhat-is-parasol.mdread against it, since the two overlap and one should become the other’s section) todocs/PARASOL.md,docs/PARASOL-REFERENCE.md,docs/PARASOL-GRAMMAR.md; every fence taggedparasol,sol,shortextas it is read; the<!--count-->markers re-synced; the editor’smessages.pyrepointed; the site’s nav given a Parasol entry. The pages a user reads, first, because they are the ones that make the tool feel like a member. Done, 2026-09-15. The front page andwhat-is-parasol.mdbecame one: the four questions that explain the tool are a section ofPARASOL.md, How it works, as it was asked, and the first, a status answer at 0.9.0, is not, its items being here.pipeline.htmlwent with them asPARASOL-PIPELINE.html. Thirty-three fences on the front page: eightparasol, of which one carries a claim and is checked, and the resttext, since a fragment that declares&&and uses>is a picture. Why it is not a folder inside Solveig is Why it takes nothing from Solveig now, the argument unchanged and the first paragraph saying where the distance went. - The essays.
does-it-pay.md,second-reader.md,rules-and-logic.md,targets.mdunder the same prefix.conventions.mdis Parasol’smethod.md: the agreements that survive being one project (predictions before a program, a claim about cost measured, a new check run against the unfixed compiler from a clean build) go intomethod.mdwith their occasions, and the ones that were about being a separate repository are retired with a line saying so. Done, 2026-09-15.solveig-notes.mdwent with the essays rather than waiting for sub-step 4, asPARASOL-SOLVEIG-NOTES.md, and closing the log meant raising it: its four open findings are 3.23 to 3.26 on the root roadmap, each still reproducing, each pointing back for the account. Nine ofconventions.md’s rules are sections ofmethod.mdand two are second occasions of rules already there; five were retired, named in the section that says so. Every link toconventions.mdin the records lands on that section. - The records.
journal.mdinterleaves into the root’s by date, each section keeping its words;COMPLETED.mdbecomes section 7 of the root’s,7.1to7.19, numbers kept; this page’s open entries become section 7 of the root roadmap;CHANGELOG.mdbecomesdocs/PARASOL-CHANGELOG.md, closed at the version merge, with every later Parasol entry in the root changelog as today’s already are;POSTMORTEM.mdbecomesdocs/PARASOL-POSTMORTEM.md, kept whole, with the rootCLAUDE.mdsaying it is the record of Parasol’s defects up to the merge and that the rule against a root postmortem stands;solveig-notes.md’s open items go where they were always addressed to, the root roadmap or ideas, and the file is retired. Fourth because the records are read least and moved most carefully. - What is left in
parasol/.CLAUDE.mdfolds into the root’s as a paragraph;README.mdis gone by sub-step 2;LICENSEgoes, being the root’s byte for byte.parasol/iscmd,include,src, assolas/is. The memory notes and the rootREADME.mdtable row say so.
The calls that are the author’s, before sub-step 2: whether the records fold (sub-step 4 as written) or stay whole under the prefix; and whether
POSTMORTEM.mdis kept at all, since the root’s position is that predictions scored inideas.mddo its job. Both made on 2026-09-15, before sub-step 1, and neither is what sub-step 4 says above. The five records (journal,COMPLETED,ROADMAP,CHANGELOG,POSTMORTEM) go whole todocs/parasol/and freeze there, each opening with a note giving the date and saying that from it Parasol’s record is Solveig’s; nothing is appended below the note afterwards.CHANGELOG.mdends at 0.17.0, which is also the version line, and the root’s next release entry says Parasol joined there.POSTMORTEM.mdfreezes with the rest, its 33 entries readable and closed, and a Parasol defect after the freeze is scored in the root’sideas.mdlike any other; the rootCLAUDE.mdgets a clause saying the archived one was moved in and not created. Open items leave before the freeze, this page’s to the root roadmap, and each archived record ends with a line saying where its open matter went. The checker readsdocs/parasol/for links and fences both. Sub-step 3 is unchanged; sub-step 5 losesPOSTMORTEMand the interleave. - The checker first.
What is not in the plan: any change to what Parasol does. The driver, the reader, the expander and the emitter are the same before and after, and the only thing about the boundary that moves is which file states it.
Six entries stood here after the plan: grouping programs/ into kinds, a
logical xor, postfix operators, a hole’s kind with no alternation, a
template’s constants never folded, and a dialect that ends at its domain.
Carried to Solveig’s roadmap as 7.3, 7.9, 7.9,
7.4, 7.5 and 7.6 on 2026-09-15, the day this page froze.
Waiting on a customer — optional and repeated parts
The entry stood here, and was carried to Solveig’s roadmap as 7.7 on 2026-09-15, the day this page froze.
A selector built from a name hole
The entry stood here, and was carried to Solveig’s roadmap as 7.8 on 2026-09-15, the day this page froze.
Retracted
A form’s trailing hole swallowing what follows was written up twice as a
limitation and is not one. programs/ember reported it for postfix sends and
programs/grammar for infix operators, and both were the same mistake: a form
declared as a pattern when it was an application. A call ends at its closing
parenthesis and has no such behaviour.
The sketch of a fix that went with it – a trailing hole binding at unary
precedence, declared per form – described a feature nothing needs. It is not on
this page any more.
What the two programs really found is that choosing the shape wrongly is silent. A pattern where a call was meant parses, quietly takes what came after, and fails at run time in generated code if it fails at all. Nothing at the declaration can say otherwise, both readings being legal. The rule is now in GRAMMAR.md under Which shape a form should have, which is where somebody choosing one would look; it had been in a program’s README, which is not.
Not planned, and why
A dialect that changes the lexer. The line between a fixed token stream and
a declared grammar is where this design sits. An extensible grammar over fixed
tokens can still be parsed by something that has not run the file’s own
declarations, and every editor, formatter and grep downstream depends on that.
Forth and TeX moved the line and became languages no tool can read without
executing them. If it moves, it moves at the module boundary and nowhere else.
A @token directive binding a spelling to a named token was proposed against
this and refused in 0.9.0: it would not have crossed the Forth line, the header
still being read rather than run, but it crosses a nearer one — today any tool
can tokenise any .psol without knowing what a dialect is. The want behind it
was real and || answers it, by growing the fixed vocabulary rather than by
making the vocabulary declarable. That is the shape any future version of this
request should take. See COMPLETED.md 12.
A rule that begins with a nonterminal. Left recursion, and therefore an
expression grammar written in @syntax. The reader would have to guess,
ambiguity would stop being checkable by looking, and composition would stop
being safe – and the case that motivates it is already read from the precedence
table. rules-and-logic.md argues all three.
Emitting bytecode, or machine code. Parasol would then own the .sob format
and Solum’s instruction set, and reimplement what Solas already does. The one
thing it would buy — errors from Solas landing on Parasol source — the map buys
instead. targets.md works the question through, including what a
native back end would actually cost and why a program written in Parasol can
already emit anything it likes. --sob, since 2026-09-14, is not this: it
runs solas on the .sol it wrote and owns nothing of the format. The
smaller cousin, linking libsol.a and calling sol_compile_options on the
emitted text, was scoped the same day and put aside, not because it is large
(forty lines) but because it would make the Makefile’s first sentence false;
COMPLETED.md 19 has the two side by side.
@expr. Solveig’s fixed infix region is the special case of what @infix
generalises. Supporting both would be supporting two. Solveig drew its side of
the same line on 2026-09-14: the region is off there unless solas --expr
asks for it, on this sentence, and a .psol needs nothing.
A signed bare number — -3 rather than #-3. Solveig’s scanner gives the
sign to the number outside a @expr region and treats it as the operator inside
one. Parasol can have neither half. It has no regions, so it cannot be
context-sensitive; and it cannot simply take -3 as a literal, because then
a -3 stops being a subtraction in every dialect that declares -. A prefix
declaration is the only reading left, and #-3 — where nothing else can begin
with # — is why the integer keeps its sign.
This is the extensible-operator line arriving from a direction nothing had come
from: not a dialect wanting to change the lexer, but Solveig’s own number
syntax being uncopyable while Parasol’s operators stay declarable. It means
everything but operator is Solveig’s own spelling was never achievable, and
0.1.0 chose against it without recording that it had.
COMPLETED.md 15 has the whole survey — nine differences, seven
closed across 0.11.0 to 0.13.0, and this one and @expr left.
Rough edges
The list stood here, and was carried to Solveig’s roadmap as 7.10 on 2026-09-15, the day this page froze.