Skip to content

Commit

Permalink
Maintain types better through lambda and list
Browse files Browse the repository at this point in the history
Fixes #249
  • Loading branch information
benjie committed Mar 21, 2023
1 parent c5a1273 commit 0049f89
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 30 deletions.
4 changes: 2 additions & 2 deletions grafast/dataplan-pg/src/examples/exampleSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3231,8 +3231,8 @@ export function makeExampleSchema(
any,
any
>,
number[],
ListStep<ExecutableStep<number>[]>
readonly number[],
ListStep<readonly ExecutableStep<any>[]>
> => ({
Person: {
match: (v) => v[0] != null,
Expand Down
10 changes: 7 additions & 3 deletions grafast/dataplan-pg/src/steps/pgSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1716,16 +1716,20 @@ and ${sql.indent(sql.parens(condition(i + 1)))}`}

const $lower =
this.lowerIndexStepId != null
? this.getDep(this.lowerIndexStepId)
? (this.getDep(this.lowerIndexStepId) as ExecutableStep<
number | null | undefined
>)
: constant(null);
const $upper =
this.upperIndexStepId != null
? this.getDep(this.upperIndexStepId)
? (this.getDep(this.upperIndexStepId) as ExecutableStep<
number | null | undefined
>)
: constant(null);

const limitAndOffsetLambda = lambda(
list([$lower, $upper]),
([cursorLower, cursorUpper]: Array<number | null>) => {
([cursorLower, cursorUpper]) => {
/** lower bound - exclusive (1-indexed) */
let lower = 0;
/** upper bound - exclusive (1-indexed) */
Expand Down
22 changes: 13 additions & 9 deletions grafast/dataplan-pg/src/steps/pgUnionAll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function parseCursor(cursor: string | null) {
}
parseCursor.isSyncAndSafe = true; // Optimization

function add([a, b]: [a: number, b: number]): number {
function add([a, b]: readonly [a: number, b: number]): number {
return a + b;
}
add.isSyncAndSafe = true;
Expand Down Expand Up @@ -1310,16 +1310,20 @@ and ${condition(i + 1)}`}

const $lower =
this.lowerIndexStepId != null
? this.getDep(this.lowerIndexStepId)
? (this.getDep(this.lowerIndexStepId) as ExecutableStep<
number | null | undefined
>)
: constant(null);
const $upper =
this.upperIndexStepId != null
? this.getDep(this.upperIndexStepId)
? (this.getDep(this.upperIndexStepId) as ExecutableStep<
number | null | undefined
>)
: constant(null);

const limitAndOffsetLambda = lambda(
list([$lower, $upper]),
([cursorLower, cursorUpper]: Array<number | null>) => {
([cursorLower, cursorUpper]) => {
/** lower bound - exclusive (1-indexed) */
let lower = 0;
/** upper bound - exclusive (1-indexed) */
Expand Down Expand Up @@ -1379,13 +1383,13 @@ and ${condition(i + 1)}`}
true,
);
this.limitAndOffsetId = this.addDependency(limitAndOffsetLambda);
const limitLambda = access<number>(limitAndOffsetLambda, [0]);
const offsetLambda = access<number>(limitAndOffsetLambda, [1]);
const limitPlusOffsetLambda = lambda([limitLambda, offsetLambda], add);
const $limitLambda = access<number>(limitAndOffsetLambda, [0]);
const $offsetLambda = access<number>(limitAndOffsetLambda, [1]);
const limitPlusOffsetLambda = lambda([$limitLambda, $offsetLambda], add);
this.limitAndOffsetSQL = sql`\nlimit ${this.placeholder(
limitLambda,
$limitLambda,
TYPES.int,
)}\noffset ${this.placeholder(offsetLambda, TYPES.int)}`;
)}\noffset ${this.placeholder($offsetLambda, TYPES.int)}`;
this.innerLimitSQL = sql`\nlimit ${this.placeholder(
limitPlusOffsetLambda,
TYPES.int,
Expand Down
6 changes: 6 additions & 0 deletions grafast/grafast/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -814,3 +814,9 @@ export interface JSONObject {
[key: string]: JSONValue;
}
export interface JSONArray extends Array<JSONValue> {}

export type UnwrapPlanTuple<
/* const */ TIn extends readonly ExecutableStep<any>[],
> = {
[Index in keyof TIn]: TIn[Index] extends ExecutableStep<infer U> ? U : never;
} & { length: number };
15 changes: 9 additions & 6 deletions grafast/grafast/src/steps/lambda.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ExecutionExtra, PromiseOrDirect } from "../interfaces.js";
import type { ExecutionExtra, PromiseOrDirect, UnwrapPlanTuple } from "../interfaces.js";
import type { ExecutableStep } from "../step.js";
import { UnbatchedExecutableStep } from "../step.js";
import { list } from "./list.js";
Expand Down Expand Up @@ -50,12 +50,15 @@ export class LambdaStep<TIn, TOut> extends UnbatchedExecutableStep<TOut> {
* callback. Note: if you need to pass more than one value, pass a `ListStep`
* as the `$plan` argument.
*/
function lambda<TIn extends [...any[]], TOut>(
plans: { [Index in keyof TIn]: ExecutableStep<TIn[Index]> },
fn: (value: TIn) => PromiseOrDirect<TOut>,
function lambda<const TIn extends readonly ExecutableStep<any>[], TOut>(
plans: TIn,
fn: (value: UnwrapPlanTuple<TIn>) => PromiseOrDirect<TOut>,
isSyncAndSafe?: boolean,
): LambdaStep<TIn, TOut>;
function lambda<TIn, TOut>(
): LambdaStep<
UnwrapPlanTuple<TIn>,
TOut
>;
function lambda<const TIn extends any, TOut>(
$plan: ExecutableStep<TIn> | null | undefined,
fn: (value: TIn) => PromiseOrDirect<TOut>,
isSyncAndSafe?: boolean,
Expand Down
14 changes: 4 additions & 10 deletions grafast/grafast/src/steps/list.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import type { ExecutionExtra } from "../interfaces.js";
import type { ExecutionExtra, UnwrapPlanTuple } from "../interfaces.js";
import type { ExecutableStep } from "../step.js";
import { UnbatchedExecutableStep } from "../step.js";

type UnwrapPlanTuple<TPlanTuple extends readonly ExecutableStep<any>[]> = [
...(TPlanTuple extends readonly ExecutableStep<infer U>[]
? readonly U[]
: never)
];

export class ListStep<
TPlanTuple extends readonly ExecutableStep<any>[],
const TPlanTuple extends readonly ExecutableStep<any>[],
> extends UnbatchedExecutableStep<UnwrapPlanTuple<TPlanTuple>> {
static $$export = {
moduleName: "grafast",
Expand All @@ -18,7 +12,7 @@ export class ListStep<
isSyncAndSafe = true;
allowMultipleOptimizations = true;

constructor(list: readonly [...TPlanTuple]) {
constructor(list: TPlanTuple) {
super();
for (let i = 0, l = list.length; i < l; i++) {
this.addDependency(list[i]);
Expand Down Expand Up @@ -95,7 +89,7 @@ export class ListStep<
* Takes a list of plans and turns it into a single plan that represents the
* list of their values.
*/
export function list<TPlanTuple extends ExecutableStep<any>[]>(
export function list<const TPlanTuple extends readonly ExecutableStep<any>[]>(
list: TPlanTuple,
): ListStep<TPlanTuple> {
return new ListStep<TPlanTuple>(list);
Expand Down

0 comments on commit 0049f89

Please sign in to comment.