Start of making globals and hook declarations configurable

Some refactoring to allow the environment options to be passed in from the 
outside.
This commit is contained in:
Joe Savona
2023-02-16 14:06:15 -08:00
parent 158c9e4fc1
commit eece73262e
6 changed files with 53 additions and 12 deletions
+3 -3
View File
@@ -7,12 +7,12 @@
/// <reference path="./plugin-syntax-jsx.d.ts" />
import * as t from "@babel/types";
import type * as BabelCore from "@babel/core";
import generate from "@babel/generator";
import jsx from "@babel/plugin-syntax-jsx";
import { CompilerFlags, parseCompilerFlags } from "../CompilerFlags";
import * as t from "@babel/types";
import prettier from "prettier";
import { CompilerFlags, parseCompilerFlags } from "../CompilerFlags";
import { compile } from "../CompilerPipeline";
type BabelPluginPass = {
@@ -47,7 +47,7 @@ export default function ReactForgetBabelPlugin(
if (fn.scope.getProgramParent() !== fn.scope.parent) {
return;
}
const ast = compile(fn);
const ast = compile(fn, null);
// We are generating a new FunctionDeclaration node, so we must skip over it or this
// traversal will loop infinitely.
+9 -4
View File
@@ -12,6 +12,7 @@ import {
mergeConsecutiveBlocks,
ReactiveFunction,
} from "./HIR";
import { EnvironmentOptions } from "./HIR/Environment";
import {
analyseFunctions,
dropMemoCalls,
@@ -47,9 +48,10 @@ export type CompilerPipelineValue =
| { kind: "reactive"; name: string; value: ReactiveFunction };
export function* run(
func: NodePath<t.FunctionDeclaration>
func: NodePath<t.FunctionDeclaration>,
options?: EnvironmentOptions | null
): Generator<CompilerPipelineValue, t.Function> {
const hir = lower(func).unwrap();
const hir = lower(func, options ?? null).unwrap();
yield log({ kind: "hir", name: "HIR", value: hir });
mergeConsecutiveBlocks(hir);
@@ -186,8 +188,11 @@ export function* run(
return ast;
}
export function compile(func: NodePath<t.FunctionDeclaration>): t.Function {
let generator = run(func);
export function compile(
func: NodePath<t.FunctionDeclaration>,
options?: EnvironmentOptions | null
): t.Function {
let generator = run(func, options);
while (true) {
const next = generator.next();
if (next.done) {
+4 -3
View File
@@ -11,7 +11,7 @@ import invariant from "invariant";
import { CompilerError, ErrorSeverity } from "../CompilerError";
import { Err, Ok, Result } from "../Utils/Result";
import { assertExhaustive } from "../Utils/utils";
import { Environment } from "./Environment";
import { Environment, EnvironmentOptions } from "./Environment";
import {
BlockId,
BranchTerminal,
@@ -51,9 +51,10 @@ import HIRBuilder from "./HIRBuilder";
*/
export function lower(
func: NodePath<t.Function>,
options: EnvironmentOptions | null,
capturedRefs: t.Identifier[] = []
): Result<HIRFunction, CompilerError> {
const env = new Environment();
const env = new Environment(options);
const builder = new HIRBuilder(env, capturedRefs);
const context: Place[] = [];
@@ -1334,7 +1335,7 @@ function lowerExpression(
//
// This isn't a problem in practice because use Babel's scope analysis to
// identify the correct references.
const lowering = lower(expr, [
const lowering = lower(expr, builder.environment.options, [
...builder.context,
...captured.identifiers,
]);
+31
View File
@@ -1,9 +1,40 @@
import { IdentifierId, makeIdentifierId } from "./HIR";
import { BUILTIN_HOOKS, Hook } from "./Hooks";
const HOOK_PATTERN = /^_?use/;
export type EnvironmentOptions = {
customHooks: Map<string, Hook>;
};
const DEFAULT_OPTIONS: EnvironmentOptions = {
customHooks: new Map(),
};
export class Environment {
#options: EnvironmentOptions;
#nextIdentifer: number = 0;
constructor(options: EnvironmentOptions | null) {
this.#options = options ?? DEFAULT_OPTIONS;
}
get options(): EnvironmentOptions {
return this.#options;
}
get nextIdentifierId(): IdentifierId {
return makeIdentifierId(this.#nextIdentifer++);
}
getHookDeclaration(name: string): Hook | null {
if (!name.match(HOOK_PATTERN)) {
return null;
}
const hook = BUILTIN_HOOKS.get(name) ?? this.#options.customHooks.get(name);
if (hook !== undefined) {
return hook;
}
return null;
}
}
+4
View File
@@ -93,6 +93,10 @@ export default class HIRBuilder {
return this.#context;
}
get environment(): Environment {
return this.#env;
}
constructor(env: Environment, context: t.Identifier[]) {
this.#env = env;
this.#context = context;
+2 -2
View File
@@ -7,7 +7,7 @@
import { Effect, Place, ValueKind } from "./HIR";
export const HOOKS: Map<string, Hook> = new Map([
export const BUILTIN_HOOKS: Map<string, Hook> = new Map([
[
"useState",
{
@@ -68,7 +68,7 @@ export function parseHookCall(place: Place): Hook | null {
if (name === null || !name.match(/^_?use/)) {
return null;
}
const hook = HOOKS.get(name);
const hook = BUILTIN_HOOKS.get(name);
if (hook != null) {
return hook;
}