More cleanup and a possible fix for #29

This commit is contained in:
dcodeIO 2018-02-16 11:55:13 +01:00
parent f729444320
commit 3d7e8b2b7a
17 changed files with 1038 additions and 680 deletions

4
dist/asc.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1644,7 +1644,9 @@ export class WhileStatement extends Statement {
/** Cached unused modifiers for reuse. */ /** Cached unused modifiers for reuse. */
var reusableModifiers: Modifier[] | null = null; var reusableModifiers: Modifier[] | null = null;
export function setReusableModifiers(modifiers: Modifier[]) { export function setReusableModifiers(
modifiers: Modifier[]
): void {
reusableModifiers = modifiers; reusableModifiers = modifiers;
} }
@ -1660,16 +1662,22 @@ export function createModifiers(): Modifier[] {
return ret; return ret;
} }
/** Adds a modifier to a modifiers array. Creates and returns a new array if `null`. */ /** Adds a modifier to a set of modifiers. Creates a new set if `null`. */
export function addModifier(modifier: Modifier, modifiers: Modifier[] | null): Modifier[] { export function addModifier(
modifier: Modifier,
modifiers: Modifier[] | null
): Modifier[] {
if (modifiers == null) if (modifiers == null)
modifiers = createModifiers(); modifiers = createModifiers();
modifiers.push(modifier); modifiers.push(modifier);
return modifiers; return modifiers;
} }
/** Gets a specific modifier from the specified array of modifiers. */ /** Gets a specific modifier from the specified set of modifiers. */
export function getModifier(kind: ModifierKind, modifiers: Modifier[] | null): Modifier | null { export function getModifier(
kind: ModifierKind,
modifiers: Modifier[] | null
): Modifier | null {
if (modifiers) if (modifiers)
for (var i = 0, k = modifiers.length; i < k; ++i) for (var i = 0, k = modifiers.length; i < k; ++i)
if (modifiers[i].modifierKind == kind) if (modifiers[i].modifierKind == kind)
@ -1677,13 +1685,19 @@ export function getModifier(kind: ModifierKind, modifiers: Modifier[] | null): M
return null; return null;
} }
/** Tests whether a specific modifier exists in the specified array of modifiers. */ /** Tests whether a modifier exists in the specified set of modifiers. */
export function hasModifier(kind: ModifierKind, modifiers: Modifier[] | null): bool { export function hasModifier(
kind: ModifierKind,
modifiers: Modifier[] | null
): bool {
return getModifier(kind, modifiers) != null; return getModifier(kind, modifiers) != null;
} }
/** Gets a specific decorator within the specified decorators, if present. */ /** Gets the first decorator by name within at set of decorators, if present. */
export function getFirstDecorator(name: string, decorators: Decorator[] | null): Decorator | null { export function getFirstDecorator(
name: string,
decorators: Decorator[] | null
): Decorator | null {
if (decorators) if (decorators)
for (var i = 0, k = decorators.length; i < k; ++i) { for (var i = 0, k = decorators.length; i < k; ++i) {
var decorator = decorators[i]; var decorator = decorators[i];
@ -1695,12 +1709,18 @@ export function getFirstDecorator(name: string, decorators: Decorator[] | null):
} }
/** Tests if a specific decorator is present within the specified decorators. */ /** Tests if a specific decorator is present within the specified decorators. */
export function hasDecorator(name: string, decorators: Decorator[] | null): bool { export function hasDecorator(
name: string,
decorators: Decorator[] | null
): bool {
return getFirstDecorator(name, decorators) != null; return getFirstDecorator(name, decorators) != null;
} }
/** Mangles a declaration's name to an internal name. */ /** Mangles a declaration's name to an internal name. */
export function mangleInternalName(declaration: DeclarationStatement, asGlobal: bool = false): string { export function mangleInternalName(
declaration: DeclarationStatement,
asGlobal: bool = false
): string {
var name = declaration.name.text; var name = declaration.name.text;
var parent = declaration.parent; var parent = declaration.parent;
if (!parent) if (!parent)
@ -1720,18 +1740,26 @@ export function mangleInternalName(declaration: DeclarationStatement, asGlobal:
} }
/** Mangles an external to an internal path. */ /** Mangles an external to an internal path. */
export function mangleInternalPath(path: string): string { export function mangleInternalPath(
path: string
): string {
if (path.endsWith(".ts")) if (path.endsWith(".ts"))
path = path.substring(0, path.length - 3); path = path.substring(0, path.length - 3);
return path; return path;
} }
function setParent(nodes: Node[], parent: Node): void { function setParent(
nodes: Node[],
parent: Node
): void {
for (var i = 0, k = nodes.length; i < k; ++i) for (var i = 0, k = nodes.length; i < k; ++i)
nodes[i].parent = parent; nodes[i].parent = parent;
} }
function setParentOpt(nodes: (Node | null)[], parent: Node): void { function setParentOpt(
nodes: (Node | null)[],
parent: Node
): void {
for (var i = 0, k = nodes.length; i < k; ++i) { for (var i = 0, k = nodes.length; i < k; ++i) {
var node = nodes[i]; var node = nodes[i];
if (node) if (node)

View File

@ -122,10 +122,6 @@ import {
typesToNativeTypes typesToNativeTypes
} from "./types"; } from "./types";
import {
sb
} from "./util/sb";
/** Compilation target. */ /** Compilation target. */
export enum Target { export enum Target {
/** WebAssembly with 32-bit pointers. */ /** WebAssembly with 32-bit pointers. */

View File

@ -12,10 +12,6 @@ import {
isLineBreak isLineBreak
} from "./util/charcode"; } from "./util/charcode";
import {
sb
} from "./util/sb";
export { export {
DiagnosticCode, DiagnosticCode,
diagnosticCodeToString diagnosticCodeToString
@ -103,7 +99,7 @@ export function formatDiagnosticMessage(message: DiagnosticMessage, useColors: b
context = formatDiagnosticContext(message.range, useColors); context = formatDiagnosticContext(message.range, useColors);
// general information // general information
sb.length = 0; var sb: string[] = [];
if (useColors) sb.push(diagnosticCategoryToColor(message.category)); if (useColors) sb.push(diagnosticCategoryToColor(message.category));
sb.push(diagnosticCategoryToString(message.category)); sb.push(diagnosticCategoryToString(message.category));
if (useColors) sb.push(colorReset); if (useColors) sb.push(colorReset);
@ -141,10 +137,11 @@ export function formatDiagnosticContext(range: Range, useColors: bool = false):
start--; start--;
while (end < len && !isLineBreak(text.charCodeAt(end))) while (end < len && !isLineBreak(text.charCodeAt(end)))
end++; end++;
sb.length = 0; var sb: string[] = [
sb.push("\n "); "\n ",
sb.push(text.substring(start, end)); text.substring(start, end),
sb.push("\n "); "\n "
];
while (start < range.start) { while (start < range.start) {
sb.push(" "); sb.push(" ");
start++; start++;

File diff suppressed because it is too large Load Diff

View File

@ -239,14 +239,7 @@ export class Parser extends DiagnosticEmitter {
/** Obtains the next file to parse. */ /** Obtains the next file to parse. */
nextFile(): string | null { nextFile(): string | null {
if (this.backlog.length) { return this.backlog.length ? this.backlog.shift() : null;
var filename = this.backlog[0];
for (var i = 0, k = this.backlog.length - 1; i < k; ++i)
this.backlog[i] = this.backlog[i + 1];
this.backlog.length--;
return filename;
}
return null;
} }
/** Finishes parsing and returns the program. */ /** Finishes parsing and returns the program. */

View File

@ -96,6 +96,7 @@ class QueuedExport {
class QueuedImport { class QueuedImport {
internalName: string; internalName: string;
referencedName: string; referencedName: string;
referencedNameAlt: string;
declaration: ImportDeclaration; declaration: ImportDeclaration;
} }
@ -209,8 +210,14 @@ export class Program extends DiagnosticEmitter {
this.elements.set(queuedImport.internalName, element); this.elements.set(queuedImport.internalName, element);
queuedImports.splice(i, 1); queuedImports.splice(i, 1);
} else { } else {
this.error(DiagnosticCode.Module_0_has_no_exported_member_1, queuedImport.declaration.range, (<ImportStatement>queuedImport.declaration.parent).path.value, queuedImport.declaration.externalName.text); element = this.tryResolveImport(queuedImport.referencedNameAlt, queuedExports);
++i; if (element) {
this.elements.set(queuedImport.internalName, element);
queuedImports.splice(i, 1);
} else {
this.error(DiagnosticCode.Module_0_has_no_exported_member_1, queuedImport.declaration.range, (<ImportStatement>queuedImport.declaration.parent).path.value, queuedImport.declaration.externalName.text);
++i;
}
} }
} }
@ -756,38 +763,24 @@ export class Program extends DiagnosticEmitter {
var referencedName = internalPath + PATH_DELIMITER + declaration.externalName.text; var referencedName = internalPath + PATH_DELIMITER + declaration.externalName.text;
// resolve right away if the export exists // resolve right away if the exact export exists
if (this.exports.has(referencedName)) { var element: Element | null;
this.elements.set(internalName, <Element>this.exports.get(referencedName)); if (element = this.exports.get(referencedName)) {
this.elements.set(internalName, element);
return; return;
} }
// walk already known queued exports
var seen = new Set<QueuedExport>();
var queuedExport: QueuedExport | null;
while (queuedExport = queuedExports.get(referencedName)) {
if (queuedExport.isReExport) {
if (this.exports.has(queuedExport.referencedName)) {
this.elements.set(internalName, <Element>this.exports.get(referencedName));
return;
}
referencedName = queuedExport.referencedName;
if (seen.has(queuedExport))
break;
seen.add(queuedExport);
} else {
if (this.elements.has(queuedExport.referencedName)) {
this.elements.set(internalName, <Element>this.elements.get(referencedName));
return;
}
break;
}
}
// otherwise queue it // otherwise queue it
var indexPart = PATH_DELIMITER + "index";
var queuedImport = new QueuedImport(); var queuedImport = new QueuedImport();
queuedImport.internalName = internalName; queuedImport.internalName = internalName;
queuedImport.referencedName = referencedName; if (internalPath.endsWith(indexPart)) {
queuedImport.referencedName = referencedName; // try exact first
queuedImport.referencedNameAlt = internalPath.substring(0, internalPath.length - indexPart.length + 1) + declaration.externalName.text;
} else {
queuedImport.referencedName = referencedName; // try exact first
queuedImport.referencedNameAlt = internalPath + indexPart + PATH_DELIMITER + declaration.externalName.text;
}
queuedImport.declaration = declaration; queuedImport.declaration = declaration;
queuedImports.push(queuedImport); queuedImports.push(queuedImport);
} }

View File

@ -7,10 +7,6 @@ import {
Function Function
} from "./program"; } from "./program";
import {
sb
} from "./util/sb";
import { import {
NativeType, NativeType,
ExpressionRef, ExpressionRef,

File diff suppressed because one or more lines are too long

View File

@ -1,23 +1,26 @@
//////////////////////////// Internal path utility /////////////////////////////
import { import {
CharCode CharCode
} from "./charcode"; } from "./charcode";
const separator = CharCode.SLASH; const separator = CharCode.SLASH;
/** Normalizes the specified path, removing interior placeholders. Expects a posix-formatted string / not Windows compatible. */ /**
* Normalizes the specified path, removing interior placeholders.
* Expects a posix-compatible relative path (not Windows compatible).
*/
export function normalize(path: string): string { export function normalize(path: string): string {
// expects a relative path
var pos = 0; var pos = 0;
var len = path.length; var len = path.length;
// trim leading './' // trim leading './'
while (pos + 1 < len && path.charCodeAt(pos) == CharCode.DOT && path.charCodeAt(pos + 1) == separator) while (pos + 1 < len &&
path.charCodeAt(pos) == CharCode.DOT &&
path.charCodeAt(pos + 1) == separator
) {
pos += 2; pos += 2;
}
// trim extension if requested
// if (trimExtension && len > pos + 3 && path.charCodeAt(len - 3) == CharCode.DOT && (path.charCodeAt(len - 2) == CharCode.t || path.charCodeAt(len - 2) == CharCode.a) && path.charCodeAt(len - 1) == CharCode.s)
// len = len - 3;
if (pos > 0 || len < path.length) { if (pos > 0 || len < path.length) {
path = path.substring(pos, len); path = path.substring(pos, len);
@ -30,13 +33,15 @@ export function normalize(path: string): string {
atEnd = false; atEnd = false;
// we are only interested in '/.' sequences ... // we are only interested in '/.' sequences ...
if (path.charCodeAt(pos) == separator && path.charCodeAt(pos + 1) == CharCode.DOT) { if (
path.charCodeAt(pos) == separator &&
path.charCodeAt(pos + 1) == CharCode.DOT
) {
// '/.' ( '/' | $ ) // '/.' ( '/' | $ )
if ( atEnd = pos + 2 == len;
(atEnd = pos + 2 == len) if (atEnd ||
|| pos + 2 < len &&
pos + 2 < len && path.charCodeAt(pos + 2) == separator path.charCodeAt(pos + 2) == separator
) { ) {
path = atEnd path = atEnd
? path.substring(0, pos) ? path.substring(0, pos)
@ -46,17 +51,20 @@ export function normalize(path: string): string {
} }
// '/.' ( './' | '.' $ ) // '/.' ( './' | '.' $ )
if ( atEnd = pos + 3 == len;
(atEnd = pos + 3 == len) && path.charCodeAt(pos + 2) == CharCode.DOT if (atEnd && path.charCodeAt(pos + 2) == CharCode.DOT ||
|| pos + 3 < len &&
pos + 3 < len && path.charCodeAt(pos + 2) == CharCode.DOT && path.charCodeAt(pos + 3) == separator path.charCodeAt(pos + 2) == CharCode.DOT &&
path.charCodeAt(pos + 3) == separator
) { ) {
// find preceeding '/' // find preceeding '/'
var ipos = pos; var ipos = pos;
while (--ipos >= 0) { while (--ipos >= 0) {
if (path.charCodeAt(ipos) == separator) { if (path.charCodeAt(ipos) == separator) {
if (pos - ipos != 3 || path.charCodeAt(ipos + 1) != CharCode.DOT || path.charCodeAt(ipos + 2) != CharCode.DOT) { // exclude '..' itself if (pos - ipos != 3 ||
path.charCodeAt(ipos + 1) != CharCode.DOT ||
path.charCodeAt(ipos + 2) != CharCode.DOT
) { // exclude '..' itself
path = atEnd path = atEnd
? path.substring(0, ipos) ? path.substring(0, ipos)
: path.substring(0, ipos) + path.substring(pos + 3); : path.substring(0, ipos) + path.substring(pos + 3);
@ -69,7 +77,10 @@ export function normalize(path: string): string {
// if there's no preceeding '/', trim start if non-empty // if there's no preceeding '/', trim start if non-empty
if (ipos < 0 && pos > 0) { if (ipos < 0 && pos > 0) {
if (pos != 2 || path.charCodeAt(0) != CharCode.DOT || path.charCodeAt(1) != CharCode.DOT) { // exclude '..' itself if (pos != 2 ||
path.charCodeAt(0) != CharCode.DOT ||
path.charCodeAt(1) != CharCode.DOT
) { // exclude '..' itself
path = path.substring(pos + 4); path = path.substring(pos + 4);
len = path.length; len = path.length;
continue; continue;
@ -82,11 +93,13 @@ export function normalize(path: string): string {
return len > 0 ? path : "."; return len > 0 ? path : ".";
} }
/** Resolves the specified path to a normalized path relative to the specified origin. */ /** Resolves the specified path relative to the specified origin. */
export function resolve(normalizedPath: string, normalizedOrigin: string): string { export function resolve(normalizedPath: string, origin: string): string {
if (normalizedPath.startsWith("std/")) if (normalizedPath.startsWith("std/"))
return normalizedPath; return normalizedPath;
return normalize(dirname(normalizedOrigin) + String.fromCharCode(separator) + normalizedPath); return normalize(
dirname(origin) + String.fromCharCode(separator) + normalizedPath
);
} }
/** Obtains the directory portion of a normalized path. */ /** Obtains the directory portion of a normalized path. */

View File

@ -1,2 +0,0 @@
/** A shared string builder utilized to reduce overall array allocations. */
export const sb = new Array<string>();

View File

@ -15,6 +15,4 @@ export function free_memory(ptr: usize): void {
_free(ptr); _free(ptr);
} }
export function reset_memory(): void { export { reset_memory } from "./none";
throw new Error("not supported");
}

View File

@ -0,0 +1,11 @@
export function allocate_memory(size: usize): usize {
throw new Error("not supported");
}
export function free_memory(ptr: usize): void {
throw new Error("not supported");
}
export function reset_memory(): void {
throw new Error("not supported");
}

View File

@ -14,6 +14,4 @@ export function free_memory(ptr: usize): void {
free(ptr); free(ptr);
} }
export function reset_memory(): void { export { reset_memory } from "./none";
throw new Error("not supported");
}

View File

@ -486,3 +486,5 @@ export function free_memory(data: usize): void {
} }
} }
} }
export { reset_memory } from "./none";