tilts at the windmills of programming
blog logic puzzles piward coding rec-math the-bonfire
github profile
β•­ πŸ™πŸ™Β· 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.