Skip to content

Spike feat(exo): take 1: opt out individual arguments#1724

Closed
erights wants to merge 1 commit intomarkm-type-guardsfrom
markm-interface-optout
Closed

Spike feat(exo): take 1: opt out individual arguments#1724
erights wants to merge 1 commit intomarkm-type-guardsfrom
markm-interface-optout

Conversation

@erights
Copy link
Copy Markdown
Contributor

@erights erights commented Aug 16, 2023

Staged on #1715 , though if feasible I would have preferred to stage it on #1712

This take 1 is a failed experiment, or at least an incomplete one.

Add an M.rawValue() guard as kind of a peer to M.await(), whose purpose is to allow the argument in that position to pass through as is, with no checking or enforcement, to be bound to the corresponding raw method parameter.

This experiment failed when I got to exo's use of M.splitArray to process the matching of required, optional, and rest arguments. A lot of work went into generating good error messages, all of which would need to be redone if the argument list is not a Passable list, and the components are not Pattern lists.

Attn @michaelfig , though not a reviewer because I do not consider this PR a candidate for merging.

@erights erights self-assigned this Aug 16, 2023
@erights erights changed the base branch from master to markm-type-guards August 16, 2023 01:35
@erights erights marked this pull request as draft August 16, 2023 01:37
* non-raw method guards.
*/
const MinMethodGuard = M.call().rest(M.any()).returns(M.any());

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of M.splitArray that caused me to give up on take1 is on line 38 below.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is what I would do to make it work. Am I missing something?

const defendSyncArgs = (args, methodGuard, label) => {
  const { argGuards, optionalArgGuards, restArgGuard } = methodGuard;
  const paramsPattern = M.splitArray(
    argGuards,
    optionalArgGuards,
    restArgGuard,
  );
  const positionalGuards = [...argGuards, ...(optionalArgGuards || [])];
  const numPositionalArgs = Math.min(positionalGuards.length, args.length);
  const startOfRawArgs = isRawValueGuard(restArgGuard) ? numPositionalArgs : undefined;
  const cookedArgs = args.slice(0, startOfRawArgs);
  for (let i = 0; i < numPositionalArgs; i += 1) {
    if (isRawValueGuard(positionalGuards[i])) {
      // Replace the raw argument with something innocuous as a
      // placeholder to be matched by the raw value guard without
      // hardening the caller's argument.
      cookedArgs[i] = null;
    }
  }
  mustMatch(harden(cookedArgs), paramsPattern, label);
};

// ...
    // Note purposeful use of `this` and concise method syntax
    syncMethod(...args) {
      defendSyncArgs(args, methodGuard, label);
      const result = apply(method, this, args);
      if (!isRawValueGuard(returnGuard)) {
        // Only harden non-raw return values.
        mustMatch(harden(result), returnGuard, `${label}: result`);
      }
      return result;
    },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OMG that’s beautiful! I love how local it is. Please do try this, thanks!

@erights
Copy link
Copy Markdown
Contributor Author

erights commented Aug 16, 2023

Closing in favor of #1725

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants