sile-typesetter / sile

The SILE Typesetter — Simon’s Improved Layout Engine
https://sile-typesetter.org
MIT License
1.61k stars 97 forks source link

Re-organize type constructors #1986

Closed alerque closed 5 months ago

alerque commented 5 months ago

See #1396

Omikhleia commented 5 months ago

I am not fully convinced by the extra types indirection, which doesn't mean much IMHO. Maybe we could keep SILE.length and SILE.measurement unchanged I do like the replacement of nodefactory by node however, it speaks enough (though again, short form SILE.node.nnode (etc.) would be sufficient).

EDIT: fixed typos in my message.

alerque commented 5 months ago

The "indirection" helps get things separated into modules that are actually independent scopes instead of the current cross-wired mess. We've come a long way on this (so far I've refactored classes, packages, inputters, outputters, etc.) but we're only at 50%. The rest needs cleaning up the same way ... right now I keep trying to swap out bits for performance testing etc. and it all blows up because Lua scopes are cross wired all over the place. A big one left is languages (BCP47, hyphenators, etc. are all wrapped up in that mess).

For short forms they can be aliased anywhere they are used a lot (local measurement = SILE.types.measurement). Also if we get them broken down like this in the future we'll have the option to use fenv() / _ENV stuff to automatically make everything in a certain scope reachable from top level Lua.

We can't do that without recursion issues with the current patchwork layout.

Omikhleia commented 5 months ago

I kind of understand, but I also see the same things being renamed again and again, from before my time in SILE to current days (suffice to look at _deprecated_nodefactory for instance), without visible real added value... E.g. newDisc > disc > discretionary -- Sure! But the discretionary logic was heavily deeply broken not that long ago, and we are still finding weirdness here and there in it... so we can rename concepts ad aeternam on layers of unstable algorithms, it doesn't imply anything really improves, apart from troubling users once again, and causing a lot of annoying deprecation notices ^^ ;)

alerque commented 5 months ago

I also see the same things being renamed again and again, from before my time in SILE to current days (suffice to look at _deprecated_nodefactory for instance)...

Not exactly. Yes the same general API surface has been renamed before, but the previous rename was the node names, not the location in the API and how the API gets loaded or how it is isolated from other functions.

The previous rename was done as part of the transition from stdlib objects to Penlight classes. I actually wanted to make this re-organization part of that transition but gave up after several failed attempts at creating shims. In spite of wanting to just bite the bullet and jump straight to the end goal, I decided would be a lot more friendly for end users if we were able to shim the functionality and throw warnings rather than start failing to render old documents entirely (i.e. deprecation warnings are noisy and obnoxious but more friendly than errors and give time to migrate, especially if they can go as far as suggesting the correct replacement usage) and I couldn't figure out how to shim 3 differed operations at once (renaming the node types, changing the class model used to instantiate them, and changing the on-demand loader and namespace isolation). Instead I opted for only making the subset of the desired changes that I was confident we could shim fairly robustly in one go, then waiting at least 2 major release cycles to make further breaking changes.

Omikhleia commented 5 months ago

Whatever,

alerque commented 5 months ago

Agreed, types is pretty generic. However it was my best idea for this loosely related assortment of building blocks (and we might eventually have more). Leaning towards the term "type" was largely driven by this being what they must be called in Rust and any variant of type-checked Lua we look into (whether an addon like typecheck or a dialect like Luau, Teal, Pluto, Ravi, etc.).

A "type" is actually what they are now in programmer terms—we have a "length" type that isn't a string and isn't a number and has specific attributes. We have type checking and casting utility functions already. A function might well expect one of these things as an argument type. Plain Lua of course has no type checking, but these are some of our common types to pass around and we check for them manually. Technically our document classes and packages are also a type, but we don't create/remove/instantiate/iterate over them quite the same way as do nodes, measurements, colors, etc.

I'm open to suggestion for better naming, but after several years of waiting to make this happen am not very open to not cleaning up the mess and moving towards cleaner types and namespacing.

Omikhleia commented 5 months ago

Then (SILE.colorparser >) SILE.color > SILE.types.color, I assume... I wouldn't be illogical in that grand scheme.

EDIT: Ah, indeed.

alerque commented 5 months ago

Yes.

The question I had was whether frames should be stashed in with types (SILE.types.frame) (extendable but the general assumption being that there is only one type of frame and they are generally used as-is) or promoted to a top level extensible type that are easy to subclass (a frames.base like we have for typesetters/etc.)? At the moment even in all of our external tinkering we only really have one frame implementation but I'm thinking that floats and possible non-square shapes and such might eventually be implemented as more robust frame classes. Does that sound reasonable?

Omikhleia commented 5 months ago

https://github.com/sile-typesetter/sile/issues/1396#issuecomment-1328365069

Look, I tried to think about it, but I always end up no wanting to be part of this renaming challenge. I have no understanding which problems it aims at solving. Maybe it's good, but I can't say... I only thrive for typography, after all. The frames are an utter mess. The pagebuilder would need to be killed directly on first sight. The typesetter... though I tried things there, still has problems (... "pushback" or "re-starting" without re-processing the whole queue...). The "insertions" and the "alternates" would need to be re-thought... So I don't really have the mind for "renaming" these. Might be my own limit here. We had SILE.colorparser: remember how I was unhappy about the shift to SILE.color... Eh, I won't change :) .... Yet the latter might be better as a class, but it doesn't have a __tostring method to help developers debugging a color, right? So what did we really win? I dunno... My own way is to go for each individual Lua file each year, and rank it between 1 (very bad) and 5 (highly good). Very few passed a mere 2.... Not that they are inherently bad, the system works, doh! But there would be better ways to improve them. Regardless of their naming, that is... But that must be me not understanding the final goal. So go ahead, rename; You might have seen what eludes me.

Omikhleia commented 5 months ago

As for frames, then -- I dunno, but it seems they'd be on par with typesetters. (Even without classes and inheritance, we can already replace their highly broken logic... As for insertions (look up for steal-position in the code.... Sigh)

alerque commented 5 months ago

I am leaning towards agreeing on frames. No worries if you don't have input (or the time to give it) on the programming stuff.

I'll send another PR with debug tooling for colors, because yes they should have :__tostring().

There is lots more to go here (frames, languages, etc.) but I'm merging now because I have multiple branches going on with experiments for languages and it's hard to keep them in sync when they all depend on this.