
@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