diff --git a/compiler/forget/src/Babel/PluginOptions.ts b/compiler/forget/src/Babel/PluginOptions.ts index 0e47a59cfb..eaaf90015c 100644 --- a/compiler/forget/src/Babel/PluginOptions.ts +++ b/compiler/forget/src/Babel/PluginOptions.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import { EnvironmentOptions } from "../HIR/Environment"; +import { EnvironmentConfig } from "../HIR/Environment"; export type PluginOptions = { /** @@ -13,7 +13,7 @@ export type PluginOptions = { */ enableOnlyOnUseForgetDirective: boolean; - environment: Partial | null; + environment: EnvironmentConfig | null; logger: Logger | null; diff --git a/compiler/forget/src/CompilerPipeline.ts b/compiler/forget/src/CompilerPipeline.ts index e628207fc2..80fb6dc299 100644 --- a/compiler/forget/src/CompilerPipeline.ts +++ b/compiler/forget/src/CompilerPipeline.ts @@ -12,7 +12,7 @@ import { mergeConsecutiveBlocks, ReactiveFunction, } from "./HIR"; -import { EnvironmentOptions, mergeOptions } from "./HIR/Environment"; +import { EnvironmentConfig, Environment } from "./HIR/Environment"; import { validateConsistentIdentifiers } from "./HIR/ValidateConsistentIdentifiers"; import { analyseFunctions, @@ -51,9 +51,9 @@ export type CompilerPipelineValue = export function* run( func: NodePath, - options?: Partial | null + config?: EnvironmentConfig | null ): Generator { - const hir = lower(func, mergeOptions(options ?? null)).unwrap(); + const hir = lower(func, new Environment(config ?? null)).unwrap(); yield log({ kind: "hir", name: "HIR", value: hir }); mergeConsecutiveBlocks(hir); @@ -147,7 +147,7 @@ export function* run( }); pruneNonEscapingScopes(reactiveFunction, { - memoizeJsxElements: options?.memoizeJsxElements ?? true, + memoizeJsxElements: config?.memoizeJsxElements ?? true, }); yield log({ kind: "reactive", @@ -205,7 +205,7 @@ export function* run( export function compile( func: NodePath, - options?: Partial | null + options?: Partial | null ): t.FunctionDeclaration { let generator = run(func, options); while (true) { diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 0cb6f316ac..9aaa6ce52f 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -12,7 +12,7 @@ import invariant from "invariant"; import { CompilerError, ErrorSeverity } from "../CompilerError"; import { Err, Ok, Result } from "../Utils/Result"; import { assertExhaustive } from "../Utils/utils"; -import { Environment, EnvironmentOptions } from "./Environment"; +import { Environment } from "./Environment"; import { ArrayPattern, BlockId, @@ -57,13 +57,11 @@ import HIRBuilder from "./HIRBuilder"; */ export function lower( func: NodePath, - options: EnvironmentOptions | null, + env: Environment, capturedRefs: t.Identifier[] = [], // the outermost function being compiled, in case lower() is called recursively (for lambdas) - parent: NodePath | null = null, - environment: Environment | null = null + parent: NodePath | null = null ): Result { - const env = environment ?? new Environment(options); const builder = new HIRBuilder(env, parent ?? func, capturedRefs); const context: Place[] = []; @@ -2013,10 +2011,9 @@ function lowerFunctionExpression( // identify the correct references. const lowering = lower( expr, - builder.environment.options, + builder.environment, [...builder.context, ...captured.identifiers], - builder.parentFunction, - builder.environment + builder.parentFunction ); let loweredFunc: HIRFunction; if (lowering.isErr()) { diff --git a/compiler/forget/src/HIR/Environment.ts b/compiler/forget/src/HIR/Environment.ts index d41e044713..28aa5abfaa 100644 --- a/compiler/forget/src/HIR/Environment.ts +++ b/compiler/forget/src/HIR/Environment.ts @@ -11,41 +11,29 @@ import { ValueKind, } from "./HIR"; import { BUILTIN_HOOKS, Hook } from "./Hooks"; -import { BUILTIN_SHAPES, FunctionSignature } from "./ObjectShape"; +import { + BUILTIN_SHAPES, + FunctionSignature, + ShapeRegistry, +} from "./ObjectShape"; const HOOK_PATTERN = /^_?use/; -export type EnvironmentOptions = { +export type EnvironmentConfig = Partial<{ customHooks: Map; - globals: Set; memoizeJsxElements: boolean; -}; - -const DEFAULT_OPTIONS: EnvironmentOptions = { - customHooks: new Map(), - globals: DEFAULT_GLOBALS, - memoizeJsxElements: true, -}; - -export function mergeOptions( - options: Partial | null -): EnvironmentOptions { - return { - ...DEFAULT_OPTIONS, - ...(options ?? {}), - }; -} +}>; export class Environment { - #options: EnvironmentOptions; + #customHooks: Map; + #globals: Set; + #shapes: ShapeRegistry; #nextIdentifer: number = 0; - constructor(options: EnvironmentOptions | null) { - this.#options = options ?? DEFAULT_OPTIONS; - } - - get options(): EnvironmentOptions { - return this.#options; + constructor(config: EnvironmentConfig | null) { + this.#customHooks = config?.customHooks ?? new Map(); + this.#shapes = BUILTIN_SHAPES; + this.#globals = DEFAULT_GLOBALS; } get nextIdentifierId(): IdentifierId { @@ -53,7 +41,7 @@ export class Environment { } getGlobalDeclaration(name: string): Global | null { - if (!this.#options.globals.has(name)) { + if (!this.#globals.has(name)) { log(() => `Undefined global '${name}'`); } return { name }; @@ -63,7 +51,7 @@ export class Environment { if (!name.match(HOOK_PATTERN)) { return null; } - const hook = BUILTIN_HOOKS.get(name) ?? this.#options.customHooks.get(name); + const hook = BUILTIN_HOOKS.get(name) ?? this.#customHooks.get(name); if (hook !== undefined) { return hook; } @@ -83,7 +71,7 @@ export class Environment { if (shapeId !== null) { // If an object or function has a shapeId, it must have been assigned // by Forget (and be present in a builtin or user-defined registry) - const shape = BUILTIN_SHAPES.get(shapeId); + const shape = this.#shapes.get(shapeId); invariant( shape !== undefined, `[HIR] Forget internal error: cannot resolve shape ${shapeId}` @@ -97,7 +85,7 @@ export class Environment { getFunctionSignature(type: FunctionType): FunctionSignature | null { const { shapeId } = type; if (shapeId !== null) { - const shape = BUILTIN_SHAPES.get(shapeId); + const shape = this.#shapes.get(shapeId); invariant( shape !== undefined, `[HIR] Forget internal error: cannot resolve shape ${shapeId}` diff --git a/compiler/forget/src/__tests__/hir-test.ts b/compiler/forget/src/__tests__/hir-test.ts index ef5fc5457f..b828be1e8b 100644 --- a/compiler/forget/src/__tests__/hir-test.ts +++ b/compiler/forget/src/__tests__/hir-test.ts @@ -7,19 +7,19 @@ "use strict"; -import * as t from "@babel/types"; import { parse } from "@babel/parser"; import traverse, { NodePath } from "@babel/traverse"; +import * as t from "@babel/types"; import path from "path"; +import invariant from "invariant"; import * as CompilerPipeline from "../CompilerPipeline"; import { Effect, ValueKind } from "../HIR"; +import { EnvironmentConfig } from "../HIR/Environment"; import { printFunction } from "../HIR/PrintHIR"; -import { EnvironmentOptions } from "../HIR/Environment"; -import { Result, Ok, Err } from "../Utils/Result"; import { toggleLogging } from "../Utils/logger"; +import { Err, Ok, Result } from "../Utils/Result"; import generateTestsFromFixtures from "./test-utils/generateTestsFromFixtures"; -import invariant from "invariant"; // TODO: make pipeline names an enum // Currently, this is the last pass that operates on hir @@ -81,7 +81,7 @@ type CompileResult = { function compile( source: string, language: "flow" | "typescript", - compilerEnv: Partial + compilerEnv: Partial ): Result, Error> { const transformedFns = new Array(); const babelAsts = parseFunctions(source, language);