Try parsing signatures only if node is callable, see #149; Minor refactoring

This commit is contained in:
dcodeIO
2018-06-24 01:04:24 +02:00
parent 7a8995b18b
commit 188b4e48ce
14 changed files with 933 additions and 813 deletions

View File

@ -9,7 +9,7 @@ import {
STATIC_DELIMITER,
INSTANCE_DELIMITER,
LIBRARY_PREFIX
} from "./program";
} from "./common";
import {
Token,
@ -110,6 +110,26 @@ export function nodeIsConstantValue(kind: NodeKind): bool {
return false;
}
/** Checks if a node might be callable. */
export function nodeIsCallable(kind: NodeKind): bool {
switch (kind) {
case NodeKind.IDENTIFIER:
case NodeKind.CALL:
case NodeKind.ELEMENTACCESS:
case NodeKind.PROPERTYACCESS: return true;
}
return false;
}
/** Checks if a node might be callable with generic arguments. */
export function nodeIsGenericCallable(kind: NodeKind): bool {
switch (kind) {
case NodeKind.IDENTIFIER:
case NodeKind.PROPERTYACCESS: return true;
}
return false;
}
/** Base class of all nodes. */
export abstract class Node {

94
src/common.ts Normal file
View File

@ -0,0 +1,94 @@
/**
* Common constants.
* @module common
*//***/
/** Indicates traits of a {@link Node} or {@link Element}. */
export enum CommonFlags {
/** No flags set. */
NONE = 0,
// Basic modifiers
/** Has an `import` modifier. */
IMPORT = 1 << 0,
/** Has an `export` modifier. */
EXPORT = 1 << 1,
/** Has a `declare` modifier. */
DECLARE = 1 << 2,
/** Has a `const` modifier. */
CONST = 1 << 3,
/** Has a `let` modifier. */
LET = 1 << 4,
/** Has a `static` modifier. */
STATIC = 1 << 5,
/** Has a `readonly` modifier. */
READONLY = 1 << 6,
/** Has an `abstract` modifier. */
ABSTRACT = 1 << 7,
/** Has a `public` modifier. */
PUBLIC = 1 << 8,
/** Has a `private` modifier. */
PRIVATE = 1 << 9,
/** Has a `protected` modifier. */
PROTECTED = 1 << 10,
/** Has a `get` modifier. */
GET = 1 << 11,
/** Has a `set` modifier. */
SET = 1 << 12,
// Extended modifiers usually derived from basic modifiers
/** Is ambient, that is either declared or nested in a declared element. */
AMBIENT = 1 << 13,
/** Is generic. */
GENERIC = 1 << 14,
/** Is part of a generic context. */
GENERIC_CONTEXT = 1 << 15,
/** Is an instance member. */
INSTANCE = 1 << 16,
/** Is a constructor. */
CONSTRUCTOR = 1 << 17,
/** Is an arrow function. */
ARROW = 1 << 18,
/** Is a module export. */
MODULE_EXPORT = 1 << 19,
/** Is a module import. */
MODULE_IMPORT = 1 << 20,
// Compilation states
/** Is a builtin. */
BUILTIN = 1 << 21,
/** Is compiled. */
COMPILED = 1 << 22,
/** Has a constant value and is therefore inlined. */
INLINED = 1 << 23,
/** Is scoped. */
SCOPED = 1 << 24,
/** Is a trampoline. */
TRAMPOLINE = 1 << 25,
/** Is a virtual method. */
VIRTUAL = 1 << 26
}
/** Path delimiter inserted between file system levels. */
export const PATH_DELIMITER = "/";
/** Substitution used to indicate the parent directory. */
export const PARENT_SUBST = "..";
/** Function name prefix used for getters. */
export const GETTER_PREFIX = "get:";
/** Function name prefix used for setters. */
export const SETTER_PREFIX = "set:";
/** Delimiter used between class names and instance members. */
export const INSTANCE_DELIMITER = "#";
/** Delimiter used between class and namespace names and static members. */
export const STATIC_DELIMITER = ".";
/** Delimiter used between a function and its inner elements. */
export const INNER_DELIMITER = "~";
/** Substitution used to indicate a library directory. */
export const LIBRARY_SUBST = "~lib";
/** Library directory prefix. */
export const LIBRARY_PREFIX = LIBRARY_SUBST + PATH_DELIMITER;
/** Prefix used to indicate a filespace element. */
export const FILESPACE_PREFIX = "file:";

View File

@ -36,6 +36,16 @@ import {
getGetLocalIndex
} from "./module";
import {
CommonFlags,
PATH_DELIMITER,
INNER_DELIMITER,
INSTANCE_DELIMITER,
STATIC_DELIMITER,
GETTER_PREFIX,
SETTER_PREFIX
} from "./common";
import {
Program,
ClassPrototype,
@ -54,18 +64,10 @@ import {
Property,
VariableLikeElement,
FlowFlags,
CommonFlags,
ConstantValueKind,
Flow,
OperatorKind,
DecoratorFlags,
PATH_DELIMITER,
INNER_DELIMITER,
INSTANCE_DELIMITER,
STATIC_DELIMITER,
GETTER_PREFIX,
SETTER_PREFIX
DecoratorFlags
} from "./program";
import {
@ -1487,17 +1489,11 @@ export class Compiler extends DiagnosticEmitter {
this.currentFunction.flow = blockFlow;
var stmts = this.compileStatements(statements);
var lastType: NativeType;
var stmt = stmts.length == 0
? this.module.createNop()
: stmts.length == 1
? stmts[0]
: this.module.createBlock(null, stmts,
// if the last expression is a value, annotate the block's return value
(lastType = getExpressionType(stmts[stmts.length - 1])) == NativeType.None
? NativeType.None
: lastType
);
: this.module.createBlock(null, stmts,getExpressionType(stmts[stmts.length - 1]));
// Switch back to the parent flow
var parentFlow = blockFlow.leaveBranchOrScope();

View File

@ -3,10 +3,13 @@
* @module definitions
*//***/
import {
CommonFlags
} from "./common";
import {
Program,
Element,
CommonFlags,
ElementKind,
Global,
Enum,

View File

@ -92,7 +92,7 @@ import {
import {
CommonFlags
} from "../program";
} from "../common";
/** An AST builder. */
export class ASTBuilder {

View File

@ -34,8 +34,7 @@ import {
} from "./parser";
import {
Program,
LIBRARY_PREFIX
Program
} from "./program";
/** Parses a source file. If `parser` has been omitted a new one is created. */
@ -168,4 +167,4 @@ export function buildTSD(program: Program): string {
}
/** Prefix indicating a library file. */
export { LIBRARY_PREFIX };
export { LIBRARY_PREFIX } from "./common";

View File

@ -4,10 +4,13 @@
*//***/
import {
Program,
CommonFlags,
LIBRARY_PREFIX,
PATH_DELIMITER
} from "./common";
import {
Program
} from "./program";
import {
@ -77,7 +80,9 @@ import {
VoidStatement,
WhileStatement,
mangleInternalPath
mangleInternalPath,
nodeIsCallable,
nodeIsGenericCallable
} from "./ast";
const builtinsFile = LIBRARY_PREFIX + "builtins.ts";
@ -3113,16 +3118,18 @@ export class Parser extends DiagnosticEmitter {
if (!expr) return null;
var startPos = expr.range.start;
// CallExpression with type arguments
var typeArguments: CommonTypeNode[] | null;
while (
// there might be better ways to distinguish a LESSTHAN from a CALL with type arguments
(typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn)) ||
tn.skip(Token.OPENPAREN)
) {
let args = this.parseArguments(tn);
if (!args) return null;
expr = Node.createCallExpression(expr, typeArguments, args, tn.range(startPos, tn.pos));
// CallExpression?
if (nodeIsCallable(expr.kind)) {
let typeArguments: CommonTypeNode[] | null = null;
while (
tn.skip(Token.OPENPAREN)
||
nodeIsGenericCallable(expr.kind) && (typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn)) !== null
) {
let args = this.parseArguments(tn);
if (!args) return null;
expr = Node.createCallExpression(expr, typeArguments, args, tn.range(startPos, tn.pos)); // is again callable
}
}
var token: Token;

View File

@ -3,6 +3,17 @@
* @module program
*//***/
import {
CommonFlags,
PATH_DELIMITER,
STATIC_DELIMITER,
INSTANCE_DELIMITER,
LIBRARY_PREFIX,
GETTER_PREFIX,
SETTER_PREFIX,
FILESPACE_PREFIX
} from "./common";
import {
Options
} from "./compiler";
@ -18,7 +29,6 @@ import {
TypeKind,
TypeFlags,
Signature,
typesToString
} from "./types";
@ -105,27 +115,6 @@ import {
CharCode
} from "./util";
/** Path delimiter inserted between file system levels. */
export const PATH_DELIMITER = "/";
/** Substitution used to indicate the parent directory. */
export const PARENT_SUBST = "..";
/** Function name prefix used for getters. */
export const GETTER_PREFIX = "get:";
/** Function name prefix used for setters. */
export const SETTER_PREFIX = "set:";
/** Delimiter used between class names and instance members. */
export const INSTANCE_DELIMITER = "#";
/** Delimiter used between class and namespace names and static members. */
export const STATIC_DELIMITER = ".";
/** Delimiter used between a function and its inner elements. */
export const INNER_DELIMITER = "~";
/** Substitution used to indicate a library directory. */
export const LIBRARY_SUBST = "~lib";
/** Library directory prefix. */
export const LIBRARY_PREFIX = LIBRARY_SUBST + PATH_DELIMITER;
/** Prefix used to indicate a filespace element. */
export const FILESPACE_PREFIX = "file:";
/** Represents a yet unresolved import. */
class QueuedImport {
localName: string;
@ -2415,6 +2404,16 @@ export class Program extends DiagnosticEmitter {
);
return null;
}
// resolveExpressionType(
// expression: Expression,
// contextualFunction: Function
// ): Type {
// var element = this.resolveExpression(expression, contextualFunction);
// switch (element.kind) {
// }
// }
}
/** Indicates the specific kind of an {@link Element}. */
@ -2453,75 +2452,6 @@ export enum ElementKind {
FILESPACE,
}
/** Indicates traits of a {@link Node} or {@link Element}. */
export enum CommonFlags {
/** No flags set. */
NONE = 0,
// Basic modifiers
/** Has an `import` modifier. */
IMPORT = 1 << 0,
/** Has an `export` modifier. */
EXPORT = 1 << 1,
/** Has a `declare` modifier. */
DECLARE = 1 << 2,
/** Has a `const` modifier. */
CONST = 1 << 3,
/** Has a `let` modifier. */
LET = 1 << 4,
/** Has a `static` modifier. */
STATIC = 1 << 5,
/** Has a `readonly` modifier. */
READONLY = 1 << 6,
/** Has an `abstract` modifier. */
ABSTRACT = 1 << 7,
/** Has a `public` modifier. */
PUBLIC = 1 << 8,
/** Has a `private` modifier. */
PRIVATE = 1 << 9,
/** Has a `protected` modifier. */
PROTECTED = 1 << 10,
/** Has a `get` modifier. */
GET = 1 << 11,
/** Has a `set` modifier. */
SET = 1 << 12,
// Extended modifiers usually derived from basic modifiers
/** Is ambient, that is either declared or nested in a declared element. */
AMBIENT = 1 << 13,
/** Is generic. */
GENERIC = 1 << 14,
/** Is part of a generic context. */
GENERIC_CONTEXT = 1 << 15,
/** Is an instance member. */
INSTANCE = 1 << 16,
/** Is a constructor. */
CONSTRUCTOR = 1 << 17,
/** Is an arrow function. */
ARROW = 1 << 18,
/** Is a module export. */
MODULE_EXPORT = 1 << 19,
/** Is a module import. */
MODULE_IMPORT = 1 << 20,
// Compilation states
/** Is a builtin. */
BUILTIN = 1 << 21,
/** Is compiled. */
COMPILED = 1 << 22,
/** Has a constant value and is therefore inlined. */
INLINED = 1 << 23,
/** Is scoped. */
SCOPED = 1 << 24,
/** Is a trampoline. */
TRAMPOLINE = 1 << 25,
/** Is a virtual method. */
VIRTUAL = 1 << 26
}
export enum DecoratorFlags {
/** No flags set. */
NONE = 0,