Skip to content

Commit

Permalink
Checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
wycats committed Feb 12, 2025
1 parent 3dafadd commit a5f57d9
Show file tree
Hide file tree
Showing 22 changed files with 819 additions and 412 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ module('[glimmer-compiler] precompile', ({ test }) => {

let block: WireFormat.SerializedTemplateBlock = JSON.parse(wire.block);

let [[, componentNameExpr]] = block[0] as [WireFormat.Content.ResolvedBlock];
let [[, componentNameExpr]] = block[0] as [WireFormat.Content.InvokeResolvedBlockComponent];

localAssert(
Array.isArray(componentNameExpr) && componentNameExpr[0] === Op.ResolveAsComponentCallee,
Expand Down
44 changes: 36 additions & 8 deletions packages/@glimmer/compiler/lib/builder/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import type { RequireAtLeastOne, Simplify } from 'type-fest';
import { localAssert } from '@glimmer/debug-util';
import { LOCAL_DEBUG } from '@glimmer/local-debug-flags';
import { dict, values } from '@glimmer/util';
import { SexpOpcodes as Op } from '@glimmer/wire-format';
import {
BLOCKS_OPCODE,
EMPTY_ARGS_OPCODE,
NAMED_ARGS_AND_BLOCKS_OPCODE,
NAMED_ARGS_OPCODE,
SexpOpcodes as Op,
} from '@glimmer/wire-format';

export interface Symbols {
top: ProgramSymbols;
Expand Down Expand Up @@ -146,13 +152,35 @@ export interface BuilderGetFree {
export function buildComponentArgs(
splattributes: Optional<WireFormat.Core.Splattributes>,
hash: Optional<WireFormat.Core.Hash>,
blocks: Optional<WireFormat.Core.Blocks>
): Optional<WireFormat.Core.ComponentArgs> {
return compact({
splattributes,
hash,
blocks,
});
componentBlocks: Optional<WireFormat.Core.Blocks>
): WireFormat.Core.BlockArgs {
const blocks = combineSplattributes(componentBlocks, splattributes);

if (hash && blocks) {
return [NAMED_ARGS_AND_BLOCKS_OPCODE, hash, blocks];
} else if (hash) {
return [NAMED_ARGS_OPCODE, hash];
} else if (blocks) {
return [BLOCKS_OPCODE, blocks];
} else {
return [EMPTY_ARGS_OPCODE];
}
}

function combineSplattributes(
blocks: Optional<WireFormat.Core.Blocks>,
splattributes: Optional<WireFormat.Core.Splattributes>
): Optional<WireFormat.Core.Blocks> {
if (blocks && splattributes) {
return [
[...blocks[0], 'attrs'],
[...blocks[1], [splattributes, []] satisfies WireFormat.SerializedInlineBlock],
];
} else if (splattributes) {
return [['attrs'], [[splattributes, []] satisfies WireFormat.SerializedInlineBlock]];
} else {
return blocks;
}
}

type CompactObject<T> = Simplify<
Expand Down
42 changes: 29 additions & 13 deletions packages/@glimmer/compiler/lib/builder/test-support/test-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ import {
import { exhausted, expect, isPresentArray, localAssert, unreachable } from '@glimmer/debug-util';
import { assertNever } from '@glimmer/util';
import {
BLOCKS_OPCODE,
EMPTY_ARGS_OPCODE,
NAMED_ARGS_AND_BLOCKS_OPCODE,
NAMED_ARGS_OPCODE,
POSITIONAL_AND_BLOCKS_OPCODE,
POSITIONAL_AND_NAMED_ARGS_AND_BLOCKS_OPCODE,
POSITIONAL_AND_NAMED_ARGS_OPCODE,
POSITIONAL_ARGS_OPCODE,
SexpOpcodes as Op,
Expand All @@ -68,8 +72,7 @@ import type {
} from './builder-interface';

import { compactSexpr } from '../../passes/2-encoding/content';
import { callArgs } from '../../passes/2-encoding/expressions';
import { compact, isGet, isInvokeResolved, needsAtNames } from '../builder';
import { isGet, isInvokeResolved, needsAtNames } from '../builder';
import { normalizeStatement } from './builder-interface';

export function buildStatements(
Expand Down Expand Up @@ -158,6 +161,7 @@ export function buildStatement(
}

return [[Op.InvokeDynamicBlock, path, args]];
// ^?
}

case KEYWORD_HEAD: {
Expand All @@ -183,7 +187,7 @@ export function buildAppendCautiously(
): WireFormat.Content.SomeAppend | WireFormat.Content.AppendHtmlText {
if (Array.isArray(expr)) {
if (expr[0] === Op.ResolveAsAppendableCallee) {
return [Op.AppendResolvedInvokable, expr[1]];
return [Op.AppendResolvedInvokable, expr[1], [EMPTY_ARGS_OPCODE]];
} else if (isInvokeResolved(expr)) {
const [, callee, args] = expr;

Expand Down Expand Up @@ -410,17 +414,17 @@ export function buildExpression(
);

if (builtExpr[0] === Op.CallResolved) {
return [builtExpr[0], builtExpr[1], buildArgs(builtParams, builtHash)];
return [builtExpr[0], builtExpr[1], buildCallArgs(builtParams, builtHash)];
}

if (builtExpr.length === 2) {
switch (builtExpr[0]) {
case Op.ResolveAsAppendableCallee:
return [Op.CallResolved, builtExpr[1], buildArgs(builtParams, builtHash)];
return [Op.CallResolved, builtExpr[1], buildCallArgs(builtParams, builtHash)];
}
}

return [Op.CallDynamicValue, builtExpr, buildArgs(builtParams, builtHash)];
return [Op.CallDynamicValue, builtExpr, buildCallArgs(builtParams, builtHash)];
}

case HAS_BLOCK_EXPR: {
Expand Down Expand Up @@ -666,15 +670,27 @@ export function buildBlockArgs(
rawHash: Optional<WireFormat.Core.Hash>,
blocks: Optional<WireFormat.Core.Blocks>,
{ path }: { path: WireFormat.Core.Expression }
): Optional<WireFormat.Core.BlockArgs> {
): WireFormat.Core.BlockArgs {
if (!params && !rawHash && !blocks) {
return [EMPTY_ARGS_OPCODE];
}

const hash: Optional<WireFormat.Core.Hash> =
isGet(path) && needsAtNames(path) ? addAtNames(rawHash) : rawHash;

return compact({
params,
hash,
blocks,
});
if (!blocks) {
return buildCallArgs(params, hash);
}

if (params && hash) {
return [POSITIONAL_AND_NAMED_ARGS_AND_BLOCKS_OPCODE, params, hash, blocks];
} else if (params) {
return [POSITIONAL_AND_BLOCKS_OPCODE, params, blocks];
} else if (hash) {
return [NAMED_ARGS_AND_BLOCKS_OPCODE, hash, blocks];
} else {
return [BLOCKS_OPCODE, blocks];
}
}

function addAtNames(hash: Optional<WireFormat.Core.Hash>): Optional<WireFormat.Core.Hash> {
Expand All @@ -685,7 +701,7 @@ function addAtNames(hash: Optional<WireFormat.Core.Hash>): Optional<WireFormat.C
return [keys.map((key) => `@${key}`) as PresentArray<string>, values];
}

function buildArgs(
function buildCallArgs(
params: Optional<WireFormat.Core.Params>,
hash: Optional<WireFormat.Core.Hash>
): WireFormat.Core.CallArgs {
Expand Down
57 changes: 32 additions & 25 deletions packages/@glimmer/compiler/lib/passes/2-encoding/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ import type { BlockSymbolTable } from '@glimmer/syntax';
import { assertPresentArray, exhausted, localAssert } from '@glimmer/debug-util';
import { LOCAL_DEBUG, LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags';
import { LOCAL_LOGGER } from '@glimmer/util';
import { isGetLexical, SexpOpcodes as Op } from '@glimmer/wire-format';
import { EMPTY_ARGS_OPCODE, isGetLexical, SexpOpcodes as Op } from '@glimmer/wire-format';

import type { OptionalList } from '../../shared/list';
import type * as mir from './mir';

import {
buildComponentArgs,
compact,
isGet,
isGetSymbolOrPath,
isTupleExpression,
needsAtNames,
} from '../../builder/builder';
import { deflateAttrName, deflateTagName } from '../../utils';
import {
callArgs,
encodeArgs,
encodeComponentBlockArgs,
encodeExpr,
encodeMaybeExpr,
encodeNamedArguments,
Expand Down Expand Up @@ -166,28 +166,23 @@ export function InvokeBlockComponent({
return [
Op.InvokeLexicalBlockComponent,
encodeExpr(head),
BlockArgs(args, blocks, { insertAtPrefix: needsAtNames(path) }),
// @todo verify whether insertAtPrefix is variable here
encodeComponentBlockArgs(args.positional, args.named, blocks),
];
} else if (head.type === 'Resolved') {
return [
Op.InvokeResolvedBlockComponent,
encodeExpr(head),
BlockArgs(args, blocks, { insertAtPrefix: needsAtNames(path) }),
// @todo verify whether insertAtPrefix is variable here
encodeComponentBlockArgs(args.positional, args.named, blocks),
];
}

return [Op.InvokeDynamicBlock, path, BlockArgs(args, blocks, { insertAtPrefix: true })];
}

export function BlockArgs(
argsNode: Pick<mir.Args, 'positional' | 'named'>,
blocksNode: Optional<mir.NamedBlocks>,
{ insertAtPrefix }: { insertAtPrefix: boolean }
): Optional<WireFormat.Core.BlockArgs> {
return compact({
...encodeArgs(argsNode, insertAtPrefix),
blocks: blocksNode ? NamedBlocks(blocksNode) : undefined,
});
return [
Op.InvokeDynamicBlock,
path,
encodeComponentBlockArgs(args.positional, args.named, blocks),
];
}

export function AppendTrustedHTML({
Expand All @@ -201,7 +196,7 @@ export function AppendValueCautiously({
}: mir.AppendValueCautiously): WireFormat.Content.SomeAppend {
switch (value.type) {
case 'Resolved': {
return [Op.AppendResolvedInvokable, value.symbol];
return [Op.AppendResolvedInvokable, value.symbol, [EMPTY_ARGS_OPCODE]];
}
case 'CallExpression': {
const args = encodeArgs(value.args);
Expand All @@ -212,7 +207,11 @@ export function AppendValueCautiously({
throw new Error(`BUG: Resolved ${value.callee.name} is not appendable`);
}

return [Op.AppendResolvedInvokable, value.callee.symbol, args];
return [
Op.AppendResolvedInvokable,
value.callee.symbol,
callArgs(value.args.positional, value.args.named),
];
}

case 'Local': {
Expand Down Expand Up @@ -275,12 +274,12 @@ export function AngleBracketComponent({
blocks,
}: mir.AngleBracketComponent): WireFormat.Content.SomeInvokeComponent {
let wireTag = encodeExpr(tag);
let wirePositional = ElementParameters(params);
let wireNamed = encodeNamedArguments(named, false);
let wireSplattributes = ElementParameters(params);
let wireNamed = encodeNamedArguments(named, { insertAtPrefix: false });

let wireNamedBlocks = NamedBlocks(blocks);

const args = buildComponentArgs(wirePositional.toPresentArray(), wireNamed, wireNamedBlocks);
const args = buildComponentArgs(wireSplattributes.toPresentArray(), wireNamed, wireNamedBlocks);

localAssert(
isTupleExpression(wireTag),
Expand Down Expand Up @@ -412,7 +411,7 @@ export function WithDynamicVars({
}: mir.WithDynamicVars): WireFormat.Content.WithDynamicVars {
return [
Op.WithDynamicVars,
encodeNamedArguments(named, false),
encodeNamedArguments(named, { insertAtPrefix: false }),
namedBlock(block.body, block.scope),
];
}
Expand All @@ -429,15 +428,23 @@ export function InvokeComponentKeyword({
`[BUG] {{component <KW>}} is not a valid node`
);

return [Op.InvokeComponentKeyword, expression, BlockArgs(args, blocks, { insertAtPrefix: true })];
return [
Op.InvokeComponentKeyword,
expression,
encodeComponentBlockArgs(args.positional, args.named, blocks),
];
}

export function InvokeResolvedComponentKeyword({
definition,
args,
blocks,
}: mir.InvokeResolvedComponentKeyword): WireFormat.Content.InvokeComponentKeyword {
return [Op.InvokeComponentKeyword, definition, BlockArgs(args, blocks, { insertAtPrefix: true })];
return [
Op.InvokeComponentKeyword,
definition,
encodeComponentBlockArgs(args.positional, args.named, blocks),
];
}

export type StaticAttrArgs = [name: string | WellKnownAttrName, value: string, namespace?: string];
Expand Down
Loading

0 comments on commit a5f57d9

Please sign in to comment.