IMPORTANT NOTE: management of list has been migrated to an external task tracker as of February 2023. This historic "one-person tracker" remains as reference, and its contents are not authoritative or up-to-date.
[x] Rendering
[x] Components
[x] Logging
[x] Stroke, color, fill
[x] Sizing
[x] Browser resize support
[x] None-sizing
[x] Transform.align
[x] Transform.anchor
[x] Expression engine
[x] variables, declaration & storage
[x] node IDs
[x] summonables
[x] built-in vars like frame count
[x] MVP rust closures + manifest of deps
[x] Stackers (née Stacks)
[x] Decide `primitive` vs. userland `components`
`components`
[x] Internal template mechanism for components
[x] Make `root` into a component definition
[x] Control-flow `slot` (`slot`) for inputs/children
[x] Ensure path forward to userland `slots`
[x] Clipping & Frames
[x] Control-flow `repeat` for cells & dividers inside template
[x] Gutter
[x] Split out userland code
[x] Add a third project to workspace, the sample project
[x] (Further work to be done via compiler task)
[x] Timelines, transitions
[x] Refactors
[x] Bundle Transform into "sugary transform," incl. anchor & align; consider a separate transform_matrix property
[x] Is there a way to better-DRY the shared logic across render-nodes?
e.g. check out the `get_size` methods for Frame and Stacker
[x] Maybe related to above: can we DRY the default properties for a render node?
Perhaps a macro is the answer?
Same with `scale`
[x] Can we do something better than `(Box<......>, Box<.......>)` for `Size`?
[x] Rename various properties, e.g. bounding_dimens => bounds
[x] Take a pass on references/ownership in render_render_tree — perhaps &Affine should transfer ownership instead, for example
[x] Better ergonomics for `wrap_render_node_ptr_into_list`
[x] Evaluate whether to refactor the `unsafe` + PolymorphicType/PolymorphicData approach in expressions + scope data storage
[x] decide on API design, expected GUI experience
- Direction (horiz/vert)
- Gutter
- Cell widths
[x] expose a Stacker element for consumption by engine
[x] accept children, just like primitives e.g. `Group`
[x] author an internal template, incl. `slot`ing children and `repeating` inputs
<Frame repeat=self.children transform=get_transform(i)>
<Slot index=i>
</Frame>
- need to be able to define/call methods on containing class (a la VB)
- need to figure out polymorphism, Vec<T> (?) for repeat
- need to figure out slot — special kind of rendernode?
[x] Frame
[x] Clipping
[x] Slot
[x] Repeat
[x] "flattening yield" to support <Stacker><Repeat n=5><Rect>...
[x] scopes:
[x] `i`, `datum`
[x] braced templating {} ? or otherwise figure out `eval`
- Code-gen? piece together strings into a file and run rustc on it?
* Can achieve this with Expressions for now
[x] calling "class methods" from templates, e.g. <Repeat n=5><Rect color="get_color(i)"
* Can achieve with expressions
[x] Scopes & DI
[x] Figure out dissonance between: 1. string based keys, 2. struct `Properties`
and figure out how this plays out into the property DI mechanism. Along the way,
figure out how to inject complex objects (ideally with a path forward to a JS runtime.)
- Option A: write a macro that decorates expression definitions (or _is_ the exp. def.) and (if possible)
generates the necessary code to match param names to elsewhere-registered dependency streams (Angular-style)
- Option A0: don't write the macro (above, A) yet, but write the expanded version of it by hand, incl. string deps (present-day approach)
^ to achieve "DI," does this require a hand-rolled "monomorphization" of each expression invocation?
Or does a string dependency list suffice? If the latter, we must solve a way to pass a data-type <D> through PolymorphicValue
Probably the answer is the _former_ — write the DI-binding logic manually alongside a string dep list (roughly how the macro unrolling will work)
[x] Support getting self (or Scope) for access to Repeat Data
- use-case: translate each element within a `repeat` by `i * k`
[x] Quick pass on other relevant data to get from Scopes
[x] Layout
[x] Primary logic + repeat via expression
[x] Parameterize:
- Gutter
- (come back later for overrides; ensure design supports visual UX)
RIL means Rust Intermediate Language, which is the
"object code" — i.e. compiler backend target — for Pax. As the name suggests, RIL is valid Rust
(specifically, a subset of Rust.) Pax relies on
rustc
(via cargo
) to convert RIL "object code" to machine code.
[x] Compile base cartridge
[x] Refactor PropertiesCoproduct to its own module
[x] Sanity check "patch" ability for "blanks" (Properties, Expressions)
[x] Demo app chassis running example project (`./serve.sh`)
[x] Add stub macro for `pax`, derives
[x] baseline primitive(s) for hello world
[x] import/package management
[x] RIL -> PAX compatibility, port primitives
[x] Repeat, path from @foreach
[x] hand-write RIL first!
[x] Handle control-flow with codegen
[x] support with manual RIL, port old primitives
[x] @for
[x] syntax
[x] with/out enumeration (`i`)
[x] figure out scoping, e.g. addition of symbols to namespace, collision management
[x] RepeatItem: manage scope, properties
[x] @if
[x] slot
[x] frame
[x] rendering hello world
[x] proof of concept (RIL) for expressions
[x] handle expressable + nestable, e.g. Stroke (should be able to set root as Expression, or any individual sub-properties)
[x] proof of concept (RIL) for timelines
[x] running on assumption that the problem is isomorphic to the Expression vtable problem
[x] proof of concept (RIL) for actions
[x] pax_engine::log
[x] `Tick` support (wired up)
[x] pencil in `Click`, but don't worry about raycasting yet (or do naive raycasting?? easy to PoC!)
[x] sanity-check Repeat
[x] port Repeat, etc. to latest RIL
[x] API cleanup pass
[x] make consistent Size, Percent, Anchor, Align
[x] finish-line @if
[x] support in-.rs-file pax, as alternative choice vs. code-behind file
[x] Spend some cycles ideating demo deliverables/storyboard
[x] Port Stacker to be a pure component
[x] figure out importing mechanism for core and/or other std primitives
[x] Group, Slot (e.g. from Core)
[x] Frame (e.g. from std — though if easier could just move to Core)
[x] port stacker logic; design expression/method approach
[-] pure expressions + helpers?
[x] on_pre_render + manual dirty checking?
[x] decision: no dirty checking at all for right now; expose imperative dirty-check API only when implementing dirty checking for Expressions
[x] hook in existing layout calc logic
[x] Import and use Stacker in Root example
[x] update example .pax as needed along the way
[x] "expand the proof" of generated code & make it work manually
[x] Action API
[x] state management (.get/.set/etc.)
[-] hooks into dirty-update system, to support expression dirty-watching
[x] Instantiation, reference management, enum ID + addressing for method definitions &
invocations
[x] tween/dynamic timeline API
[x] revisit chassis-web implementation
[x] rust/JS divide
[x] Sandwich TS and rust (as current,) or
[x] handle all cartridge work from rust, incl. generation of public API
[x] Event capture and transmission
[x] Map inputs through chassis, native events (mouse, touch)
[x] PoC with Web
[x] PoC with macOS
[x] tick event e2e
[x] Message queue in runtime
[x] Ray-casting? probably
[x] Message bubbling/capture or similar solution
[x] Expressions
[x] Write ExpressionTable harness, incl. mechanisms for:
[x] vtable storage & lookup
[x] Return value passing & caching
[-] Sketch out design for parallelized expression computation (e.g. in WebWorkers)
[-] Patch ExpressionTable into cartridge à la PropertyCoproduct
[x] resolve the `Any` question
[x] defer until later; reassess if it becomes clear a lot of backtracking is emerging
[x] parser
[x] grammar definition, PEG
[x] parse grammar into manifest
[x] grammar/parser updates:
[x] `@for`
[x] ranges: literal and symbolic
[x] `@template` block, vs. top-level
[x] native rendering ++
[x] message design/arch
[x] runtime de/serialization
[x] Data across FFI
[x] explore raw C structs (decided: brittle)
[x] Logging, strings, message-passing
[x] CRUD operations and methods: PoC with `Text`
[x] flexbuffers instead of fat c structs
- Might want to revisit one day for fixed schema, might reduce Swift boilerplate?
[x] ids
[x] handle monotonic, instance-unique IDs
- expose method in engine to generate new id
- initial use-case: instance IDs for associating engine <> native Text instances
[x] text support
[x] handle_mount and handle_unmount
[x] trigger mount/unmount lifecycle events in engine, `Conditional`, `Repeat`
[x] hook up Text primitive + API
[x] macOS
[x] web -- reattach with updated messaging model
[x] basic API pass: content, color, font, textSize
[x] handle dirty-checking for `Patch` event population
[x] native clipping support
[x] rectilinear-affine frames
[x] support macOS
[x] support Web
[x] click support
[x] simple 2D ray-casting
[x] Handle clipped content? and scrolled content? (i.e. check within accumulated clip bounds as well as object bounds)
[x] inbound event arg-wrapping and dispatch
[x] macos
[x] web
[x] sketch out bubbling/canceling, hierarchy needs
[x] dev env ++
[x] support for different example projects
[x] native macOS chassis + dev-harness
[x] pax-chassis-macos (written in rust). responsible for:
[x] accepting a CGContext pointer and rendering to it via Piet
[x] managing user input channel, e.g. click/touch
[x] managing native rendering channel, e.g. form controls, text
[x] mac app dev-harness (written in swift). responsible for:
[x] granting a piece of real estate (full window of simple mac app) to rendering with a CGContext.
[x] passing CGContext to pax-chassis-coregraphics
[x] handling resize
[x] handling basic user input (e.g. click)
[x] Debugging via LLDB
[x] support debugging as necessary with macos dev-harness
[x] IDE configs for each of: userland cartridge; core; std
[x] compiler + codegen
[-] codegen Cargo.toml + solution for patching
Note: decided to require manual Cargo setup for launch (solved by `generate` use-case)
[x] manual
[-] automated + file generation
[-] Note use-case: pax-std also needs the same feature flags + deps. Would be nice to automate!
[x] .pax folder
[x] manual .pax folder 'proof'
[x] codegen + templating logic
[x] generate `pub mod pax_reexports` via `pax_app` -- tricky because full parse is required to
know how to build this tree. Either: do a full parse during macro eval (possible! pending confirmation that parse_to_manifest can be called at macro-expansion time) or
do some codegen/patching on the userland project (icky)
(Tentative decision: refactor macro-time parse logic; probably do a full parse; return necessary dep strings along with pascal_identifiers)
Escape hatch if the above doesn't work: use include_str!() along with a file that contains
[x] Refactor parsing logic -- maybe start clean?
[x] De-risk: verify ability to call macro-generated code at compile-time (parse_to_manifest)
[x] Parse all of, recursively:
[x] Template
[x] Properties:
[x] Property key
[x] Property type, full module (import) path
[x] This will be tricky... either
[-] static analysis on the whole source file, looking for a `use ... KEYWORD` statement and infer paths
[-] dynamic analysis -- some kind of rustc API.....?
[x] dynamic analysis: `parse_to_manifest`-style `get_module_path`, called by parser
[x] parser returns fully qualified types in manifest by dynamically calling `get_module_path` on each discovered type during parsing
[x] refactor: punch `parser` features through all necessary Cargo.tomls — `impl PropertyManifestable` manually for `Size` and `Size2D`
[-] refactor: instead of `scoped_resolvable_types`, might need to `impl PropertyManifestable` for concrete nested generic types, e.g.
instead of Vec::get_property_manifest and Rc::get_property_manifest, Vec<Rc<StackerCell>>::get_property_manifest
-- this addresses compiler error `cannot infer type T for Rc<T>` (non-viable approach)
[x] Alternatively: hard-code a list of prelude types; treat as blacklist for re-exporting
-- note that this adds additional complexity/weakness around "global identifier" constraints, i.e. that as currently implemented, there can be no userland `**::**::Rc` or `**::**::Vec`
[-] Require fully qualified types inside Property<...>, like `Property<crate::SomeType>` or `Property<pax_engine::api::Color>`
[-] Make Property types `Pathable` or similar, which exposes a method `get_module_path()` that invoked `module_path!()` internally
Then -- `pax` macro can invoke `get_module_path()` just like `parse_to_manifest`
(Evaluated at compiletime) `Color::_get_module_path()`
^ wrong -- this would be evaluated at `parser bin`-time
Which returns `pax_runtime::api::Color`
Which gets codegenned into `pub mod pax_reexports`
Checksum: does this resolve at the right time
MAYBE we still need two phases: one that parses template and property types, which allows codegen of `get_module_path` and `parse_to_manifest`
and another that runs the parser bin
[x] Codegen`.pax/reexports.partial.rs`
[x] Basic logic
[x] Filter prelude
[x] fix bug: using `ctx` for property_manifests (maybe only a bug in primitives)
[x] Hook up primitives + types
-- possibly recycle logic that checks for `Property<...>`
[x] fix bug: prelude types not showing up in PropertyManifests
-- perhaps each propertymanifest should have:
-- fully qualified atomic types
-- for `pub mod pax_reexports`
-- for recursive calls to `get_property_manifest`
-- for TypesCoproduct generation
-- for cartridge codegen (imports)
-- In each of the above, it should be reasonable to handle prelude vs. imported types separately
-- Also: should this be called something else, like `dependencies` or `imports`? Instead of `PropertyManifests`.
-- What about `properties`? For design tooling, will definitely be necessary. Is it worth shimming `dependencies` into
-- maybe `get_property_manifest` should just be `get_property_dependencies` ??
[-] include_str!() `.pax/reexports.partial.rs` _at compile-time_ in macro logic
-- the goal is for this types re-export to be present at the root of the *userland project* by the time
the chassis is attached / compiled
[-] might need to "create if doesn't exist," or otherwise guard the lifecycle of the include_str! per best practice
-- a likely-viable approach: feature-gate two complementary `pax_app` macros, across binary values `is parser`
parser mode passes an empty string; prod mode assumes presence of .pax/reexports.partial.rs and hard-code-includes it
[x] solution: write another macro, gated behind `not(feature="parser")`, which gets
passed `env!("CARGO_MANIFEST_DIR")`
[x] parser bin logic finish-line
[x] macro
[X] untangle dependencies between core, runtime entities (e.g. Transform, RenderTreeContext, InstanceNodePtrList), and cartridge
[X] work as needed in Engine to accept external cartridge (previously where Component was patched into Engine)
[x] update .pest and manifest-populating logic to latest language spec
[x] support incremental compilation — not all #[pax] expansions (namely, side-effects) are expected to happen each compilation
[-] NOTE: provisionally, this whole group is solved as not necessary, in light of the "parser binary" feature-flagged approach
[x] science: determine how macros behave, caching of expansion, incremental compilation
[x] allow macros to report their registrants and the appropriate module path + file path via IPC
[x] sweep for files that have been removed from fs; update fsdb
[x] determine
[x] persist fsdb to disk, probably .pax/fsdb, probably binpack
[x] enable manual full rebuild, e.g. via `pax compile --full | --force | etc.` (should be doable via rustc with something like INCREMENTAL=0, refer to rust incremental compilation docs)
[x] architecture
[x] compiler seq. diagram
[x] dependency diagram
[x] two-stage compilation process
[x] thread/process/IPC chassis
[x] parser cargo feature
[x] bin-running harness to execute parser (see https://stackoverflow.com/questions/62180215/renaming-main-rs-and-using-with-cargo)
[-] TCP message passing (using stdio for now)
[x] de/serialization for manifest
[x] maybe normalize SelectorLiteralBlockDefinitions, if Serde can't elegantly de/serialize it
[x] or de-normalize TemplateNodeDefinition!
[-] coordination of TCP client/server from compiler main thread
[x] parse and load .pax files
[x] load file via macro
[x] generate the parser bin logic via macro
[x] manual
[x] port minimal set of std entities (Rectangle, Group) to support manifest-gen
[x] traverse manifest of Component defs: parse .pax files, store in mem
[x] (start with templates only)
[x] thread for wrapping `cargo build`
[x] sketch out .pax folder design
[-] graceful shutdown for threaded chassis (at least: ctrl+c and error handling)
[x] Alternatively: back out of async, given stdio for passing data from parser
[x] generate & embed reexports
[x] parse properties into manifest
[x] bundle pax_reexports into nested mods
[x] load reexports.partial.rs into userland project
[x] introduce `pax-cli`, import compiler to be a dep
[-] `pax demo`?
[-] `pax create`
[x] generate properties coproduct
[x] retrieve userland crate name (e.g. `pax-example`) and identifier (e.g. `pax_example`)
[-] alternatively, hard-code a single dependency, something like "host", which always points to "../.." (relative to ".pax/properties-coproduct")
-- don't think the above will work; cargo needs a symbol that maps to the target Cargo.toml
[x] patch / generate Cargo.toml
[x] include `pax-example = {path="../../"}`
-- where `pax-example` is the userland crate name
[x] PropertiesCoproduct
-- coproduct of ComponentName
[x] run through Tera template, iterating over dependencies
[x] TypesCoproduct
-- coproduct of all types from PropertyDefinitions
[x] if necessary, supporting type parsing & inference work for TypesCoproduct
[x] run through Tera template
[x] generate cartridge definition
[x] prelude / hard-coded template
[x] imports via `pax_example::pax_reexports::*`
-- or, fully resolve every import when using
[x] component factories
[x] `compute_properties_fn` generation
[x] `instantiate_main_component` generation, based on `pax_root` declaration
[x] `properties: PropertiesCoproduct::Stacker(Stacker {...})` generation
[x] PropertiesLiteral inline embedding vs. PropertiesExpression vtable id embedding
[x] fully qualified resolution of expression symbols, e.g. `Transform2d`
[-] Alternatively: don't support arbitrary imports yet:
[-] Support referring to `T` for any Property<T> (already parsed + resolvable)
[-] Import Transform2d::*, Color::*, and a few others via prelude
-- Note that each prelude import prohibits any other top-level symbols with colliding names; increases DX snafu likelihood via compiler errors
[x] expression compilation
[x] fully qualified resolution of expression symbols, e.g. `Transform2d`
[-] Alternatively: don't support arbitrary imports yet:
[-] Support referring to `T` for any Property<T> (already parsed + resolvable)
[-] Import Transform2d::*, Color::*, and a few others via prelude
-- Note that each prelude import prohibits any other top-level symbols with colliding names; increases DX snafu likelihood via compiler errors
[x] expression string => RIL generation
[x] Pratt parser "hello world"
[x] operator definitions to combine `px`, `%`, and numerics with operators `+*/-%`
[x] grouping of units, e.g. `(5 + 10)%`
[x] boolean ops: `==`, `&&`, and `||`
[x] parenthetical grouping `(.*)`
[x] Literals for strings, bools, ints, floats
[x] Nested object references + injected context
[x] invocations for deriving values from scope
[x] type-matching
[x] Numeric type management, type inference / casting
[x] QA
[x] fix: order / index of `vtable.insert` statements
-- ordering is jumbled
-- `3` is passed twice
[x] fix: import prelude types like Color::* so that `rgb()` and friends just work
[x] fix: duplicate invocation of `j` in `rgb(100 %, (100 - (j * 12.5)) %, (j * 12.5) %) `
[x] clean: remove "offset example" comment
[x] fix: tuples return usize(0) instead of Range()...
[x] fix: <<TODO>> for invocation of built-ins (either build built-in or refactor...)
[x] fix: need to fully qualify assc. fn. (helpers), e.g. a helper is currently called as `get_frame_size(` instead of `pax_reexports::...::get_frame_size()`
[x] generate / patch chassis cargo.toml
[x] control flow
[x] for
[x] parse declaration `i`, `(i)`, `(i, elem)`
[x] handle range literals 0..10
[x] shuttle data into RepeatInstance via Manifest
[x] if
[x] parse condition, handle as expression
[x] slot
[x] parse contents as expression/literal, e.g. `slot(i)` or `slot(0)`
[x] support inline (in-file) component def. (as alternative to `#[pax_file]` file path)
[x] e2e `pax run`
[x] publication to crates.io
[x] reserve pax-engine crate on crates.io
[x] update relative paths in all cargo.tomls, point to hard-coded published versions
- can include both a relative path & version number, a feature of Cargo for this exact use-case
[x] publish all crates
HIGH
zb [ ] hook up `pax_on` and basic lifecycle events
[ ] consider design for async while doing this
[ ] also requires hooking up `handler_registry` generation in cartridge
wj [ ] `Numeric` - "unlocks ability to multiply floats & ints"
[ ] Introduce wrapper around literal numerics
[ ] Build Into and From across expected primitive types (f64, usize, isize, etc.)
[ ] Implement necessary Rust operators (`Mul`, etc.), following "truth table" for conversions
[ ] Implement necessary non-Rust-builtin-operator operations, like `pow`, on Numeric directly
[ ] Refactor Size (maybe take on Color, etc. along the way) to accept numerics
[ ] Chase this thread through the engine, refactoring to support Numeric where necessary (e.g. inside Size)
zb [ ] (Crude) error reporting through CLI
[x] Parser errors (row, column and spatially local text)
[ ] Better ParsingError handling, at least surfacing only the line_col info without the noise
[ ] Stretch: explore a quick, friendlier error message PoC with "cascading errors in PEG" approach
[x] Chassis compilation error
[ ] Primitive source-maps
- MVP: pipe / output stderr correctly?
- Note: this only occurs during lib dev or when encountering a compiler bug in the wild
Due to the above, this may not be a blocker on alpha launch
wj [ ] "code-behind file" as alternative to in-Rust macro
[x] turn off codesigning for dev harness
[ ] docs pass
[ ] clean up codebase; reduce warnings
[ ] README pass & updates
[ ] update concepts, appendix articles
[ ] Consider writing guides:
[ ] Walk through building one or more examples (e.g. show reusable components, expressions, loops, lifecycle event handlers)
[ ] Pipeline of compiling a project
[ ] Writing a primitive
wj [ ] support `pax build` for distributable binaries (alternative to `pax run`)
[ ] at least web + production build; consider the codesigning question separately
[ ] interactive demos for docs, website
[ ] site
[ ] branding
[ ] content
[ ] audience, outline, etc.
[ ] demos
[ ] windows & linux dev envs
[ ] web target only
[ ] ensure e2e support & ergonomics
[ ] usability - high priority
[x] figure out spurious stroke / outlining on macOS (clear Piet context?)
zb [ ] solve pax-std feature-flagging / "roundup export" / raw coproduct memory access problem
[ ] either `pax_primitive_exports` at crate root for external crates — or raw memory access into coproduct
zb [ ] Patch in RIL generation for control flow — `Stacker` should work flawlessly, incl. `Slot` and `Repeat`
[x] Figure out how to fork process properly in macOS without requiring debug mode
[x] Fix native bindings / wasm compile issue (extricate pax-compiler)
[x] pax-compiler "cache" — sometimes changes aren't propagated to `.pax/chassis/MacOS` —
this is because the file copying logic for `include_dir` aborts when files already exist
a solution: manually walk `include_dir` fs and write each file, instead of
using their provided one-shot method
[x] Any easy wins for compile times?
[x] See if we can decouple pax-macro from pax-compiler — currently userland projects that rely on pax-macro thus rely on pax-compiler, which in turn has many dependencies and takes a long time to compile.
[x] pre-npm-install for web builds?
[x] package.json and Cargo.toml dependency cleaning; austerity measures
zb [ ] Refactor Color to accept percentage channel values; refactor Translate/etc. to support
[ ] Also design ideal re: constant access -- maybe
Color::Rgb(r,g,b) should be a literal enum after all? (instead of fn call)
This enables Color::Red() & other "constants" to live under the same symbol, `Color`
wj [ ] Introduce x= and y= values, separately from `Transform` (probably a last-applied Translate, in practice)
[ ] consider revisiting transform API — keep current functionality, but also add translate=, rotate=, scale=
-- this gracefully handles the use-case where complex or nested transforms are required (just use `rotate=120` instead of `transform={Transform2D::rotate(120)}`)
[ ] profiling, CPU sanity-optimization (likely: impl. dep graph / dirty-tracking / caching for expressions)
zb [ ] Production harness
[ ] macos
[ ] allow config of apple id / signing cert
alt: can probably punt this, until concrete needs arise
[ ] web
[ ] decide if necessary; maybe same as dev harness for now
zb [ ] Warning cleanup
MED
[ ] round out functionality
[ ] Text APIs (and fix macOS regression)
[x] Path primitive
[x] API design
[x] Ellipse primitive
[ ] polish up defaults & expected behavior (e.g. width of a Rect when unspecified)
[ ] Cargo cache bug (when changing the contents of @pax/pax-cartridge (template),
`cargo clean` is sometimes needed to update the `include_dir` cache.)
Is there a better solution than requiring `cargo clean` on lib-dev machines?
[ ] New units: `rad` and/or `deg` for rotation
[ ] @settings blocks
[ ] Runtime error handling
[ ] chart out surface area
[ ] divide by zero? what else?
[ ] vector access
[ ] ideally: patch into source maps
[ ] consts
-- decorate with `#[pax_const]`; copy tokens? or refer to orig? consider component/namespace reqs
-- consider also how to "coordinate between macros"
[ ] Support async
[ ] `Property` => channels 'smart object'; disposable `mut self` => lifecycle methods (support async lifecycle event handlers)
[ ] Pencil out error handling (userland)
[ ] update runtime to dispatch event handlers asynchronously, creating and passing "disposable self"s as needed
[ ] Dependency tracking & dirty-watching
[ ] support "helpers", composable functions, which also serve the need of temporaries/`let`s
[ ] dependency DAG + lazy evaluation, a la Excel
[ ] cache last known values
[ ] consider keeping a cache of `state tuple => output value`
[ ] address use-case of `Property<Vec<T>>`, inserting/changing an element without setting the whole
entity. Might want to offer a `get_mut` API (keep an eye on async / ownership concerns)
-- In fact, probably address this on the heels of a Property -> channel refactor, as the implications for this
intersection are significant
-- Solution for now: 1. store Vec<T> inside Property<Vec<T>> — .get_mut() the Vec, mutate, then set() the updated value -- treat the entire property as dirty when this `set` occurs
[ ] usable error messages
[ ] macro-time errors:
[ ] write to stderr? or other pipe/file/channel readable by `pax-compiler`
[ ] parsetime errors:
[ ] pax syntax errors -- error handling with Pest (add "overflow" final rule to grammar at necessary junctures, e.g. `foo = bar | baz | error` — then handle `error` matches at parse-time)
[ ] track line/column numbers; figure out how to report back to Rust/editor language server (if possible)
[ ] compile-time errors:
[ ] handle ad-hoc
[-] runtime errors: probably no special handling needed
[ ] `with` + event bindings
[ ] vtable + wrapper functions for event dispatch; play nicely with HandlerRegistry; add `Scope` or most relevant thing to args list in HandlerRegistry
[ ] update `handler_registry` closure codegen in cartridge — call methods with correct signature based on specified `with`
[ ] grammar+parser support
[ ] single variables, with option parens (e.g. `with (i)` or `with i`, or `with (i,j,k)`)
[ ] multiple variables in tuple `(i,j,k)`
[ ] Scrolling
[ ] Create `Scroller` primitive -- =refer to `Text` primitive for closest reference: pax-std-primitives
[ ] Register `Scroller` in `pax-std` and surface for use in `pax-example`
[ ] native scrolling container, passes scroll events / position to engine
- refer to how `click` events are handled from chassis-macos through the runtime
[ ] bounds for scrolling container passed to chassis by engine; chassis instantiates a scrolling container
[ ] attach native content as children of the native scroll container, so that native content scrolls natively with no need for Pax runtime intervention
- if this introduces "jello" sync problems, instead try updating native elements positions through the vanilla CRUD operations — refer to how `Text` content is updated in `chassis-macos` or `chassis-web`
[ ] Update `HandlerRegistry` to account for scroll event handlers; support `@scroll=self.some_handler` registration
[ ] `Text` upgrades:
[ ] alignment horizontal within bounding box
[ ] alignment vertical within bounding box
[ ] auto-sizing? (makes for super-easy alignment; requires letting OS render one frame, possibly off-screen, then applying that calculation. Requires `interrupt` from chassis after size is measured.
[ ] Rich text display (Possibly support markdown as authoring format)
[ ] Dropdown list
[ ] Slider
[ ] Toggle buttons (iOS "on/off" style)
[ ] Button + content (arbitrary rendering content? or just text to start?)
[ ] File controls
[ ] Upload/open control?
[ ] save/download control?
[ ] Text input boxes
[ ] single-line
[ ] multi-line?
[ ] rich text?
[ ] Numeric + stepper?
[ ] Databinding: event-based changes + two-way binding
[ ] Refactor ABI/FFI layer - Do before adding new targets, so that porting work & waste are reduced
[ ] flexbuffers -> flatbuffers, with schema
[ ] Port `pax-message/../lib.rs` to a Flexbuffer schema + codegenned Rust
[ ] Update macOS messaging layers to support
[ ] (Profile overhead of JSON serializing+parsing for Web; decide whether additional footprint cost is worth embedding a flatbuffer reader)
[ ] Linux/GTK dev-harness & chassis
[ ] support `NativeMessage`s for all primitives and `std`
[ ] dev-harness
[ ] ios app dev-harness & chassis
[ ] support `NativeMessage`s for all primitives and `std`
[ ] extract shared logic with macOS dev harness
[ ] support ios simulator / physical device
[ ] CLI hookups (--target)
[ ] Touch support
[ ] tap / swipe support
[ ] `clap` event, for "click or tap"
[ ] Image primitive
[ ] Bitmap support: .png, .jpg, maybe .svg, serialize as base64 and include encoding so that chassis can make sense of it
[ ] API: how to support assets? check out `include_bytes!`
[ ] Gradient fills: shapes, text
[ ] Support interpolating Colors; see: `impl Interpolatable for Color {` ...
[ ] Opacity (likely built-in property alongside `transform`, `size` -- it accumulates down render tree)
[ ] Palette built-in: perhaps `@palette { optional_nesting: { } }
[ ] Path primitive + APIs for animations
[ ] Mask primitive (a Clipping primitive that allows a `Path` definition for bounds, instead of a rectangle)
[ ] Ellipse
[ ] macOS chassis improvements:
[ ] Revisit loop timer? (keep timestamps, target exact FPS, able to know when frames are dropped)
[ ] support stand-alone .pax files (no rust file); .html use-case
[ ] asset management -- enables fonts and images
[ ] decide on approach: bundle into binary or work with chassis/dev-harness for bundling
[ ] support async/http assets, relative paths + configurable prefix path, absolute paths, http/https
[ ] Text++
[ ] custom fonts: embedded or webfonts
[ ] basic text + paragraph API
[ ] font family, face, weight, decoration
[ ] "rich text" or "annotated text" to support mixed content
[ ] paragraph: left-align/right-align/justify
[ ] (rely on `Transform` for vertical centering)
[ ] Raster images
[ ] Sizing / clipping API (e.g. cover, or anchor + stretch/maintain/fill/target-width/target-height/etc.)
(instead of full-window Electron/Expo-like wrappers)
[ ] Runtime sharing -- allow cartridges to share/sideload a runtime instead of duplicating, e.g. for 100 individual component/cartridges in a codebase
[ ] Component SDK
[ ] per-platform userland API (`mount`)
[ ] `component-harness` alternative to `dev-harness` for embedding
[ ] Wire up: properties/settings, placeholders,
[ ] Hook up PropertyTimeline
[ ] refactor easing curve packaging, probably into enum
[ ] refactor Tweenable, to support arbitrary types (dyn Tweenable) and impl for `fsize`
[ ] support Tweenable for f64
[ ] support Tweenable for `Transform`
[ ] ergonomic timeline API design in pax (probably JSON-esque {30: value, 120: other_value} where 30 is frame number
[ ] Imperative dirty-tracking API (a la MutationObserver)
[ ] Temporary lets in PAXEL?
[ ] Or: easy composition, "helpers"
[ ] Support "skinning" the template subgrammar:
[ ] KDL
[ ] YAML
[ ] JSON
[ ] "Media queries"
[ ] built-ins for platforms (`@macos, @web`)
[ ] `if` for dynamic application of properties, also responsive/screen-size concerns
[ ] Pax Browser
- simple desktop app, mostly a dev harness, but also
supports
[ ] Revisit embedded literal strings across codebase for error messages, to reduce binary footprint (enum? codes?)
[ ] Reinvestigate Any as an alternative to Coproduct generation
[ ] would dramatically simplify compiler, code-gen process
[ ] would make build process less brittle
[ ] roughly: `dyn InstanceNode` -> `Box<Any>`, downcast blocks instead of `match ... unreachable!()` blocks
[ ] ensure compatibility with `Rc`! Circa Q4'21, Any could not be downcast to Rc (e.g. `InstanceNodePtr`)
[ ] de-globalize InstantiationArgs, e.g. `slot_index` and `source_expression`
[ ] remove PropertiesCoproduct entirely (and probably repeat the process for TypesCoproduct)
[ ] possibly remove two-stage compiler process
[ ] sanity check that we can downcast from a given `Any` both to: 1. `dyn InstanceNode` (to call methods), and 2. `WhateverProperties` (to access properties)
[ ] sanity check that `Any + 'static` will work with needs of `dyn InstanceNode` and individual properties
[ ] check out downcast_rs crate as way to ease?
[ ] ensure that `'static` constraints can be met!! e.g. with dynamically instantiated nodes in `Repeat`
[ ] Designtime
[ ] codegen DefinitionToInstance traverser
[ ] codegen in `#[pax]`: From<SettingsLiteralBlockDefinition>
[ ] manual
[ ] macro
[ ] instantiator/traverser logic (codegen or library-coded)
[ ] duplex websocket connection + handlers
[ ] Write ORM (and maybe caching) methods for `Definitions`
[ ] Attach CRUD API endpoints to `Definition` ORM methods via `designtime` server
[ ] figure out recompilation loop or hot-reloading of Properties and Expressions
[ ] incl. state transfer
[ ] Margin & padding?
[ ] Decide whether to support, e.g. is there a simpler alternative w/ existing pieces?
[ ] Decide whether to support ONE or BOTH
[ ] Component-level defaults ("default masks") for properties (think: design system) -- e.g. "if not specified, all Rectangle > Stroke is _this value_"
[ ] Frames: overflow scrolling
[ ] chassis:
[ ] iOS
[ ] Windows
[ ] Android
[ ] Linux (GTK?)
[ ] Gradients
[ ] Multiple (stacked, polymorphic) fills
[ ] Gradient strokes?
[ ] Production compilation
[ ] Generation of RIL, feature-gating `designtime`
[ ] Packaging & imports
[ ] Ensure that 3rd party components can be loaded via vanilla import mechanism
[ ] JavaScript runtime
[ ] First-class TypeScript support
[ ] API design
[ ] code-behind & decorator syntax
[ ] Bindings to `runtime` API, plus IPC mechanism for triggering
[ ] Language server, syntax highlighting, IDE errors (VSCode, JetBrains)
[ ] Transform.skew
[ ] 3D renderers
[ ] Audio/video components
[ ] "headless" components?
Creative development environment
for makers of
graphical user interfaces