@samitouri / QOS-React-2 / commits / 45331ef21b

[be][env] Move EnvironmentOptions -> EnvironmentConfig

--- Simplify Environment options by: - EnvironmentOptions -> EnvironmentConfig config is now directly passed around instead of being eagerly merged. - Moving merging / initialization logic into `Environment` constructor. From my understanding, there is no need to decouple merged options from an environment. This prepares Environment for the next PR, which adds non-stateful properties to Environment (i.e. a `GlobalRegistry`) that should be converted from config values (i.e. not directly exposed to the user due to potentially inconsistent inputs)

Mofei Zhang committed Mar 30, 2023 at 15:03 UTC 45331ef21b9b25c784e73bdda3c529d2074612cb
5 files changed +35 -50
compiler/forget/src/Babel/PluginOptions.ts
+2 -2
@@ -5,7 +5,7 @@
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 -import { EnvironmentOptions } from "../HIR/Environment";
8 +import { EnvironmentConfig } from "../HIR/Environment";
9
10 export type PluginOptions = {
11 /**
@@ -13,7 +13,7 @@ export type PluginOptions = {
13 */
14 enableOnlyOnUseForgetDirective: boolean;
15
16 - environment: Partial<EnvironmentOptions> | null;
16 + environment: EnvironmentConfig | null;
17
18 logger: Logger | null;
19
compiler/forget/src/CompilerPipeline.ts
+5 -5
@@ -12,7 +12,7 @@ import {
12 mergeConsecutiveBlocks,
13 ReactiveFunction,
14 } from "./HIR";
15 -import { EnvironmentOptions, mergeOptions } from "./HIR/Environment";
15 +import { EnvironmentConfig, Environment } from "./HIR/Environment";
16 import { validateConsistentIdentifiers } from "./HIR/ValidateConsistentIdentifiers";
17 import {
18 analyseFunctions,
@@ -51,9 +51,9 @@ export type CompilerPipelineValue =
51
52 export function* run(
53 func: NodePath<t.FunctionDeclaration>,
54 - options?: Partial<EnvironmentOptions> | null
54 + config?: EnvironmentConfig | null
55 ): Generator<CompilerPipelineValue, t.FunctionDeclaration> {
56 - const hir = lower(func, mergeOptions(options ?? null)).unwrap();
56 + const hir = lower(func, new Environment(config ?? null)).unwrap();
57 yield log({ kind: "hir", name: "HIR", value: hir });
58
59 mergeConsecutiveBlocks(hir);
@@ -147,7 +147,7 @@ export function* run(
147 });
148
149 pruneNonEscapingScopes(reactiveFunction, {
150 - memoizeJsxElements: options?.memoizeJsxElements ?? true,
150 + memoizeJsxElements: config?.memoizeJsxElements ?? true,
151 });
152 yield log({
153 kind: "reactive",
@@ -205,7 +205,7 @@ export function* run(
205
206 export function compile(
207 func: NodePath<t.FunctionDeclaration>,
208 - options?: Partial<EnvironmentOptions> | null
208 + options?: Partial<EnvironmentConfig> | null
209 ): t.FunctionDeclaration {
210 let generator = run(func, options);
211 while (true) {
compiler/forget/src/HIR/BuildHIR.ts
+5 -8
@@ -12,7 +12,7 @@ import invariant from "invariant";
12 import { CompilerError, ErrorSeverity } from "../CompilerError";
13 import { Err, Ok, Result } from "../Utils/Result";
14 import { assertExhaustive } from "../Utils/utils";
15 -import { Environment, EnvironmentOptions } from "./Environment";
15 +import { Environment } from "./Environment";
16 import {
17 ArrayPattern,
18 BlockId,
@@ -57,13 +57,11 @@ import HIRBuilder from "./HIRBuilder";
57 */
58 export function lower(
59 func: NodePath<t.Function>,
60 - options: EnvironmentOptions | null,
60 + env: Environment,
61 capturedRefs: t.Identifier[] = [],
62 // the outermost function being compiled, in case lower() is called recursively (for lambdas)
63 - parent: NodePath<t.Function> | null = null,
64 - environment: Environment | null = null
63 + parent: NodePath<t.Function> | null = null
64 ): Result<HIRFunction, CompilerError> {
66 - const env = environment ?? new Environment(options);
65 const builder = new HIRBuilder(env, parent ?? func, capturedRefs);
66 const context: Place[] = [];
67
@@ -2013,10 +2011,9 @@ function lowerFunctionExpression(
2011 // identify the correct references.
2012 const lowering = lower(
2013 expr,
2016 - builder.environment.options,
2014 + builder.environment,
2015 [...builder.context, ...captured.identifiers],
2018 - builder.parentFunction,
2019 - builder.environment
2016 + builder.parentFunction
2017 );
2018 let loweredFunc: HIRFunction;
2019 if (lowering.isErr()) {
compiler/forget/src/HIR/Environment.ts
+18 -30
@@ -11,41 +11,29 @@ import {
11 ValueKind,
12 } from "./HIR";
13 import { BUILTIN_HOOKS, Hook } from "./Hooks";
14 -import { BUILTIN_SHAPES, FunctionSignature } from "./ObjectShape";
14 +import {
15 + BUILTIN_SHAPES,
16 + FunctionSignature,
17 + ShapeRegistry,
18 +} from "./ObjectShape";
19
20 const HOOK_PATTERN = /^_?use/;
21
18 -export type EnvironmentOptions = {
22 +export type EnvironmentConfig = Partial<{
23 customHooks: Map<string, Hook>;
20 - globals: Set<string>;
24 memoizeJsxElements: boolean;
22 -};
23 -
24 -const DEFAULT_OPTIONS: EnvironmentOptions = {
25 - customHooks: new Map(),
26 - globals: DEFAULT_GLOBALS,
27 - memoizeJsxElements: true,
28 -};
29 -
30 -export function mergeOptions(
31 - options: Partial<EnvironmentOptions> | null
32 -): EnvironmentOptions {
33 - return {
34 - ...DEFAULT_OPTIONS,
35 - ...(options ?? {}),
36 - };
37 -}
25 +}>;
26
27 export class Environment {
40 - #options: EnvironmentOptions;
28 + #customHooks: Map<string, Hook>;
29 + #globals: Set<string>;
30 + #shapes: ShapeRegistry;
31 #nextIdentifer: number = 0;
32
43 - constructor(options: EnvironmentOptions | null) {
44 - this.#options = options ?? DEFAULT_OPTIONS;
45 - }
46 -
47 - get options(): EnvironmentOptions {
48 - return this.#options;
33 + constructor(config: EnvironmentConfig | null) {
34 + this.#customHooks = config?.customHooks ?? new Map();
35 + this.#shapes = BUILTIN_SHAPES;
36 + this.#globals = DEFAULT_GLOBALS;
37 }
38
39 get nextIdentifierId(): IdentifierId {
@@ -53,7 +41,7 @@ export class Environment {
41 }
42
43 getGlobalDeclaration(name: string): Global | null {
56 - if (!this.#options.globals.has(name)) {
44 + if (!this.#globals.has(name)) {
45 log(() => `Undefined global '${name}'`);
46 }
47 return { name };
@@ -63,7 +51,7 @@ export class Environment {
51 if (!name.match(HOOK_PATTERN)) {
52 return null;
53 }
66 - const hook = BUILTIN_HOOKS.get(name) ?? this.#options.customHooks.get(name);
54 + const hook = BUILTIN_HOOKS.get(name) ?? this.#customHooks.get(name);
55 if (hook !== undefined) {
56 return hook;
57 }
@@ -83,7 +71,7 @@ export class Environment {
71 if (shapeId !== null) {
72 // If an object or function has a shapeId, it must have been assigned
73 // by Forget (and be present in a builtin or user-defined registry)
86 - const shape = BUILTIN_SHAPES.get(shapeId);
74 + const shape = this.#shapes.get(shapeId);
75 invariant(
76 shape !== undefined,
77 `[HIR] Forget internal error: cannot resolve shape ${shapeId}`
@@ -97,7 +85,7 @@ export class Environment {
85 getFunctionSignature(type: FunctionType): FunctionSignature | null {
86 const { shapeId } = type;
87 if (shapeId !== null) {
100 - const shape = BUILTIN_SHAPES.get(shapeId);
88 + const shape = this.#shapes.get(shapeId);
89 invariant(
90 shape !== undefined,
91 `[HIR] Forget internal error: cannot resolve shape ${shapeId}`
compiler/forget/src/__tests__/hir-test.ts
+5 -5
@@ -7,19 +7,19 @@
7
8 "use strict";
9
10 -import * as t from "@babel/types";
10 import { parse } from "@babel/parser";
11 import traverse, { NodePath } from "@babel/traverse";
12 +import * as t from "@babel/types";
13 import path from "path";
14
15 +import invariant from "invariant";
16 import * as CompilerPipeline from "../CompilerPipeline";
17 import { Effect, ValueKind } from "../HIR";
18 +import { EnvironmentConfig } from "../HIR/Environment";
19 import { printFunction } from "../HIR/PrintHIR";
18 -import { EnvironmentOptions } from "../HIR/Environment";
19 -import { Result, Ok, Err } from "../Utils/Result";
20 import { toggleLogging } from "../Utils/logger";
21 +import { Err, Ok, Result } from "../Utils/Result";
22 import generateTestsFromFixtures from "./test-utils/generateTestsFromFixtures";
22 -import invariant from "invariant";
23
24 // TODO: make pipeline names an enum
25 // Currently, this is the last pass that operates on hir
@@ -81,7 +81,7 @@ type CompileResult = {
81 function compile(
82 source: string,
83 language: "flow" | "typescript",
84 - compilerEnv: Partial<EnvironmentOptions>
84 + compilerEnv: Partial<EnvironmentConfig>
85 ): Result<Array<CompileResult>, Error> {
86 const transformedFns = new Array<CompileResult>();
87 const babelAsts = parseFunctions(source, language);