Skip to content

Commit

Permalink
Replace OperationInstanceNode with OperationSignature types
Browse files Browse the repository at this point in the history
  • Loading branch information
daviwil committed May 25, 2022
1 parent 98bc1f6 commit 4d14e95
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 136 deletions.
6 changes: 1 addition & 5 deletions packages/compiler/core/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
ModelStatementNode,
NamespaceStatementNode,
Node,
OperationInstanceNode,
OperationStatementNode,
ProjectionLambdaExpressionNode,
ProjectionLambdaParameterDeclarationNode,
Expand Down Expand Up @@ -203,9 +202,6 @@ export function createBinder(program: Program, options: BinderOptions = {}): Bin
case SyntaxKind.OperationStatement:
bindOperationStatement(node);
break;
case SyntaxKind.OperationInstance:
bindOperationStatement(node);
break;
case SyntaxKind.TemplateParameterDeclaration:
bindTemplateParameterDeclaration(node);
break;
Expand Down Expand Up @@ -390,7 +386,7 @@ export function createBinder(program: Program, options: BinderOptions = {}): Bin
(currentFile.usings as UsingStatementNode[]).push(statement);
}

function bindOperationStatement(statement: OperationStatementNode | OperationInstanceNode) {
function bindOperationStatement(statement: OperationStatementNode) {
if (scope.kind !== SyntaxKind.InterfaceStatement) {
declareSymbol(statement, SymbolFlags.Operation);
}
Expand Down
52 changes: 13 additions & 39 deletions packages/compiler/core/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import {
NodeFlags,
NumericLiteralNode,
NumericLiteralType,
OperationInstanceNode,
OperationStatementNode,
OperationType,
ProjectionArithmeticExpressionNode,
Expand Down Expand Up @@ -379,8 +378,6 @@ export function createChecker(program: Program): Checker {
return checkNamespace(node);
case SyntaxKind.OperationStatement:
return checkOperation(node);
case SyntaxKind.OperationInstance:
return checkOperation(node);
case SyntaxKind.NumericLiteral:
return checkNumericLiteral(node);
case SyntaxKind.BooleanLiteral:
Expand Down Expand Up @@ -471,7 +468,6 @@ export function createChecker(program: Program): Checker {
| AliasStatementNode
| InterfaceStatementNode
| OperationStatementNode
| OperationInstanceNode
| UnionStatementNode
): number {
return node.symbol!.id!;
Expand Down Expand Up @@ -499,7 +495,6 @@ export function createChecker(program: Program): Checker {
| ModelStatementNode
| InterfaceStatementNode
| OperationStatementNode
| OperationInstanceNode
| UnionStatementNode
| AliasStatementNode;
const links = getSymbolLinks(node.symbol);
Expand Down Expand Up @@ -688,7 +683,6 @@ export function createChecker(program: Program): Checker {
| AliasStatementNode
| InterfaceStatementNode
| OperationStatementNode
| OperationInstanceNode
| UnionStatementNode;
if (decl.templateParameters.length === 0) {
if (args.length > 0) {
Expand Down Expand Up @@ -779,7 +773,6 @@ export function createChecker(program: Program): Checker {
| AliasStatementNode
| InterfaceStatementNode
| OperationStatementNode
| OperationInstanceNode
| UnionStatementNode,
args: Type[]
): Type {
Expand Down Expand Up @@ -969,7 +962,6 @@ export function createChecker(program: Program): Checker {
| ModelStatementNode
| NamespaceStatementNode
| OperationStatementNode
| OperationInstanceNode
| EnumStatementNode
| InterfaceStatementNode
| UnionStatementNode
Expand All @@ -983,7 +975,6 @@ export function createChecker(program: Program): Checker {
if (
parent.kind === SyntaxKind.ModelStatement ||
parent.kind === SyntaxKind.OperationStatement ||
parent.kind === SyntaxKind.OperationInstance ||
parent.kind === SyntaxKind.EnumStatement ||
parent.kind === SyntaxKind.InterfaceStatement ||
parent.kind === SyntaxKind.UnionStatement ||
Expand All @@ -998,7 +989,7 @@ export function createChecker(program: Program): Checker {
}

if (
(node.kind === SyntaxKind.OperationStatement || node.kind === SyntaxKind.OperationInstance) &&
node.kind === SyntaxKind.OperationStatement &&
node.parent &&
node.parent.kind === SyntaxKind.InterfaceStatement
) {
Expand Down Expand Up @@ -1034,7 +1025,7 @@ export function createChecker(program: Program): Checker {
}

function checkOperation(
node: OperationStatementNode | OperationInstanceNode,
node: OperationStatementNode,
parentInterface?: InterfaceType
): OperationType | ErrorType {
const links = getSymbolLinks(node.symbol);
Expand All @@ -1046,44 +1037,27 @@ export function createChecker(program: Program): Checker {

const namespace = getParentNamespaceType(node);
const name = node.id.sv;
const decorators = checkDecorators(node);
let decorators = checkDecorators(node);

// Is this a definition or instance?
// Is this a definition or reference?
let parameters: ModelType, returnType: Type;
if (node.kind === SyntaxKind.OperationInstance) {
if (node.signature.kind === "Reference") {
// Attempt to resolve the operation
const baseOperation = checkOperationIs(node, node.baseOperation);
const baseOperation = checkOperationIs(node, node.signature.baseOperation);
if (!baseOperation) {
// TODO: Are the proper diagnostics written already?
return errorType;
}

// Reference the same return type and create the parameters type
parameters = cloneType(baseOperation.parameters);
returnType = baseOperation.returnType;
parameters = createType({
kind: "Model",
name: "",
node: baseOperation.parameters.node, // TODO: This seems bad!
properties: new Map<string, ModelTypeProperty>(),
namespace: getParentNamespaceType(node),
decorators: [],
derivedModels: [],
});

// Copy parameters of the base operation
for (const prop of baseOperation.parameters.properties.values()) {
console.log("copying param:", prop.name, (prop.type as any).kind);
// Don't use the same property, clone it and finish it to execute the decorators again
parameters.properties.set(
prop.name,
finishType({
...prop,
})
);
}
// Copy decorators from the base operation, inserting the base decorators first
decorators = [...baseOperation.decorators, ...decorators];
} else {
parameters = getTypeForNode(node.parameters) as ModelType;
returnType = getTypeForNode(node.returnType);
parameters = getTypeForNode(node.signature.parameters) as ModelType;
returnType = getTypeForNode(node.signature.returnType);
}

const operationType: OperationType = createType({
Expand All @@ -1093,7 +1067,7 @@ export function createChecker(program: Program): Checker {
node,
parameters,
returnType,
decorators, // TODO: Concatenate base operation decorators recursively!
decorators,
interface: parentInterface,
});

Expand All @@ -1120,7 +1094,7 @@ export function createChecker(program: Program): Checker {
}

function checkOperationIs(
operation: OperationInstanceNode,
operation: OperationStatementNode,
opReference: TypeReferenceNode | undefined
): OperationType | undefined {
if (!opReference) return undefined;
Expand Down
78 changes: 29 additions & 49 deletions packages/compiler/core/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
Node,
NodeFlags,
NumericLiteralNode,
OperationInstanceNode,
OperationSignature,
OperationStatementNode,
ProjectionBlockExpressionNode,
ProjectionEnumSelectorNode,
Expand Down Expand Up @@ -509,7 +509,9 @@ export function parse(code: string | SourceFile, options: ParseOptions = {}): Ca
nextToken();
}

const operations = parseList(ListKind.InterfaceMembers, parseInterfaceMember);
const operations = parseList(ListKind.InterfaceMembers, (pos, decorators) =>
parseOperationStatement(pos, decorators, true)
);

return {
kind: SyntaxKind.InterfaceStatement,
Expand Down Expand Up @@ -539,28 +541,6 @@ export function parse(code: string | SourceFile, options: ParseOptions = {}): Ca
return list;
}

function parseInterfaceMember(
pos: number,
decorators: DecoratorExpressionNode[]
): OperationStatementNode {
parseOptional(Token.OpKeyword);

const id = parseIdentifier();
const parameters = parseOperationParameters();
parseExpected(Token.Colon);

const returnType = parseExpression();
return {
kind: SyntaxKind.OperationStatement,
id,
templateParameters: [],
parameters,
returnType,
decorators,
...finishNode(pos),
};
}

function parseUnionStatement(
pos: number,
decorators: DecoratorExpressionNode[]
Expand Down Expand Up @@ -612,45 +592,50 @@ export function parse(code: string | SourceFile, options: ParseOptions = {}): Ca

function parseOperationStatement(
pos: number,
decorators: DecoratorExpressionNode[]
): OperationStatementNode | OperationInstanceNode {
parseExpected(Token.OpKeyword);
decorators: DecoratorExpressionNode[],
inInterface?: boolean
): OperationStatementNode {
if (inInterface) {
parseOptional(Token.OpKeyword);
} else {
parseExpected(Token.OpKeyword);
}

const id = parseIdentifier();
const templateParameters = parseTemplateParameterList();

// Check if we're parsing a declaration or reuse of another operation
let signature: OperationSignature;
if (token() === Token.OpenParen) {
const parameters = parseOperationParameters();
parseExpected(Token.Colon);
const returnType = parseExpression();

parseExpected(Token.Semicolon);

return {
kind: SyntaxKind.OperationStatement,
id,
templateParameters,
signature = {
kind: "Declaration",
parameters,
returnType,
decorators,
...finishNode(pos),
};
} else {
parseExpected(Token.Colon);
const opReference = parseReferenceExpression();

parseExpected(Token.Semicolon);

return {
kind: SyntaxKind.OperationInstance,
id,
templateParameters,
signature = {
kind: "Reference",
baseOperation: opReference,
decorators,
...finishNode(pos),
};
}

return {
kind: SyntaxKind.OperationStatement,
id,
templateParameters,
signature,
decorators,
...finishNode(pos),
};
}

function parseOperationParameters(): ModelExpressionNode {
Expand Down Expand Up @@ -2178,15 +2163,10 @@ export function visitChildren<T>(node: Node, cb: NodeCallback<T>): T | undefined
return (
visitEach(cb, node.decorators) ||
visitNode(cb, node.id) ||
visitNode(cb, node.parameters) ||
visitEach(cb, node.templateParameters) ||
visitNode(cb, node.returnType)
);
case SyntaxKind.OperationInstance:
return (
visitEach(cb, node.decorators) ||
visitNode(cb, node.id) ||
visitNode(cb, node.baseOperation)
(node.signature.kind === "Declaration"
? visitNode(cb, node.signature.parameters) || visitNode(cb, node.signature.returnType)
: visitNode(cb, node.signature.baseOperation))
);
case SyntaxKind.NamespaceStatement:
return (
Expand Down
22 changes: 12 additions & 10 deletions packages/compiler/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export interface EnumMemberType extends BaseType, DecoratedType {

export interface OperationType extends BaseType, DecoratedType, TemplatedType {
kind: "Operation";
node: OperationStatementNode | OperationInstanceNode;
node: OperationStatementNode;
name: string;
namespace?: NamespaceType;
interface?: InterfaceType;
Expand Down Expand Up @@ -388,7 +388,6 @@ export enum SyntaxKind {
NamespaceStatement,
UsingStatement,
OperationStatement,
OperationInstance,
ModelStatement,
ModelExpression,
ModelProperty,
Expand Down Expand Up @@ -502,7 +501,6 @@ export type Node =
| ModelPropertyNode
| UnionVariantNode
| OperationStatementNode
| OperationInstanceNode
| EnumMemberNode
| ModelSpreadPropertyNode
| DecoratorExpressionNode
Expand Down Expand Up @@ -553,7 +551,6 @@ export type Statement =
| EnumStatementNode
| AliasStatementNode
| OperationStatementNode
| OperationInstanceNode
| EmptyStatementNode
| InvalidStatementNode
| ProjectionStatementNode;
Expand All @@ -568,7 +565,6 @@ export type Declaration =
| UnionStatementNode
| NamespaceStatementNode
| OperationStatementNode
| OperationInstanceNode
| TemplateParameterDeclarationNode
| ProjectionStatementNode
| ProjectionParameterDeclarationNode
Expand Down Expand Up @@ -672,16 +668,22 @@ export interface UsingStatementNode extends BaseNode {
readonly name: IdentifierNode | MemberExpressionNode;
}

export interface OperationStatementNode extends BaseNode, DeclarationNode, TemplateDeclarationNode {
readonly kind: SyntaxKind.OperationStatement;
export interface OperationSignatureDeclaration {
readonly kind: "Declaration";
readonly parameters: ModelExpressionNode;
readonly returnType: Expression;
readonly decorators: readonly DecoratorExpressionNode[];
}

export interface OperationInstanceNode extends BaseNode, DeclarationNode, TemplateDeclarationNode {
readonly kind: SyntaxKind.OperationInstance;
export interface OperationSignatureReference {
readonly kind: "Reference";
readonly baseOperation: TypeReferenceNode;
}

export type OperationSignature = OperationSignatureDeclaration | OperationSignatureReference;

export interface OperationStatementNode extends BaseNode, DeclarationNode, TemplateDeclarationNode {
readonly kind: SyntaxKind.OperationStatement;
readonly signature: OperationSignature;
readonly decorators: readonly DecoratorExpressionNode[];
}

Expand Down
Loading

0 comments on commit 4d14e95

Please sign in to comment.