@leif I’m not much of an ObjC expert, but don’t think it has constructors separate from methods. An object created by a class’s alloc is a pile of zeros, and init is called by (strong) convention to fill that in. So, yes, override init.
Init or make a separate class method to construct what you want but it all boils up through Init at some point.
Alloc init setters is the basic pattern. It’s been a while tho
@lexi.lambda It’s true that the model doesn’t have a “frame”, but addr in a Defs record plays that role. Since the model is limited to working with one definition context at a time, a definition context captures the whole current expander environment ξ and maps addr to it in the store Σ. Additions to the definition context add onto the ξ for addr. Then, the rule for lexpand can use that environment (called ξ_defs at that rule) for expanding subexpressions. If the model were written more explicitly in terms of frames, addr would start out mapped to an empty environment, and lexpand would append ξ_defs to the current expander environment ξ. Of course, in an implementation in a language with state (i.e., Racket), the store is Σ implicit, and addr is a frame object that is mutated. The content of the frame is effectively appended to the environment when the definition context is used. (Maybe it’s an actual append; I forget and didn’t look back at the code.) I’ll have to go refresh my memory on how frame-id is used to trigger use-site scopes.
Following up on frame-id in the implementation (which may not be the question you’re asking, but just in case): that’s used as an alternative to making the current expander context (i.e., ctx) have a “add use-site scope?” field and making sure the field is updated when entering a nested context. That is, the :add use-site scope?" field should be set to #f whenever a new set of bindings is added to the environment, but instead of trying to keep those things in sync, frame-id is used to determine when that hypothetical field should have been set to #f to be consistent.
@mflatt That makes sense, thanks.
It does look like to add proper screen reader support, I would have to add proper hooks in the canvas and editor interfaces. Which I’m happy to do, but that seems like a much bigger change.
(For example, you would want the screen reader to be aware of the lexer of the specific #lang, so it reads out proper tokens.
)
Although come to think of it, it could probably be as simple as adding an optional text description method to each snip, and then have the editor serialize those snips.
(Which as I understand it, it already does.)
Ehh…actually, never mind. Because in the case of text, what you want to read may cross-cut multiple snips. :disappointed:
@mflatt I’m trying my best to understand, and I think I’m starting to grok what you told me. I think I was confused by the way the typeset version of the model describes Σ as exclusively a binding store, but the actual model sticks other things in Σ as well, including definition environments. IIUC, those definition environments correspond to the env-mixins of the real expander’s internal definition contexts?
Yes
So, given that, here’s where I’m currently confused: what you’re describing seems to reflect the way the model maps addr to ξ, and that ξ then becomes the mapping that the environment is extended with upon expansion. If addr corresponds to a frame, then I would expect the real expander to get the bindings added to that frame and add them to the environment in local-expand, as the model does. But in the real expander, add-intdef-bindings doesn’t use the frame id to look up what should be added to the environment, it just uses internal-definition-context-env-mixins directly. The frame id isn’t used there. So I’m confused how the two are related in the real expander.
Ok, you’re right that env-mixins is the part that’s like addr. I see that frame-id is not always allocated alongside env-mixins, but can instead instead carry the enclosing context’s frame id.
@mflatt Thank you for your comment on that GH issue; that clears up everything, I think! I’ll try and update the PR to reflect my new understanding. However, I do have one followup question: does the intdef argument to syntax-local-value need to be relaxed to accept a list like local-expand? My feeling is that yes, it does, but I’m not completely sure.
(“Need” is probably a strong word, but I really mean “if I am using definition contexts this way and want to use syntax-local-value on something bound like in my example in the GH thread”.)
That makes sense to me, too.
In the meantime, I realized that I think syntax-local-bind-syntaxes needs a list-of-intdefs argument as well, in case the RHS of a syntax binding uses syntax-local-value.
@tetsumi has joined the channel