Compare commits
1 Commits
asserts-st
...
pr33530
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a5f77c261 |
@@ -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 = [
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
Reference in New Issue
Block a user