Skip inlining and emit a warning when trying to inline a function into itself

This commit is contained in:
dcodeIO
2018-07-14 18:01:19 +02:00
parent 3b0fd9aac2
commit 4b8500355a
12 changed files with 52 additions and 9 deletions

View File

@ -54,7 +54,6 @@ import {
import {
ReportMode
} from "./resolver";
import { CommonFlags } from "./common";
/** Compiles a call to a built-in function. */
export function compileCall(
@ -73,7 +72,7 @@ export function compileCall(
ret: ExpressionRef;
// NOTE that some implementations below make use of the select expression where straight-forward.
// whether worth or not should probably be tested once/ it's known if/how embedders handle it.
// whether worth or not should probably be tested once it's known if/how embedders handle it.
// search: createSelect
switch (prototype.internalName) {

View File

@ -265,6 +265,8 @@ export class Compiler extends DiagnosticEmitter {
currentFunction: Function;
/** Current outer function in compilation, if compiling a function expression. */
currentOuterFunction: Function | null = null;
/** Current inline function in compilation. */
currentInlineFunction: Function | null = null;
/** Current enum in compilation. */
currentEnum: Enum | null = null;
/** Current type in compilation. */
@ -5257,7 +5259,21 @@ export class Compiler extends DiagnosticEmitter {
// Inline if explicitly requested
if (inline) {
assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense
return this.compileCallInlineUnchecked(instance, argumentExpressions, reportNode, thisArg);
if (instance === this.currentInlineFunction) {
// skip inlining when trying to inline a function into itself and print a warning when
// instead compiling the function the normal way.
if (instance === this.currentFunction) {
this.warning(
DiagnosticCode.Function_0_cannot_be_inlined_into_itself,
reportNode.range, instance.internalName
);
}
} else {
this.currentInlineFunction = instance;
let ret = this.compileCallInlineUnchecked(instance, argumentExpressions, reportNode, thisArg);
this.currentInlineFunction = null;
return ret;
}
}
// Otherwise compile to just a call

View File

@ -26,6 +26,7 @@ export enum DiagnosticCode {
An_allocator_must_be_declared_to_allocate_memory_Try_importing_allocator_arena_or_allocator_tlsf = 214,
Optional_parameter_must_have_an_initializer = 215,
Constructor_of_class_0_must_not_require_any_arguments = 216,
Function_0_cannot_be_inlined_into_itself = 217,
Unterminated_string_literal = 1002,
Identifier_expected = 1003,
_0_expected = 1005,
@ -142,6 +143,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 214: return "An allocator must be declared to allocate memory. Try importing allocator/arena or allocator/tlsf.";
case 215: return "Optional parameter must have an initializer.";
case 216: return "Constructor of class '{0}' must not require any arguments.";
case 217: return "Function '{0}' cannot be inlined into itself.";
case 1002: return "Unterminated string literal.";
case 1003: return "Identifier expected.";
case 1005: return "'{0}' expected.";

View File

@ -18,6 +18,7 @@
"An allocator must be declared to allocate memory. Try importing allocator/arena or allocator/tlsf.": 214,
"Optional parameter must have an initializer.": 215,
"Constructor of class '{0}' must not require any arguments.": 216,
"Function '{0}' cannot be inlined into itself.": 217,
"Unterminated string literal.": 1002,
"Identifier expected.": 1003,