β
ππΒ·
coding I'm transitioning Cobalt to the same underlying parser I use for Midnight, which is also used for embedded GPU shaders in Cobalt code. Midnight is translated
β
to Python, Cobalt to C, shaders to GLSL (I'm bringing up graphics in OGL, to support Raspberry PIs with VideoCore IV hardware).
β
β
ππΒ·
coding Midnight is finally being properly parsed (if not perfectly) making Midnight a syntactic front end to Python! When I started, it was as an ad hoc text
π
β
replacment preprocessor, initially replacing operators like ββ¨β with βandβ or ββ©β with β&β. It slowly evolved to a point where I wanted to unify syntax with Sapphire,
π¦
β
my language based on formal logic. I translate simple constructs like:
π
β
πͺ
β
assert: l=βmdβ β lvl=10 --| assert not (l=="md") or (lvl==10)
β
β
if: βeβexpr[1β―] β¦integer-expr? eβ¦ --| if all(integer_expr_Q(e) for e in expr[1:]):
β
β°
which lets me write Python code with the same operators and syntax I use in Sapphire, which is what I use to write puzzle rules: Sudoku
β
ππΒ·
Text Regular Expression support is supplied by the Python module βreβ and, while elsewhere just called regular expressions, or abbreviated as βregexesβ, are properly
β
called "T-Rexes" and properly abbreviated as βrexβ. Thus the Python re module is referred to as βPyRexβ in βͺMidnightβ« code, which still uses the Python runtime.
β
runtime.
β
πΈ
β
ππΒ·
Added an enable to fully parse βͺMidnightβ« and generate Python code from the result, which replaces the text preprocessing that started with replacing Unicode ββ§β with
π‘
β
β and β. I still have some glitches that can appear when I switch it on for a file, but the process was made pretty smooth because not only was I already parsing
π£
β
selected constructs (triggered by certain non-ascii operators) I added a pre-commit βlintβ step for files that had been cleaned up a bit. That started a month ago
π
β
with a "don't crash the parser" check, then loading it into Python, but not running anything, and finally using pylint. I turned off a ton of stuff that didn't matter
π
β
to me, but left on style warnings caused by inconsistencies in my βͺMidnightβ« code.
β
β
I can do more with the silly things that my brain like, like operator and syntax variations, and run into fewer problems. I can use ββaβaints a.stored-rangeβ instead
β
of βall(a.stored_range for a in aints)β. Why some much work for something so... trivial? Silly? Even, dare I say it, dumb? Aside from being my idea of fun, being able
β
to use the same syntax in βͺMidnightβ« that I use in βͺSapphireβ« - where this would be an assertion over as yet undefined objects - lets me use the same constructs,
β°
mentally and in code.
β
ππΒ·
I'm taking steps toward a Python-free future, but I'm bringing as much good stuff forward as I can - at least the good stuff related to my βͺSapphireβ« project. My plan
β
for a uniform parser and an internal representation of Lisp-like sexpressions is coming together.
β
β
Python's reflective features aren't necessary, so I'm considering using libgccjit when I need to generate code on the fly, possibly for static builds, although
β
generating textual C code is an easier place to start.
π
β
π
β
ππΒ·
Ugh. Struggling to extend ideas from the AC-3 algorithm to a complete finite Constraint Satisfaction Solver without resorting to direct search. The reason is my
π£
β
interest in symbolic approaches which I hope to apply to very large problems and even infinite domains. It may not be doable, but for the time being I've been playing
π
β
with generalizing the notion of variable in AC-3 to potentially overlapping variable vectors.
π
β
β
AC-3 prunes away at an explicit representation of each variable's range by eliminating values which are not consistent with all constraints. When a the range of a
β
variable is reduced, the constraints it participates are re-examined in turn, possibly reducing the range of one or more other variables. For the AC-3 algorithm to be
β
helpful, the primary constraints are local, applying only to a subset of variables. The constraints can be locally but not globally satisfied when AC-3 terminates.
β
β
Variables can be combined - a vector variable with a range of vectors; explicit storage of those compound ranges can be similarly pruned, extending the AC-3
β°
algorithm. The approach to chosing combinations for the lower end of time and space requirements is what I'm up against.
β
ππΒ·
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.