Compare commits

...

1 Commits

Author SHA1 Message Date
Joe Savona
2a5f77c261 [compiler] More readable alias signature declarations
Now that we have support for defining aliasing signatures in moduleTypeProvider, which uses string names for receiver/args/returns/etc, we can reuse that same form for builtin declarations. The declarations are written in the unparsed form and than parsed/validated when registered (in the addFunction/addHook call).

This also required flushing out configs/schemas for more effect types.
2025-06-18 15:46:12 -07:00
4 changed files with 327 additions and 166 deletions

View File

@@ -5,14 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import { import {Effect, ValueKind, ValueReason} from './HIR';
Effect,
GeneratedSource,
makeIdentifierId,
Place,
ValueKind,
ValueReason,
} from './HIR';
import { import {
BUILTIN_SHAPES, BUILTIN_SHAPES,
BuiltInArrayId, BuiltInArrayId,
@@ -41,18 +34,12 @@ import {
addFunction, addFunction,
addHook, addHook,
addObject, addObject,
signatureArgument,
} from './ObjectShape'; } from './ObjectShape';
import {BuiltInType, ObjectType, PolyType} from './Types'; import {BuiltInType, ObjectType, PolyType} from './Types';
import { import {TypeConfig} from './TypeSchema';
AliasingEffectConfig,
AliasingSignatureConfig,
TypeConfig,
} from './TypeSchema';
import {assertExhaustive} from '../Utils/utils'; import {assertExhaustive} from '../Utils/utils';
import {isHookName} from './Environment'; import {isHookName} from './Environment';
import {CompilerError, SourceLocation} from '..'; import {CompilerError, SourceLocation} from '..';
import {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';
/* /*
* This file exports types and defaults for JavaScript global objects. * This file exports types and defaults for JavaScript global objects.
@@ -658,35 +645,35 @@ const REACT_APIS: Array<[string, BuiltInType]> = [
hookKind: 'useEffect', hookKind: 'useEffect',
returnValueKind: ValueKind.Frozen, returnValueKind: ValueKind.Frozen,
aliasing: { aliasing: {
receiver: makeIdentifierId(0), receiver: '@receiver',
params: [], params: [],
rest: makeIdentifierId(1), rest: '@rest',
returns: makeIdentifierId(2), returns: '@returns',
temporaries: [signatureArgument(3)], temporaries: ['@effect'],
effects: [ effects: [
// Freezes the function and deps // Freezes the function and deps
{ {
kind: 'Freeze', kind: 'Freeze',
value: signatureArgument(1), value: '@rest',
reason: ValueReason.Effect, reason: ValueReason.Effect,
}, },
// Internally creates an effect object that captures the function and deps // Internally creates an effect object that captures the function and deps
{ {
kind: 'Create', kind: 'Create',
into: signatureArgument(3), into: '@effect',
value: ValueKind.Frozen, value: ValueKind.Frozen,
reason: ValueReason.KnownReturnSignature, reason: ValueReason.KnownReturnSignature,
}, },
// The effect stores the function and dependencies // The effect stores the function and dependencies
{ {
kind: 'Capture', kind: 'Capture',
from: signatureArgument(1), from: '@rest',
into: signatureArgument(3), into: '@effect',
}, },
// Returns undefined // Returns undefined
{ {
kind: 'Create', kind: 'Create',
into: signatureArgument(2), into: '@returns',
value: ValueKind.Primitive, value: ValueKind.Primitive,
reason: ValueReason.KnownReturnSignature, reason: ValueReason.KnownReturnSignature,
}, },
@@ -903,10 +890,6 @@ export function installTypeConfig(
} }
} }
case 'function': { case 'function': {
const aliasing =
typeConfig.aliasing != null
? parseAliasingSignatureConfig(typeConfig.aliasing, moduleName, loc)
: null;
return addFunction(shapes, [], { return addFunction(shapes, [], {
positionalParams: typeConfig.positionalParams, positionalParams: typeConfig.positionalParams,
restParam: typeConfig.restParam, restParam: typeConfig.restParam,
@@ -922,14 +905,10 @@ export function installTypeConfig(
noAlias: typeConfig.noAlias === true, noAlias: typeConfig.noAlias === true,
mutableOnlyIfOperandsAreMutable: mutableOnlyIfOperandsAreMutable:
typeConfig.mutableOnlyIfOperandsAreMutable === true, typeConfig.mutableOnlyIfOperandsAreMutable === true,
aliasing, aliasing: typeConfig.aliasing,
}); });
} }
case 'hook': { case 'hook': {
const aliasing =
typeConfig.aliasing != null
? parseAliasingSignatureConfig(typeConfig.aliasing, moduleName, loc)
: null;
return addHook(shapes, { return addHook(shapes, {
hookKind: 'Custom', hookKind: 'Custom',
positionalParams: typeConfig.positionalParams ?? [], positionalParams: typeConfig.positionalParams ?? [],
@@ -944,7 +923,7 @@ export function installTypeConfig(
), ),
returnValueKind: typeConfig.returnValueKind ?? ValueKind.Frozen, returnValueKind: typeConfig.returnValueKind ?? ValueKind.Frozen,
noAlias: typeConfig.noAlias === true, noAlias: typeConfig.noAlias === true,
aliasing, aliasing: typeConfig.aliasing,
}); });
} }
case 'object': { case 'object': {
@@ -987,90 +966,6 @@ export function installTypeConfig(
} }
} }
function parseAliasingSignatureConfig(
typeConfig: AliasingSignatureConfig,
moduleName: string,
loc: SourceLocation,
): AliasingSignature {
const lifetimes = new Map<string, Place>();
function define(temp: string): Place {
CompilerError.invariant(!lifetimes.has(temp), {
reason: `Invalid type configuration for module`,
description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`,
loc,
});
const place = signatureArgument(lifetimes.size);
lifetimes.set(temp, place);
return place;
}
function lookup(temp: string): Place {
const place = lifetimes.get(temp);
CompilerError.invariant(place != null, {
reason: `Invalid type configuration for module`,
description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`,
loc,
});
return place;
}
const receiver = define(typeConfig.receiver);
const params = typeConfig.params.map(define);
const rest = typeConfig.rest != null ? define(typeConfig.rest) : null;
const returns = define(typeConfig.returns);
const temporaries = typeConfig.temporaries.map(define);
const effects = typeConfig.effects.map(
(effect: AliasingEffectConfig): AliasingEffect => {
switch (effect.kind) {
case 'Assign': {
return {
kind: 'Assign',
from: lookup(effect.from),
into: lookup(effect.into),
};
}
case 'Create': {
return {
kind: 'Create',
into: lookup(effect.into),
reason: ValueReason.KnownReturnSignature,
value: effect.value,
};
}
case 'Freeze': {
return {
kind: 'Freeze',
value: lookup(effect.value),
reason: ValueReason.KnownReturnSignature,
};
}
case 'Impure': {
return {
kind: 'Impure',
place: lookup(effect.place),
error: CompilerError.throwTodo({
reason: 'Support impure effect declarations',
loc: GeneratedSource,
}),
};
}
default: {
assertExhaustive(
effect,
`Unexpected effect kind '${(effect as any).kind}'`,
);
}
}
},
);
return {
receiver: receiver.identifier.id,
params: params.map(p => p.identifier.id),
rest: rest != null ? rest.identifier.id : null,
returns: returns.identifier.id,
temporaries,
effects,
};
}
export function getReanimatedModuleType(registry: ShapeRegistry): ObjectType { export function getReanimatedModuleType(registry: ShapeRegistry): ObjectType {
// hooks that freeze args and return frozen value // hooks that freeze args and return frozen value
const frozenHooks = [ const frozenHooks = [

View File

@@ -1453,6 +1453,20 @@ export const ValueKindSchema = z.enum([
ValueKind.Context, ValueKind.Context,
]); ]);
export const ValueReasonSchema = z.enum([
ValueReason.Context,
ValueReason.Effect,
ValueReason.Global,
ValueReason.HookCaptured,
ValueReason.HookReturn,
ValueReason.JsxCaptured,
ValueReason.KnownReturnSignature,
ValueReason.Other,
ValueReason.ReactiveFunctionArgument,
ValueReason.ReducerState,
ValueReason.State,
]);
// The effect with which a value is modified. // The effect with which a value is modified.
export enum Effect { export enum Effect {
// Default value: not allowed after lifetime inference // Default value: not allowed after lifetime inference

View File

@@ -6,14 +6,18 @@
*/ */
import {CompilerError} from '../CompilerError'; import {CompilerError} from '../CompilerError';
import {AliasingSignature} from '../Inference/AliasingEffects'; import {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';
import {assertExhaustive} from '../Utils/utils';
import { import {
Effect, Effect,
GeneratedSource, GeneratedSource,
Hole,
makeDeclarationId, makeDeclarationId,
makeIdentifierId, makeIdentifierId,
makeInstructionId, makeInstructionId,
Place, Place,
SourceLocation,
SpreadPattern,
ValueKind, ValueKind,
ValueReason, ValueReason,
} from './HIR'; } from './HIR';
@@ -25,6 +29,7 @@ import {
PolyType, PolyType,
PrimitiveType, PrimitiveType,
} from './Types'; } from './Types';
import {AliasingEffectConfig, AliasingSignatureConfig} from './TypeSchema';
/* /*
* This file exports types and defaults for JavaScript object shapes. These are * This file exports types and defaults for JavaScript object shapes. These are
@@ -53,13 +58,20 @@ function createAnonId(): string {
export function addFunction( export function addFunction(
registry: ShapeRegistry, registry: ShapeRegistry,
properties: Iterable<[string, BuiltInType | PolyType]>, properties: Iterable<[string, BuiltInType | PolyType]>,
fn: Omit<FunctionSignature, 'hookKind'>, fn: Omit<FunctionSignature, 'hookKind' | 'aliasing'> & {
aliasing?: AliasingSignatureConfig | null | undefined;
},
id: string | null = null, id: string | null = null,
isConstructor: boolean = false, isConstructor: boolean = false,
): FunctionType { ): FunctionType {
const shapeId = id ?? createAnonId(); const shapeId = id ?? createAnonId();
const aliasing =
fn.aliasing != null
? parseAliasingSignatureConfig(fn.aliasing, '<builtin>', GeneratedSource)
: null;
addShape(registry, shapeId, properties, { addShape(registry, shapeId, properties, {
...fn, ...fn,
aliasing,
hookKind: null, hookKind: null,
}); });
return { return {
@@ -77,11 +89,18 @@ export function addFunction(
*/ */
export function addHook( export function addHook(
registry: ShapeRegistry, registry: ShapeRegistry,
fn: FunctionSignature & {hookKind: HookKind}, fn: Omit<FunctionSignature, 'aliasing'> & {
hookKind: HookKind;
aliasing?: AliasingSignatureConfig | null | undefined;
},
id: string | null = null, id: string | null = null,
): FunctionType { ): FunctionType {
const shapeId = id ?? createAnonId(); const shapeId = id ?? createAnonId();
addShape(registry, shapeId, [], fn); const aliasing =
fn.aliasing != null
? parseAliasingSignatureConfig(fn.aliasing, '<builtin>', GeneratedSource)
: null;
addShape(registry, shapeId, [], {...fn, aliasing});
return { return {
kind: 'Function', kind: 'Function',
return: fn.returnType, return: fn.returnType,
@@ -90,6 +109,129 @@ export function addHook(
}; };
} }
function parseAliasingSignatureConfig(
typeConfig: AliasingSignatureConfig,
moduleName: string,
loc: SourceLocation,
): AliasingSignature {
const lifetimes = new Map<string, Place>();
function define(temp: string): Place {
CompilerError.invariant(!lifetimes.has(temp), {
reason: `Invalid type configuration for module`,
description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`,
loc,
});
const place = signatureArgument(lifetimes.size);
lifetimes.set(temp, place);
return place;
}
function lookup(temp: string): Place {
const place = lifetimes.get(temp);
CompilerError.invariant(place != null, {
reason: `Invalid type configuration for module`,
description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`,
loc,
});
return place;
}
const receiver = define(typeConfig.receiver);
const params = typeConfig.params.map(define);
const rest = typeConfig.rest != null ? define(typeConfig.rest) : null;
const returns = define(typeConfig.returns);
const temporaries = typeConfig.temporaries.map(define);
const effects = typeConfig.effects.map(
(effect: AliasingEffectConfig): AliasingEffect => {
switch (effect.kind) {
case 'CreateFrom':
case 'Capture':
case 'Alias':
case 'Assign': {
const from = lookup(effect.from);
const into = lookup(effect.into);
return {
kind: effect.kind,
from,
into,
};
}
case 'Mutate':
case 'MutateTransitiveConditionally': {
const value = lookup(effect.value);
return {kind: effect.kind, value};
}
case 'Create': {
const into = lookup(effect.into);
return {
kind: 'Create',
into,
reason: effect.reason,
value: effect.value,
};
}
case 'Freeze': {
const value = lookup(effect.value);
return {
kind: 'Freeze',
value,
reason: effect.reason,
};
}
case 'Impure': {
const place = lookup(effect.place);
return {
kind: 'Impure',
place,
error: CompilerError.throwTodo({
reason: 'Support impure effect declarations',
loc: GeneratedSource,
}),
};
}
case 'Apply': {
const receiver = lookup(effect.receiver);
const fn = lookup(effect.function);
const args: Array<Place | SpreadPattern | Hole> = effect.args.map(
arg => {
if (typeof arg === 'string') {
return lookup(arg);
} else if (arg.kind === 'Spread') {
return {kind: 'Spread', place: lookup(arg.place)};
} else {
return arg;
}
},
);
const into = lookup(effect.into);
return {
kind: 'Apply',
receiver,
function: fn,
mutatesFunction: effect.mutatesFunction,
args,
into,
loc,
signature: null,
};
}
default: {
assertExhaustive(
effect,
`Unexpected effect kind '${(effect as any).kind}'`,
);
}
}
},
);
return {
receiver: receiver.identifier.id,
params: params.map(p => p.identifier.id),
rest: rest != null ? rest.identifier.id : null,
returns: returns.identifier.id,
temporaries,
effects,
};
}
/* /*
* Add an object to an existing ShapeRegistry. * Add an object to an existing ShapeRegistry.
* *
@@ -192,8 +334,7 @@ export type FunctionSignature = {
canonicalName?: string; canonicalName?: string;
aliasing?: AliasingSignature | null; aliasing?: AliasingSignature | null | undefined;
todo_aliasing?: AliasingSignature | null;
}; };
/* /*
@@ -320,24 +461,24 @@ addObject(BUILTIN_SHAPES, BuiltInArrayId, [
calleeEffect: Effect.Store, calleeEffect: Effect.Store,
returnValueKind: ValueKind.Primitive, returnValueKind: ValueKind.Primitive,
aliasing: { aliasing: {
receiver: makeIdentifierId(0), receiver: '@receiver',
params: [], params: [],
rest: makeIdentifierId(1), rest: '@rest',
returns: makeIdentifierId(2), returns: '@returns',
temporaries: [], temporaries: [],
effects: [ effects: [
// Push directly mutates the array itself // Push directly mutates the array itself
{kind: 'Mutate', value: signatureArgument(0)}, {kind: 'Mutate', value: '@receiver'},
// The arguments are captured into the array // The arguments are captured into the array
{ {
kind: 'Capture', kind: 'Capture',
from: signatureArgument(1), from: '@rest',
into: signatureArgument(0), into: '@receiver',
}, },
// Returns the new length, a primitive // Returns the new length, a primitive
{ {
kind: 'Create', kind: 'Create',
into: signatureArgument(2), into: '@returns',
value: ValueKind.Primitive, value: ValueKind.Primitive,
reason: ValueReason.KnownReturnSignature, reason: ValueReason.KnownReturnSignature,
}, },
@@ -374,58 +515,56 @@ addObject(BUILTIN_SHAPES, BuiltInArrayId, [
noAlias: true, noAlias: true,
mutableOnlyIfOperandsAreMutable: true, mutableOnlyIfOperandsAreMutable: true,
aliasing: { aliasing: {
receiver: makeIdentifierId(0), receiver: '@receiver',
params: [makeIdentifierId(1)], params: ['@callback'],
rest: null, rest: null,
returns: makeIdentifierId(2), returns: '@returns',
temporaries: [ temporaries: [
// Temporary representing captured items of the receiver // Temporary representing captured items of the receiver
signatureArgument(3), '@item',
// Temporary representing the result of the callback // Temporary representing the result of the callback
signatureArgument(4), '@callbackReturn',
/* /*
* Undefined `this` arg to the callback. Note the signature does not * Undefined `this` arg to the callback. Note the signature does not
* support passing an explicit thisArg second param * support passing an explicit thisArg second param
*/ */
signatureArgument(5), '@thisArg',
], ],
effects: [ effects: [
// Map creates a new mutable array // Map creates a new mutable array
{ {
kind: 'Create', kind: 'Create',
into: signatureArgument(2), into: '@returns',
value: ValueKind.Mutable, value: ValueKind.Mutable,
reason: ValueReason.KnownReturnSignature, reason: ValueReason.KnownReturnSignature,
}, },
// The first arg to the callback is an item extracted from the receiver array // The first arg to the callback is an item extracted from the receiver array
{ {
kind: 'CreateFrom', kind: 'CreateFrom',
from: signatureArgument(0), from: '@receiver',
into: signatureArgument(3), into: '@item',
}, },
// The undefined this for the callback // The undefined this for the callback
{ {
kind: 'Create', kind: 'Create',
into: signatureArgument(5), into: '@thisArg',
value: ValueKind.Primitive, value: ValueKind.Primitive,
reason: ValueReason.KnownReturnSignature, reason: ValueReason.KnownReturnSignature,
}, },
// calls the callback, returning the result into a temporary // calls the callback, returning the result into a temporary
{ {
kind: 'Apply', kind: 'Apply',
receiver: signatureArgument(5), receiver: '@thisArg',
args: [signatureArgument(3), {kind: 'Hole'}, signatureArgument(0)], args: ['@item', {kind: 'Hole'}, '@receiver'],
function: signatureArgument(1), function: '@callback',
into: signatureArgument(4), into: '@callbackReturn',
signature: null,
mutatesFunction: false, mutatesFunction: false,
loc: GeneratedSource,
}, },
// captures the result of the callback into the return array // captures the result of the callback into the return array
{ {
kind: 'Capture', kind: 'Capture',
from: signatureArgument(4), from: '@callbackReturn',
into: signatureArgument(2), into: '@returns',
}, },
], ],
}, },
@@ -577,28 +716,28 @@ addObject(BUILTIN_SHAPES, BuiltInSetId, [
// returnValueKind is technically dependent on the ValueKind of the set itself // returnValueKind is technically dependent on the ValueKind of the set itself
returnValueKind: ValueKind.Mutable, returnValueKind: ValueKind.Mutable,
aliasing: { aliasing: {
receiver: makeIdentifierId(0), receiver: '@receiver',
params: [], params: [],
rest: makeIdentifierId(1), rest: '@rest',
returns: makeIdentifierId(2), returns: '@returns',
temporaries: [], temporaries: [],
effects: [ effects: [
// Set.add returns the receiver Set // Set.add returns the receiver Set
{ {
kind: 'Assign', kind: 'Assign',
from: signatureArgument(0), from: '@receiver',
into: signatureArgument(2), into: '@returns',
}, },
// Set.add mutates the set itself // Set.add mutates the set itself
{ {
kind: 'Mutate', kind: 'Mutate',
value: signatureArgument(0), value: '@receiver',
}, },
// Captures the rest params into the set // Captures the rest params into the set
{ {
kind: 'Capture', kind: 'Capture',
from: signatureArgument(1), from: '@rest',
into: signatureArgument(0), into: '@receiver',
}, },
], ],
}, },
@@ -1303,30 +1442,30 @@ export const DefaultNonmutatingHook = addHook(
hookKind: 'Custom', hookKind: 'Custom',
returnValueKind: ValueKind.Frozen, returnValueKind: ValueKind.Frozen,
aliasing: { aliasing: {
receiver: makeIdentifierId(0), receiver: '@receiver',
params: [], params: [],
rest: makeIdentifierId(1), rest: '@rest',
returns: makeIdentifierId(2), returns: '@returns',
temporaries: [], temporaries: [],
effects: [ effects: [
// Freeze the arguments // Freeze the arguments
{ {
kind: 'Freeze', kind: 'Freeze',
value: signatureArgument(1), value: '@rest',
reason: ValueReason.HookCaptured, reason: ValueReason.HookCaptured,
}, },
// Returns a frozen value // Returns a frozen value
{ {
kind: 'Create', kind: 'Create',
into: signatureArgument(2), into: '@returns',
value: ValueKind.Frozen, value: ValueKind.Frozen,
reason: ValueReason.HookReturn, reason: ValueReason.HookReturn,
}, },
// May alias any arguments into the return // May alias any arguments into the return
{ {
kind: 'Alias', kind: 'Alias',
from: signatureArgument(1), from: '@rest',
into: signatureArgument(2), into: '@returns',
}, },
], ],
}, },

View File

@@ -8,7 +8,12 @@
import {isValidIdentifier} from '@babel/types'; import {isValidIdentifier} from '@babel/types';
import {z} from 'zod'; import {z} from 'zod';
import {Effect, ValueKind} from '..'; import {Effect, ValueKind} from '..';
import {EffectSchema, ValueKindSchema} from './HIR'; import {
EffectSchema,
ValueKindSchema,
ValueReason,
ValueReasonSchema,
} from './HIR';
export type ObjectPropertiesConfig = {[key: string]: TypeConfig}; export type ObjectPropertiesConfig = {[key: string]: TypeConfig};
export const ObjectPropertiesSchema: z.ZodType<ObjectPropertiesConfig> = z export const ObjectPropertiesSchema: z.ZodType<ObjectPropertiesConfig> = z
@@ -38,23 +43,48 @@ export const LifetimeIdSchema = z.string().refine(id => id.startsWith('@'), {
export type FreezeEffectConfig = { export type FreezeEffectConfig = {
kind: 'Freeze'; kind: 'Freeze';
value: string; value: string;
reason: ValueReason;
}; };
export const FreezeEffectSchema: z.ZodType<FreezeEffectConfig> = z.object({ export const FreezeEffectSchema: z.ZodType<FreezeEffectConfig> = z.object({
kind: z.literal('Freeze'), kind: z.literal('Freeze'),
value: LifetimeIdSchema, value: LifetimeIdSchema,
reason: ValueReasonSchema,
});
export type MutateEffectConfig = {
kind: 'Mutate';
value: string;
};
export const MutateEffectSchema: z.ZodType<MutateEffectConfig> = z.object({
kind: z.literal('Mutate'),
value: LifetimeIdSchema,
});
export type MutateTransitiveConditionallyConfig = {
kind: 'MutateTransitiveConditionally';
value: string;
};
export const MutateTransitiveConditionallySchema: z.ZodType<MutateTransitiveConditionallyConfig> =
z.object({
kind: z.literal('MutateTransitiveConditionally'),
value: LifetimeIdSchema,
}); });
export type CreateEffectConfig = { export type CreateEffectConfig = {
kind: 'Create'; kind: 'Create';
into: string; into: string;
value: ValueKind; value: ValueKind;
reason: ValueReason;
}; };
export const CreateEffectSchema: z.ZodType<CreateEffectConfig> = z.object({ export const CreateEffectSchema: z.ZodType<CreateEffectConfig> = z.object({
kind: z.literal('Create'), kind: z.literal('Create'),
into: LifetimeIdSchema, into: LifetimeIdSchema,
value: ValueKindSchema, value: ValueKindSchema,
reason: ValueReasonSchema,
}); });
export type AssignEffectConfig = { export type AssignEffectConfig = {
@@ -69,6 +99,77 @@ export const AssignEffectSchema: z.ZodType<AssignEffectConfig> = z.object({
into: LifetimeIdSchema, into: LifetimeIdSchema,
}); });
export type AliasEffectConfig = {
kind: 'Alias';
from: string;
into: string;
};
export const AliasEffectSchema: z.ZodType<AliasEffectConfig> = z.object({
kind: z.literal('Alias'),
from: LifetimeIdSchema,
into: LifetimeIdSchema,
});
export type CaptureEffectConfig = {
kind: 'Capture';
from: string;
into: string;
};
export const CaptureEffectSchema: z.ZodType<CaptureEffectConfig> = z.object({
kind: z.literal('Capture'),
from: LifetimeIdSchema,
into: LifetimeIdSchema,
});
export type CreateFromEffectConfig = {
kind: 'CreateFrom';
from: string;
into: string;
};
export const CreateFromEffectSchema: z.ZodType<CreateFromEffectConfig> =
z.object({
kind: z.literal('CreateFrom'),
from: LifetimeIdSchema,
into: LifetimeIdSchema,
});
export type ApplyArgConfig =
| string
| {kind: 'Spread'; place: string}
| {kind: 'Hole'};
export const ApplyArgSchema: z.ZodType<ApplyArgConfig> = z.union([
LifetimeIdSchema,
z.object({
kind: z.literal('Spread'),
place: LifetimeIdSchema,
}),
z.object({
kind: z.literal('Hole'),
}),
]);
export type ApplyEffectConfig = {
kind: 'Apply';
receiver: string;
function: string;
mutatesFunction: boolean;
args: Array<ApplyArgConfig>;
into: string;
};
export const ApplyEffectSchema: z.ZodType<ApplyEffectConfig> = z.object({
kind: z.literal('Apply'),
receiver: LifetimeIdSchema,
function: LifetimeIdSchema,
mutatesFunction: z.boolean(),
args: z.array(ApplyArgSchema),
into: LifetimeIdSchema,
});
export type ImpureEffectConfig = { export type ImpureEffectConfig = {
kind: 'Impure'; kind: 'Impure';
place: string; place: string;
@@ -82,14 +183,26 @@ export const ImpureEffectSchema: z.ZodType<ImpureEffectConfig> = z.object({
export type AliasingEffectConfig = export type AliasingEffectConfig =
| FreezeEffectConfig | FreezeEffectConfig
| CreateEffectConfig | CreateEffectConfig
| CreateFromEffectConfig
| AssignEffectConfig | AssignEffectConfig
| ImpureEffectConfig; | AliasEffectConfig
| CaptureEffectConfig
| ImpureEffectConfig
| MutateEffectConfig
| MutateTransitiveConditionallyConfig
| ApplyEffectConfig;
export const AliasingEffectSchema: z.ZodType<AliasingEffectConfig> = z.union([ export const AliasingEffectSchema: z.ZodType<AliasingEffectConfig> = z.union([
FreezeEffectSchema, FreezeEffectSchema,
CreateEffectSchema, CreateEffectSchema,
CreateFromEffectSchema,
AssignEffectSchema, AssignEffectSchema,
AliasEffectSchema,
CaptureEffectSchema,
ImpureEffectSchema, ImpureEffectSchema,
MutateEffectSchema,
MutateTransitiveConditionallySchema,
ApplyEffectSchema,
]); ]);
export type AliasingSignatureConfig = { export type AliasingSignatureConfig = {