[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);