Sometimes, there are moments when you feel loosing control over your life, when there is to much on a plate and all this overwhelms you, makes you anxious. For me, solution always was to use kind of "get things done" tools, to organize myself. I tried various todo apps, even bought a paper todo, but this wasn't enough this time. Every restriction in functionality, every missed feature made me feel I'm loosing control again. And one moment I gave up and decided it is time to make my own tool and make it right (in my understanding), i.e a todo that is highly customazible and instead of hardcoded features can have any you want. Despite todo is an anecdote and there are thousands of them, same as with an edit tool https://devblogs.microsoft.com/commandline/edit-is-now-open-source/ it is quite a challenging task to make a good one.
# Design/Concept
Luckily, I had 2 weeks of winter holidays and I decided to invest this time into a project. I thought a lot on how to make a todo that potentially have any possible feature that anyone can simply add just when they need it. My solution was a Virtual Machine with persistent storage + Tasks that have their own executable instructions. So in this design any todo app could be a simple wrapper around i/o and all functionality would be powered by the VM.
# Problems/Complexity
Creation of a working VM is a complex task for sure. I will not mention every problem I faced during last months, but will just list some features I implemented to solve them:
- NaN-boxing — All stack values are 64-bit (u64) encoding 6 distinct types (Null, Boolean(TRUE_VAL,FALSE_VAL), STRING_VAL, CALLDATA_VAL, U32_VAL, MEM_SLICE_VAL (offset: 25 bits, size: 25 bits)).
- InlineVec — Fixed-size array-backed vector implementation used for stack, control stack, call stack, and jump stack with specified limits.
- Dynamic Memory/Heap — growable Vec heap, memory slices use 25-bit offset and 25-bit size fields (limited by MEM_SLICE_VAL).
- Definite Loops — DO…LOOP 2 nested loops only possible for now.
- Conditional jump - IF..THEN 2 nested IF..THEN statements only possible for now.
- Custom binary encoding/decoding implementation.
# Current state
My Virtual Machine is still in it's early days and may miss some important instructions, but it can be already used for a todo app demo with programmable tasks. All operations — from simple CRUD to the tasks' own instructions — are executed by the VM. The concept is, that any kind of automation or workflow can be enabled by task instructions executed by the VM, rather than hardcoded functions in the app - exactly what I wanted to achieve initially! There are 4 demo task instructions that are not a part of the todo code, but instead are in toml file which could be updated any time with a new one:
- chain - Creates next task once when another is completed. Removes calldata after call - called once
- either - Sets complete if either one or another task is completed + deletes not completed task
- destructable - task self destructs when it’s status set to complete
- hide - Keeps task hidden while specified task’s status is not complete.
https://github.com/tracyspacy/spacydo/tree/main/examples/todo
When I added the todo example, I realized, that the originally hardcoded states in the VM were a limitation. If I would make them generic (which I did), the VM would serve more than just todo apps: new use cases such as tasks orchestration and even state machines became possible. I added a finite state machine primitive example as well - a traffic light - where task is a simple state machine which has own state transition rules in executable calldata.
https://github.com/tracyspacy/spacydo/tree/main/examples/traffic_light
I'm still working on this project alone and struggle to get other people involved to help me stabilize and finalize the VM.
Anyway, this journey is interesting and insightful, and I'm curious what comes next.