tilts at the windmills of programming
blog logic puzzles piward coding the-bonfire
github profile
𝟙𝟜· Periodically, I tell myself I'm going to alternate exploratory coding (aka hacking) with a phase of refactoring toward a clear design (aka cleanup). The problem is
the clear design phase may never happen - it's too easy to be satisfied with code that passes the current testing, however informal. On the other hand, it's easy to
overcommit to a clear, elegant design, and if it doesn't meet some of the goals set for the project, it can be a major issue.
I'm here again, thinking my solo recreational coding would be more fun if I took time to consolidate what I've learned into a good design. Process options are plenty,
but I probably can't master the discipline of most - e.g. separate branches for exploratory phases seems heavy handed on a solo project. Alternating priorities always
𝔽 feels like the best thing to try, but I usually can't stick to it - maybe that ADHD diagnosis isn't so far off...
𝕖
𝕓 Of course, AI assistance is becoming standard practice, and beyond quickly finding simple mistakes, it can refactor efficiently and even take part in a friendly chat
𝕣 about what the plan is. The increases in productivity, even if human programmers end up only in a code review role, is hard to resist in business.
𝕦
𝕒 But I'm programming because I enjoy it. Algorithmic assistance is great, as long as I could have a hope of understanding the algorithms being used. Maybe I could
𝕣 figure out how LLM's work, but the current systems are massive, remote black box servers - which isn't part of the fun for me. The fun is opening the black boxes and
𝕪 figuring out what's going on inside.
𝟘𝟞· Woof! Slow progress... ⟪Sapphire⟫ has both logic and domain variables - a named value which may be left unspecified, given a value as assertions are simplified and
resolved. Both ‘x=3’ and ‘3=x’ mean the same thing - as an assertion it is resolved in ⟪Silver⟫ if ‘x’ evaluates to 3, but if something else, a contradiction is
flagged. If x has no value, ⟪Silver⟫ resolves the assertion by assigning 3 to x. For finite problems, functions and relations can be treated as domain or logic
variable spaces, respectively. To dig myself out from under earlier hacks, I'm rewriting things around what I'm calling ‘free order variables’ for now, which are just
⟨key table⟩ pairs, replacing constrained expressions with, in theory at least, nested function calls...
𝟚𝟝· Changes are settling and maybe my OCD will give me a chance to work on something else for a bit. Between making these changes too haphazardly and global distractions,
everything else has been suffering neglect. A pause, then forward on Slitherlink puzzles and, hopefully, some graphics fun!
𝕁 𝟚𝟛· The transition to treating constraints as a class of ⟪Iron⟫ Interpreter internal values has been... slow. I make a mess when I'm exploring to find a solution or
𝕒 implementation that works and meets my design goals. Breaking changes are a time to consolidate the current design before going forward... I was too focused on
𝕟 getting to the next exploration - constraints as first class values, and, well, messed up.
𝕦
𝕒 𝟘𝟡· I often pass keyword parameters to a subroutine unchanged, and ended up with alot of ‘keyword=keyword’ code in Python function calls. Reserving ‘=’ for the equality
𝕣 predicate (I just replace ‘=’ with ‘==’ when generating Python or C) I instead use ‘→’ to pass keyword parameters - ‘keyword→7’. I added a postfix operator ‘→←’ to
𝕪 pass the value of the variable as the keyword, so I can abbreviate ‘keyword→keyword’ ·as ‘keyword→←’.
𝟘𝟠· I've been on a side trip to additional ‘rational’ code generation based on syntactic analysis rather than ad-hoc text manipulation. This next stage let me translate
operators (‘⊗’ and ‘⊙’ for cross and dot-product) into calls to generic functions, but there's more work to make it remotely robust.
𝟛𝟘· I've been bogged down by my bootstrapping shenanigans. I finally decided to re-execl the current build when cyclic dependencies could change generated code. Because
I'm building my tools in place, I use a “revert-bootstraps” routine often to deal with all-to-frequent breakage.
𝟚𝟠· More language infrastructure progress - I've got code generating from the ⟪Violet⟫ language layer that bridges between ⟪Cobalt⟫ (aka C) and ⟪Midnight⟫ (aka Python). I
generate code that uses Python's ‘ctypes’ module to call C from Python, making it easy to mix and match implementations.
𝟚𝟞· I took a small step toward sensible language handling by generating a full parse tree for a small input file. Starting life as a no-op, my evolving ‘zypp’
preprocessor converts ⟪Midnight⟫ and ⟪Cobalt⟫ to Python and C, respectively, in an entirely ad-hoc fashion. At least I know I can create an inviting bug hotel.
Eventually, each language layer I use will share a unified parser, but different intermediate code generators which will perform first level semantic checks. The
intermiedate language will support high level primitives that can be lowered to target subsets which can be used to emit code. My ⟪Sapphire⟫ project has a good deal
of infrastructure to cope with.
𝟚𝟚· I'm using ‘⊙‘ for dot product and ‘⊗’ for cross product. My preprocessor translates these from binary operators into calls to ‘dot’ and ‘cross’, which are native in
GLSL and implemented in Python to work on number sequences of equal length (dot) or only 3-tuples of numbers (cross).
𝟚𝟚· While I use Unicode extensively and appreciate its near universal adoption and support, I object to any description of it as a “character set”. It is far closer to
Donald Knuth's TeX than an encoding of an alphabet.
𝔻
𝕖 For computing, a “character set” is an encoding of an alphabet - essentially, the association of an integer with each of a finite set of symbols. The symbols have
𝕔 associated perceptual representations (visual, auditory, tactile) that allow human beings to associate differeent sequences with different meanings. If we remove
𝕖 control values from Unicode (modifiers and typesetting indicators) and discard codepoints whith glyphs similar to those of lower codepoints, we are left with a
𝕞 workable character set. We'd also like human beings to naturally associate meaning with words to form human readable language.
𝕓
𝕖 The maximal character set subset of Unicode overdelivers for the vast majority of human beings. Perhaps it will change over time, but only a portion are recognizable
𝕣 to many of us - my dinosaur DNA seems irreperable. This intentional inclusiveity is a key feature of Unicode, but to be complete, it requires typesetting features.
And bidirectional text is a mess for formal languages. When we see at 1÷2 we have to look at the surrounding characters to know if it's the same 0.5 (e.g. A 1÷2 A) or
2.0 (e.g. א 2÷1 א). Or is that really 5.0? Bidirectional overrides are only discouraged, so we can't really tell if AND is A→N→D or A←N←D (the same as D→N→A) by
looking. Since my editor (Emacs) seems to follow unicode rules, editing שרה means when I move the cursor to the right, it goes left! Further, these identically
encoded arrows all point right, A→N→D, ש→ר→ה, indicating first to last for Latin and last to first in Hebrew. Is it better that the middle right paren A)A is the same
as this middle ש)ש left paren (they're both encoded as hex 29). With A₁ vs א₁, Emacs does the Unicode thing... oh yeah, the mathematical aleph is different: I use ℵ₁
when I print the size of a countably infinite subset of ℤ.
The mathematical typeface variations of the latin alphabet are really great for presentation (I display ℤ when I know Z represents the integers) but frustrate when
trying to make auditory distinctions.
So I (internally) use my own (still evolving) “Zy Logical Character Set” aka “Zylch” (the "zy" is vestigial, but still makes for entertaining acronyms) for formal
languages. It's a single byte encoding that starts with the digits 0⋯9, followed by the 26 uppercase then 26 lowercase letters of English. Digits, including hex, are
represented with their own value! Then a bunch of symbols that change from week to week... Again, dinosaur brain, and it works for what I'm playing around with. [last
edited 2026-01-18]
𝟚𝟙· I updated my color text routines that I use in all my Python tools to proceess faster when read into Emacs. One day, I may create an IDE for my ‘neo-retro’
logic-puzzle computing environment, but Emacs is still the best tool for me.
1 𝟭 𝟙𝟘· For my symbolic logic projects, I'm organizing my code around a division between the abstract for logic and concrete programmer-centric domains.
𝟵 / 𝟙𝟘· The git ‘index’ is like a little mini-commit zone. I backup my bare git repositories regularly but by incrementally diffing and reviewing changes using the index
feels lighter weight than a commit, and not atrisk of being pushed or fetched by accident on my test machines.
𝟲 / 𝟙𝟠· I've been enjoying Python's tremendous flexibility but am converging, with support from a preprocessor, on a consistent style. Once things are stable enough to focus
on performance, I'll use my preprocessor to target a mix of C or C++ and a more performant runtime than the standard Python interpreter.