Skip to content

Commit

Permalink
Cache node + lazy default values (#178)
Browse files Browse the repository at this point in the history
* cache node + lazy default values

* update stuff
  • Loading branch information
Brendonovich authored Aug 12, 2023
1 parent 7ba5b44 commit cafb1fb
Show file tree
Hide file tree
Showing 20 changed files with 410 additions and 105 deletions.
31 changes: 23 additions & 8 deletions app/src/components/Graph/IO/DataInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import {
BasePrimitiveType,
BaseType,
DataInput as DataInputModel,
Enum,
EnumType,
EnumVariants,
PrimitiveType,
WildcardType,
t,
} from "@macrograph/core";
import { Show, Switch, Match } from "solid-js";

Expand All @@ -19,10 +22,12 @@ import {
} from "~/components/ui";
import { DataPin } from ".";

type EnumValue = t.infer<t.Enum<Enum<EnumVariants>>>;

interface InputProps {
type: AnyType;
value: any;
onChange(v: any): void;
value: t.infer<PrimitiveType> | EnumValue | null;
onChange(v: t.infer<PrimitiveType>): void;
connected: boolean;
}

Expand All @@ -48,21 +53,27 @@ const Input = (props: InputProps) => {
/>
)}
</Match>
<Match when={props.type instanceof BasePrimitiveType && props.type}>
<Match
when={
props.type instanceof BasePrimitiveType &&
props.value !== null &&
props.type
}
>
{(type) => (
<Switch>
<Match when={type().primitiveVariant() === "bool"}>
<CheckBox
class={className()}
value={props.value}
value={props.value as boolean}
onChange={props.onChange}
/>
</Match>
<Match when={type().primitiveVariant() === "string"}>
<div class="w-16">
<TextInput
class={className()}
value={props.value}
value={props.value as string}
onChange={props.onChange}
/>
</div>
Expand All @@ -71,7 +82,9 @@ const Input = (props: InputProps) => {
<div class="w-16">
<IntInput
class={className()}
value={props.value}
initialValue={
props.value ? parseInt(props.value.toString()) : 0
}
onChange={props.onChange}
/>
</div>
Expand All @@ -80,7 +93,9 @@ const Input = (props: InputProps) => {
<div class="w-16">
<FloatInput
class={className()}
value={props.value}
initialValue={
props.value ? parseFloat(props.value.toString()) : 0
}
onChange={props.onChange}
/>
</div>
Expand All @@ -96,7 +111,7 @@ const Input = (props: InputProps) => {
enum={type().inner}
value={
(type().inner.variants as EnumVariants).find(
(v) => v.name === props.value?.variant
(v) => v.name === (props.value as EnumValue)?.variant
) ??
(props.onChange(type().inner.variants[0].default()),
type().inner.variants[0])
Expand Down
26 changes: 17 additions & 9 deletions app/src/components/ui/FloatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import clsx from "clsx";
import { createSignal } from "solid-js";

interface Props {
value: number;
initialValue: number;
onChange(v: number): void;
class?: string;
}

// floating point regex
const FLOAT_REGEX = /^[+-]?\d*(\.\d+)?$/;

export const FloatInput = (props: Props) => {
const [value, setValue] = createSignal(props.value.toString());
// if NaN reset to 0
const initialValue = isNaN(props.initialValue) ? 0 : props.initialValue;
props.onChange(initialValue);

const [value, setValue] = createSignal(props.initialValue.toString());

return (
<input
Expand All @@ -21,14 +22,21 @@ export const FloatInput = (props: Props) => {
const value = e.target.value;
setValue(value);

if (FLOAT_REGEX.test(value)) props.onChange(parseFloat(value));
const numValue = parseFloat(value);
if (!isNaN(numValue)) props.onChange(numValue);
}}
onBlur={(e) => {
if (e.target.value.length === 0) {
const s = e.target.value;
const num = parseFloat(s);

if (s.length === 0) {
setValue("0");
props.onChange(0);
} else if (!FLOAT_REGEX.test(e.target.value)) {
setValue(props.value.toString());
} else if (isNaN(num)) {
setValue(props.initialValue.toString());
} else {
setValue(num.toString());
props.onChange(num);
}
}}
class={clsx(
Expand Down
25 changes: 17 additions & 8 deletions app/src/components/ui/IntInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import clsx from "clsx";
import { createSignal } from "solid-js";

interface Props {
value: number;
initialValue: number;
onChange(v: number): void;
class?: string;
}

const INT_REGEX = /^[+-]?\d+$/;

export const IntInput = (props: Props) => {
const [value, setValue] = createSignal(props.value.toString());
// if NaN reset to 0
const initialValue = isNaN(props.initialValue) ? 0 : props.initialValue;
props.onChange(initialValue);

const [value, setValue] = createSignal(initialValue.toString());

return (
<input
Expand All @@ -21,14 +23,21 @@ export const IntInput = (props: Props) => {

setValue(value);

if (INT_REGEX.test(value)) props.onChange(parseInt(value));
const numValue = parseInt(value);
if (!isNaN(numValue)) props.onChange(parseInt(value));
}}
onBlur={(e) => {
if (e.target.value.length === 0) {
const s = e.target.value;
const num = parseInt(s);

if (s.length === 0) {
setValue("0");
props.onChange(0);
} else if (!INT_REGEX.test(e.target.value)) {
setValue(props.value.toString());
} else if (isNaN(num)) {
setValue(props.initialValue.toString());
} else {
setValue(num.toString());
props.onChange(num);
}
}}
class={clsx(
Expand Down
5 changes: 3 additions & 2 deletions core/src/models/Core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,14 @@ class ExecutionContext {
input.connection as Option<DataOutput<any> | ScopeOutput>
).mapOrElse(
() => {
if (input instanceof DataInput) return input.defaultValue;
if (input instanceof DataInput)
return input.defaultValue ?? input.type.default();
},
(conn) => {
const data = this.data.get(conn);

if (data === undefined)
throw new Error(`Data not found for ${input.name}!`);
throw new Error(`Data not found for input '${input.name}'!`);

return data;
}
Expand Down
12 changes: 6 additions & 6 deletions core/src/models/IO.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import { createMutable } from "solid-js/store";
import { ReactiveSet } from "@solid-primitives/set";
import { Node } from "./Node";
import { t, Option, None, BaseType } from "../types";
import { t, Option, None, BaseType, PrimitiveType } from "../types";
import { DataOutputBuilder, ScopeRef } from "./NodeSchema";

export type DataInputArgs<T extends BaseType<any>> = {
id: string;
name?: string;
type: T;
defaultValue?: any;
defaultValue?: t.infer<PrimitiveType> | null;
node: Node;
};

export class DataInput<T extends BaseType<any>> {
id: string;
name?: string;
defaultValue: any = null;
defaultValue: t.infer<PrimitiveType> | null = null;
type: T;
node: Node;
connection: Option<DataOutput<T>> = None;

constructor(args: DataInputArgs<T>) {
this.id = args.id;
this.name = args.name;
this.defaultValue = args.defaultValue || args.type.default();
this.defaultValue = args.defaultValue ?? null;
this.node = args.node;
this.type = args.type;

Expand All @@ -48,9 +48,9 @@ export interface DataOutputArgs<T extends BaseType<any>> {
type: T;
}

export class DataOutput<T extends BaseType<any>> {
export class DataOutput<T extends BaseType> {
id: string;
connections = new ReactiveSet<DataInput<any>>();
connections = new ReactiveSet<DataInput<BaseType>>();
node: Node;
name?: string;
type: T;
Expand Down
2 changes: 1 addition & 1 deletion core/src/models/NodeSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export type RunCtx = {
output: TOutput,
data: t.infer<TOutput["type"]>
): void;
getInput<TInput extends DataInput<any> | ScopeInput>(
getInput<TInput extends DataInput<BaseType<any>> | ScopeInput>(
input: TInput
): TInput extends DataInput<infer T>
? t.infer<T>
Expand Down
6 changes: 3 additions & 3 deletions core/src/types/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ export class EnumVariant<
return createMutable(this);
}

default(): any {
default() {
const data = this.data;

return data === null
? {
variant: this.name,
}
: ({
: {
variant: this.name,
data: Object.entries(data).reduce(
(acc, [name, type]) => ({ ...acc, [name]: type.default() }),
{}
),
} as any);
};
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/types/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class ListType<T extends BaseType> extends BaseType<t.infer<T>[]> {
super();
}

default(): any {
default(): t.infer<T>[] {
return [];
}

Expand Down
6 changes: 3 additions & 3 deletions core/src/types/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { BaseType } from "./base";
export type MapValue<T> = Map<string, T>;

export class MapType<TValue extends BaseType<any>> extends BaseType<
Map<string, t.infer<TValue>>
MapValue<t.infer<TValue>>
> {
constructor(public value: TValue) {
super();
}

default(): any {
return new Map();
default() {
return new Map<string, t.infer<TValue>>();
}

variant(): TypeVariant {
Expand Down
1 change: 0 additions & 1 deletion core/src/types/option.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createMutable } from "solid-js/store";
import { z } from "zod";
import { t, TypeVariant, Wildcard } from ".";
import { BaseType } from "./base";
Expand Down
2 changes: 1 addition & 1 deletion core/src/types/primitive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export class StringType extends BasePrimitiveType<string> {
}

export class BoolType extends BasePrimitiveType<boolean> {
default(): any {
default() {
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/types/struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ export class StructType<Fields extends StructFields> extends BaseType<
super();
}

default(): any {
default(): InferStructFields<Fields> {
return Object.entries(this.struct.fields).reduce(
(acc, [key, value]) => ({
...acc,
[key]: value.default(),
}),
{}
);
) as any;
}

variant(): TypeVariant {
Expand Down
1 change: 0 additions & 1 deletion core/src/types/t.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
AnyType,
Enum,
EnumType,
EnumVariants,
ListType,
MapType,
OptionType,
Expand Down
7 changes: 5 additions & 2 deletions core/src/types/wildcard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,11 @@ export class WildcardType extends BaseType<unknown> {
this.connections.delete(opposite);
}

default(): any {
return this.wildcard.value().map((v) => v.default());
default(): Option<unknown> {
return this.wildcard
.value()
.map((v) => v.default())
.expect("Cannot get default of unconnected wildcard!");
}

variant(): TypeVariant {
Expand Down
Loading

0 comments on commit cafb1fb

Please sign in to comment.