X Tutup
Skip to content
Merged
18 changes: 16 additions & 2 deletions language-extensions/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
declare function $multi<T extends any[]>(...values: T): MultiReturn<T>;
declare type MultiReturn<T extends any[]> = T & { readonly " __multiBrand": unique symbol };
/**
* Returns multiple values from a function, by wrapping them in a LuaMultiReturn tuple.
* For more information see: https://typescripttolua.github.io/docs/advanced/language-extensions
*
* @param T A tuple type with each element type representing a return value's type.
* @param values Return values.
*/
declare function $multi<T extends any[]>(...values: T): LuaMultiReturn<T>;

/**
* Represents multiple return values as a tuple.
* For more information see: https://typescripttolua.github.io/docs/advanced/language-extensions
*
* @param T A tuple type with each element type representing a return value's type.
*/
declare type LuaMultiReturn<T extends any[]> = T & { readonly __luaMultiReturnBrand: unique symbol };

/**
* Calls to functions with this type are translated to `left + right`.
Expand Down
3 changes: 2 additions & 1 deletion src/lualib/StringIncludes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ function __TS__StringIncludes(this: string, searchString: string, position?: num
} else {
position += 1;
}
return string.find(this, searchString, position, true) !== undefined;
const [index] = string.find(this, searchString, position, true);
return index !== undefined;
}
2 changes: 1 addition & 1 deletion src/lualib/declarations/string.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ declare namespace string {
pattern: string,
start?: number,
plainflag?: boolean
): MultiReturn<[number, number]> | undefined;
): LuaMultiReturn<[number, number] | [undefined]>;
}
20 changes: 4 additions & 16 deletions src/transformation/utils/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ export const unsupportedVarDeclaration = createErrorDiagnosticFactory(
);

export const invalidMultiFunctionUse = createErrorDiagnosticFactory(
"The $multi function must be called in an expression that is returned."
"The $multi function must be called in a return statement."
);

export const invalidMultiTypeToNonArrayBindingPattern = createErrorDiagnosticFactory(
"Expected an array destructuring pattern."
export const invalidMultiFunctionReturnType = createErrorDiagnosticFactory(
"The $multi function cannot be cast to a non-LuaMultiReturn type."
);

export const invalidMultiTypeToNonArrayLiteral = createErrorDiagnosticFactory("Expected an array literal.");
Expand All @@ -156,20 +156,8 @@ export const invalidMultiTypeToEmptyPatternOrArrayLiteral = createErrorDiagnosti
"There must be one or more elements specified here."
);

export const invalidMultiTypeArrayBindingPatternElementInitializer = createErrorDiagnosticFactory(
"This array binding pattern cannot have initializers."
);

export const invalidMultiTypeArrayLiteralElementInitializer = createErrorDiagnosticFactory(
"This array literal pattern cannot have initializers."
);

export const invalidMultiReturnAccess = createErrorDiagnosticFactory(
"The MultiReturn type can only be accessed via an element access expression of a numeric type."
);

export const unsupportedMultiFunctionAssignment = createErrorDiagnosticFactory(
"Omitted expressions and BindingElements are expected here."
"The LuaMultiReturn type can only be accessed via an element access expression of a numeric type."
);

export const invalidOperatorMappingUse = createErrorDiagnosticFactory(
Expand Down
2 changes: 1 addition & 1 deletion src/transformation/utils/language-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export enum ExtensionKind {
}

const typeNameToExtensionKind: { [name: string]: ExtensionKind } = {
MultiReturn: ExtensionKind.MultiType,
LuaMultiReturn: ExtensionKind.MultiType,
LuaAddition: ExtensionKind.AdditionOperatorType,
LuaAdditionMethod: ExtensionKind.AdditionOperatorMethodType,
LuaSubtraction: ExtensionKind.SubtractionOperatorType,
Expand Down
10 changes: 7 additions & 3 deletions src/transformation/visitors/binary-expression/assignments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { isArrayType, isDestructuringAssignment } from "../../utils/typescript";
import { transformElementAccessArgument } from "../access";
import { transformLuaTablePropertyAccessInAssignment } from "../lua-table";
import { isArrayLength, transformDestructuringAssignment } from "./destructuring-assignments";
import { isMultiReturnCall } from "../language-extensions/multi";

export function transformAssignmentLeftHandSideExpression(
context: TransformationContext,
Expand Down Expand Up @@ -91,7 +92,7 @@ export function transformAssignmentExpression(
const rootIdentifier = lua.createAnonymousIdentifier(expression.left);

let right = context.transformExpression(expression.right);
if (isTupleReturnCall(context, expression.right)) {
if (isTupleReturnCall(context, expression.right) || isMultiReturnCall(context, expression.right)) {
right = wrapInTable(right);
}

Expand Down Expand Up @@ -184,7 +185,10 @@ export function transformAssignmentStatement(
const rightType = context.checker.getTypeAtLocation(expression.right);
let right = context.transformExpression(expression.right);

if (!isTupleReturnCall(context, expression.right) && isArrayType(context, rightType)) {
if (
!(isTupleReturnCall(context, expression.right) || isMultiReturnCall(context, expression.right)) &&
isArrayType(context, rightType)
) {
right = createUnpackCall(context, right, expression.right);
}

Expand All @@ -194,7 +198,7 @@ export function transformAssignmentStatement(
}

let right = context.transformExpression(expression.right);
if (isTupleReturnCall(context, expression.right)) {
if (isTupleReturnCall(context, expression.right) || isMultiReturnCall(context, expression.right)) {
right = wrapInTable(right);
}

Expand Down
5 changes: 3 additions & 2 deletions src/transformation/visitors/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { isValidLuaIdentifier } from "../utils/safe-names";
import { isArrayType, isExpressionWithEvaluationEffect, isInDestructingAssignment } from "../utils/typescript";
import { transformElementAccessArgument } from "./access";
import { transformLuaTableCallExpression } from "./lua-table";
import { returnsMultiType } from "./language-extensions/multi";
import { shouldMultiReturnCallBeWrapped, returnsMultiType } from "./language-extensions/multi";
import { isOperatorMapping, transformOperatorMappingExpression } from "./language-extensions/operators";

export type PropertyCallExpression = ts.CallExpression & { expression: ts.PropertyAccessExpression };
Expand Down Expand Up @@ -201,8 +201,9 @@ export const transformCallExpression: FunctionVisitor<ts.CallExpression> = (node
node.parent && ts.isReturnStatement(node.parent) && isInTupleReturnFunction(context, node);
const isInSpread = node.parent && ts.isSpreadElement(node.parent);
const returnValueIsUsed = node.parent && !ts.isExpressionStatement(node.parent);
const wrapResult =
const wrapTupleReturn =
isTupleReturn && !isTupleReturnForward && !isInDestructingAssignment(node) && !isInSpread && returnValueIsUsed;
const wrapResult = wrapTupleReturn || shouldMultiReturnCallBeWrapped(context, node);

const builtinResult = transformBuiltinCallExpression(context, node);
if (builtinResult) {
Expand Down
3 changes: 2 additions & 1 deletion src/transformation/visitors/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createUnpackCall } from "../utils/lua-ast";
import { findScope, ScopeType } from "../utils/scope";
import { transformScopeBlock } from "./block";
import { transformIdentifier } from "./identifier";
import { isInMultiReturnFunction } from "./language-extensions/multi";

export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statement, context) => {
const [tryBlock, tryScope] = transformScopeBlock(context, statement.tryBlock, ScopeType.Try);
Expand Down Expand Up @@ -88,7 +89,7 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
returnValues.push(lua.createBooleanLiteral(true));
}

if (isInTupleReturnFunction(context, statement)) {
if (isInTupleReturnFunction(context, statement) || isInMultiReturnFunction(context, statement)) {
returnValues.push(createUnpackCall(context, lua.cloneIdentifier(returnValueIdentifier)));
} else {
returnValues.push(lua.cloneIdentifier(returnValueIdentifier));
Expand Down
10 changes: 0 additions & 10 deletions src/transformation/visitors/expression-statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,8 @@ import { FunctionVisitor } from "../context";
import { transformBinaryExpressionStatement } from "./binary-expression";
import { transformLuaTableExpressionStatement } from "./lua-table";
import { transformUnaryExpressionStatement } from "./unary-expression";
import { returnsMultiType, transformMultiDestructuringAssignmentStatement } from "./language-extensions/multi";

export const transformExpressionStatement: FunctionVisitor<ts.ExpressionStatement> = (node, context) => {
if (
ts.isBinaryExpression(node.expression) &&
node.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
ts.isCallExpression(node.expression.right) &&
returnsMultiType(context, node.expression.right)
) {
return transformMultiDestructuringAssignmentStatement(context, node);
}

const luaTableResult = transformLuaTableExpressionStatement(context, node);
if (luaTableResult) {
return luaTableResult;
Expand Down
5 changes: 0 additions & 5 deletions src/transformation/visitors/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
import { peekScope, performHoisting, popScope, pushScope, Scope, ScopeType } from "../utils/scope";
import { transformIdentifier } from "./identifier";
import { isMultiFunction, transformMultiCallExpressionToReturnStatement } from "./language-extensions/multi";
import { transformExpressionBodyToReturnStatement } from "./return";
import { transformBindingPattern } from "./variable-declaration";

Expand Down Expand Up @@ -56,10 +55,6 @@ function isRestParameterReferenced(context: TransformationContext, identifier: l

export function transformFunctionBodyContent(context: TransformationContext, body: ts.ConciseBody): lua.Statement[] {
if (!ts.isBlock(body)) {
if (ts.isCallExpression(body) && isMultiFunction(context, body)) {
return [transformMultiCallExpressionToReturnStatement(context, body)];
}

const returnStatement = transformExpressionBodyToReturnStatement(context, body);
return [returnStatement];
}
Expand Down
Loading
X Tutup