mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-01 18:02:15 +00:00
Cleanup; Documentation
This commit is contained in:
parent
c70eb7792f
commit
aa563a9a5a
471
src/ast.ts
471
src/ast.ts
File diff suppressed because it is too large
Load Diff
@ -107,7 +107,7 @@ export function initialize(program: Program): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds a built-in global to the specified program. */
|
/** Adds a built-in constant to the specified program. */
|
||||||
function addConstant(program: Program, name: string, type: Type): Global {
|
function addConstant(program: Program, name: string, type: Type): Global {
|
||||||
const global: Global = new Global(program, name, null, null);
|
const global: Global = new Global(program, name, null, null);
|
||||||
global.isBuiltIn = true;
|
global.isBuiltIn = true;
|
||||||
|
@ -58,6 +58,7 @@ import {
|
|||||||
ForStatement,
|
ForStatement,
|
||||||
IfStatement,
|
IfStatement,
|
||||||
ImportStatement,
|
ImportStatement,
|
||||||
|
InterfaceDeclaration,
|
||||||
MethodDeclaration,
|
MethodDeclaration,
|
||||||
ModifierKind,
|
ModifierKind,
|
||||||
NamespaceDeclaration,
|
NamespaceDeclaration,
|
||||||
@ -93,8 +94,7 @@ import {
|
|||||||
UnaryPrefixExpression,
|
UnaryPrefixExpression,
|
||||||
|
|
||||||
// utility
|
// utility
|
||||||
hasModifier,
|
hasModifier
|
||||||
InterfaceDeclaration
|
|
||||||
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
import {
|
import {
|
||||||
@ -314,7 +314,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
if (isModuleExport(element, declaration)) {
|
if (isModuleExport(element, declaration)) {
|
||||||
if ((<Global>element).hasConstantValue)
|
if ((<Global>element).hasConstantValue)
|
||||||
this.module.addGlobalExport(element.internalName, declaration.identifier.name);
|
this.module.addGlobalExport(element.internalName, declaration.name.name);
|
||||||
else
|
else
|
||||||
this.warning(DiagnosticCode.Cannot_export_a_mutable_global, declaration.range);
|
this.warning(DiagnosticCode.Cannot_export_a_mutable_global, declaration.range);
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (!declaration)
|
if (!declaration)
|
||||||
throw new Error("unexpected missing declaration");
|
throw new Error("unexpected missing declaration");
|
||||||
if (!declaration.type) { // TODO: infer type
|
if (!declaration.type) { // TODO: infer type
|
||||||
this.error(DiagnosticCode.Type_expected, declaration.identifier.range);
|
this.error(DiagnosticCode.Type_expected, declaration.name.range);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
type = this.program.resolveType(declaration.type); // reports
|
type = this.program.resolveType(declaration.type); // reports
|
||||||
@ -489,7 +489,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (!instance)
|
if (!instance)
|
||||||
return;
|
return;
|
||||||
if (isModuleExport(instance, declaration))
|
if (isModuleExport(instance, declaration))
|
||||||
this.module.addFunctionExport(instance.internalName, declaration.identifier.name);
|
this.module.addFunctionExport(instance.internalName, declaration.name.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileFunctionUsingTypeArguments(prototype: FunctionPrototype, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): Function | null {
|
compileFunctionUsingTypeArguments(prototype: FunctionPrototype, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): Function | null {
|
||||||
@ -509,12 +509,12 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
if (instance.isDeclared) {
|
if (instance.isDeclared) {
|
||||||
if (declaration.statements) {
|
if (declaration.statements) {
|
||||||
this.error(DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts, declaration.identifier.range);
|
this.error(DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts, declaration.name.range);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!declaration.statements) {
|
if (!declaration.statements) {
|
||||||
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.identifier.range);
|
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.name.range);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,7 +546,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// create the function
|
// create the function
|
||||||
const internalName: string = instance.internalName;
|
const internalName: string = instance.internalName;
|
||||||
if (instance.isDeclared) { // TODO: use parent namespace as externalModuleName, if applicable
|
if (instance.isDeclared) { // TODO: use parent namespace as externalModuleName, if applicable
|
||||||
this.module.addFunctionImport(internalName, "env", declaration.identifier.name, typeRef);
|
this.module.addFunctionImport(internalName, "env", declaration.name.name, typeRef);
|
||||||
} else {
|
} else {
|
||||||
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
|
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
|
||||||
}
|
}
|
||||||
@ -871,14 +871,14 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
compileIfStatement(statement: IfStatement): ExpressionRef {
|
compileIfStatement(statement: IfStatement): ExpressionRef {
|
||||||
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||||
const ifTrue: ExpressionRef = this.compileStatement(statement.statement);
|
const ifTrue: ExpressionRef = this.compileStatement(statement.ifTrue);
|
||||||
const ifFalse: ExpressionRef = statement.elseStatement ? this.compileStatement(<Statement>statement.elseStatement) : 0;
|
const ifFalse: ExpressionRef = statement.ifFalse ? this.compileStatement(<Statement>statement.ifFalse) : 0;
|
||||||
return this.module.createIf(condition, ifTrue, ifFalse);
|
return this.module.createIf(condition, ifTrue, ifFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileReturnStatement(statement: ReturnStatement): ExpressionRef {
|
compileReturnStatement(statement: ReturnStatement): ExpressionRef {
|
||||||
if (this.currentFunction) {
|
if (this.currentFunction) {
|
||||||
const expression: ExpressionRef = statement.expression ? this.compileExpression(<Expression>statement.expression, this.currentFunction.returnType) : 0;
|
const expression: ExpressionRef = statement.value ? this.compileExpression(<Expression>statement.value, this.currentFunction.returnType) : 0;
|
||||||
return this.module.createReturn(expression);
|
return this.module.createReturn(expression);
|
||||||
}
|
}
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
@ -895,7 +895,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// prepend initializer to inner block
|
// prepend initializer to inner block
|
||||||
const breaks: ExpressionRef[] = new Array(1 + k);
|
const breaks: ExpressionRef[] = new Array(1 + k);
|
||||||
breaks[0] = this.module.createSetLocal(tempLocal.index, this.compileExpression(statement.expression, Type.i32)); // initializer
|
breaks[0] = this.module.createSetLocal(tempLocal.index, this.compileExpression(statement.condition, Type.i32)); // initializer
|
||||||
|
|
||||||
// make one br_if per (possibly dynamic) labeled case (binaryen optimizes to br_table where possible)
|
// make one br_if per (possibly dynamic) labeled case (binaryen optimizes to br_table where possible)
|
||||||
let breakIndex: i32 = 1;
|
let breakIndex: i32 = 1;
|
||||||
@ -966,18 +966,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
for (let i: i32 = 0, k = declarations.length; i < k; ++i) {
|
for (let i: i32 = 0, k = declarations.length; i < k; ++i) {
|
||||||
const declaration: VariableDeclaration = declarations[i];
|
const declaration: VariableDeclaration = declarations[i];
|
||||||
if (declaration.type) {
|
if (declaration.type) {
|
||||||
const name: string = declaration.identifier.name;
|
const name: string = declaration.name.name;
|
||||||
const type: Type | null = this.program.resolveType(<TypeNode>declaration.type, this.currentFunction.contextualTypeArguments, true); // reports
|
const type: Type | null = this.program.resolveType(<TypeNode>declaration.type, this.currentFunction.contextualTypeArguments, true); // reports
|
||||||
if (type) {
|
if (type) {
|
||||||
if (this.currentFunction.locals.has(name))
|
if (this.currentFunction.locals.has(name))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, name); // recoverable
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, name); // recoverable
|
||||||
else
|
else
|
||||||
this.currentFunction.addLocal(<Type>type, name);
|
this.currentFunction.addLocal(<Type>type, name);
|
||||||
if (declaration.initializer)
|
if (declaration.initializer)
|
||||||
initializers.push(this.compileAssignment(declaration.identifier, <Expression>declaration.initializer, Type.void));
|
initializers.push(this.compileAssignment(declaration.name, <Expression>declaration.initializer, Type.void));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.error(DiagnosticCode.Type_expected, declaration.identifier.range);
|
this.error(DiagnosticCode.Type_expected, declaration.name.range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return initializers.length ? this.module.createBlock(null, initializers, NativeType.None) : this.module.createNop();
|
return initializers.length ? this.module.createBlock(null, initializers, NativeType.None) : this.module.createNop();
|
||||||
@ -1984,7 +1984,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
const operator: Token = expression.operator;
|
const operator: Token = expression.operator;
|
||||||
|
|
||||||
// make a getter for the expression (also obtains the type)
|
// make a getter for the expression (also obtains the type)
|
||||||
const getValue: ExpressionRef = this.compileExpression(expression.expression, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
const getValue: ExpressionRef = this.compileExpression(expression.operand, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||||
|
|
||||||
// use a temp local for the intermediate value
|
// use a temp local for the intermediate value
|
||||||
const tempLocal: Local = this.currentFunction.getTempLocal(this.currentType);
|
const tempLocal: Local = this.currentFunction.getTempLocal(this.currentType);
|
||||||
@ -2015,7 +2015,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make a setter that sets the new value (temp value +/- 1)
|
// make a setter that sets the new value (temp value +/- 1)
|
||||||
const setValue: ExpressionRef = this.compileAssignmentWithValue(expression.expression,
|
const setValue: ExpressionRef = this.compileAssignmentWithValue(expression.operand,
|
||||||
this.module.createBinary(op,
|
this.module.createBinary(op,
|
||||||
this.module.createGetLocal(tempLocal.index, nativeType),
|
this.module.createGetLocal(tempLocal.index, nativeType),
|
||||||
nativeOne
|
nativeOne
|
||||||
@ -2034,7 +2034,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileUnaryPrefixExpression(expression: UnaryPrefixExpression, contextualType: Type): ExpressionRef {
|
compileUnaryPrefixExpression(expression: UnaryPrefixExpression, contextualType: Type): ExpressionRef {
|
||||||
const operandExpression: Expression = expression.expression;
|
const operandExpression: Expression = expression.operand;
|
||||||
|
|
||||||
let operand: ExpressionRef;
|
let operand: ExpressionRef;
|
||||||
let op: UnaryOp;
|
let op: UnaryOp;
|
||||||
|
@ -64,21 +64,30 @@ import {
|
|||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
WhileStatement,
|
WhileStatement,
|
||||||
|
|
||||||
hasModifier
|
addModifier,
|
||||||
|
getModifier,
|
||||||
|
hasModifier,
|
||||||
|
setReusableModifiers
|
||||||
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
||||||
|
/** Parser interface. */
|
||||||
export class Parser extends DiagnosticEmitter {
|
export class Parser extends DiagnosticEmitter {
|
||||||
|
|
||||||
|
/** Program being created. */
|
||||||
program: Program;
|
program: Program;
|
||||||
|
/** Log of source file names to be requested. */
|
||||||
backlog: string[] = new Array();
|
backlog: string[] = new Array();
|
||||||
|
/** Log of source file names already processed. */
|
||||||
seenlog: Set<string> = new Set();
|
seenlog: Set<string> = new Set();
|
||||||
|
|
||||||
|
/** Constructs a new parser. */
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.program = new Program(this.diagnostics);
|
this.program = new Program(this.diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parses a file and adds its definitions to the program. */
|
||||||
parseFile(text: string, path: string, isEntry: bool): void {
|
parseFile(text: string, path: string, isEntry: bool): void {
|
||||||
const normalizedPath: string = normalizePath(path);
|
const normalizedPath: string = normalizePath(path);
|
||||||
for (let i: i32 = 0, k: i32 = this.program.sources.length; i < k; ++i)
|
for (let i: i32 = 0, k: i32 = this.program.sources.length; i < k; ++i)
|
||||||
@ -99,7 +108,6 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
statement.parent = source;
|
statement.parent = source;
|
||||||
source.statements.push(statement);
|
source.statements.push(statement);
|
||||||
}
|
}
|
||||||
reusableModifiers = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parseTopLevelStatement(tn: Tokenizer, isNamespaceMember: bool = false): Statement | null {
|
parseTopLevelStatement(tn: Tokenizer, isNamespaceMember: bool = false): Statement | null {
|
||||||
@ -129,6 +137,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
tn.mark();
|
tn.mark();
|
||||||
|
|
||||||
let statement: Statement | null = null;
|
let statement: Statement | null = null;
|
||||||
|
let modifier: Modifier | null;
|
||||||
switch (tn.next()) {
|
switch (tn.next()) {
|
||||||
|
|
||||||
case Token.CONST:
|
case Token.CONST:
|
||||||
@ -175,12 +184,12 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Token.IMPORT:
|
case Token.IMPORT:
|
||||||
if (hasModifier(ModifierKind.EXPORT, modifiers)) {
|
if (modifier = getModifier(ModifierKind.EXPORT, modifiers)) {
|
||||||
statement = this.parseExportImport(tn, getModifier(ModifierKind.EXPORT, <Modifier[]>modifiers).range);
|
statement = this.parseExportImport(tn, modifier.range);
|
||||||
} else
|
} else
|
||||||
statement = this.parseImport(tn);
|
statement = this.parseImport(tn);
|
||||||
if (modifiers)
|
if (modifiers)
|
||||||
reusableModifiers = modifiers;
|
setReusableModifiers(modifiers);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Token.TYPE:
|
case Token.TYPE:
|
||||||
@ -192,9 +201,9 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
statement = this.parseExport(tn, modifiers); // TODO: why exactly does this have modifiers again?
|
statement = this.parseExport(tn, modifiers); // TODO: why exactly does this have modifiers again?
|
||||||
} else {
|
} else {
|
||||||
if (modifiers) {
|
if (modifiers) {
|
||||||
if (hasModifier(ModifierKind.DECLARE, modifiers))
|
if (modifier = getModifier(ModifierKind.DECLARE, modifiers))
|
||||||
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, getModifier(ModifierKind.DECLARE, modifiers).range, "declare"); // recoverable
|
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, modifier.range, "declare"); // recoverable
|
||||||
reusableModifiers = modifiers;
|
setReusableModifiers(modifiers);
|
||||||
}
|
}
|
||||||
tn.reset();
|
tn.reset();
|
||||||
if (!isNamespaceMember)
|
if (!isNamespaceMember)
|
||||||
@ -210,6 +219,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Obtains the next file to parse. */
|
||||||
nextFile(): string | null {
|
nextFile(): string | null {
|
||||||
if (this.backlog.length) {
|
if (this.backlog.length) {
|
||||||
const filename: string = this.backlog[0];
|
const filename: string = this.backlog[0];
|
||||||
@ -221,6 +231,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Finishes parsing and returns the program. */
|
||||||
finish(): Program {
|
finish(): Program {
|
||||||
if (this.backlog.length)
|
if (this.backlog.length)
|
||||||
throw new Error("backlog is not empty");
|
throw new Error("backlog is not empty");
|
||||||
@ -775,12 +786,13 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// field: (':' Type)? ('=' Expression)? ';'?
|
// field: (':' Type)? ('=' Expression)? ';'?
|
||||||
} else {
|
} else {
|
||||||
if (hasModifier(ModifierKind.ABSTRACT, modifiers))
|
let modifier: Modifier | null;
|
||||||
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, getModifier(ModifierKind.ABSTRACT, <Modifier[]>modifiers).range, "abstract"); // recoverable
|
if (modifier = getModifier(ModifierKind.ABSTRACT, modifiers))
|
||||||
if (hasModifier(ModifierKind.GET, modifiers))
|
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, modifier.range, "abstract"); // recoverable
|
||||||
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, getModifier(ModifierKind.GET, <Modifier[]>modifiers).range, "get"); // recoverable
|
if (modifier = getModifier(ModifierKind.GET, modifiers))
|
||||||
if (hasModifier(ModifierKind.SET, modifiers))
|
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, modifier.range, "get"); // recoverable
|
||||||
this.error(DiagnosticCode._0_modifier_cannot_be_used_here,getModifier(ModifierKind.SET, <Modifier[]>modifiers).range, "set"); // recoverable
|
if (modifier = getModifier(ModifierKind.SET, modifiers))
|
||||||
|
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, modifier.range, "set"); // recoverable
|
||||||
let type: TypeNode | null = null;
|
let type: TypeNode | null = null;
|
||||||
if (tn.skip(Token.COLON)) {
|
if (tn.skip(Token.COLON)) {
|
||||||
type = this.parseType(tn);
|
type = this.parseType(tn);
|
||||||
@ -1323,7 +1335,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
// expressions
|
// expressions
|
||||||
// see: http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm#climbing
|
// see: http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm#climbing
|
||||||
|
|
||||||
parseExpressionPrefix(tn: Tokenizer): Expression | null {
|
parseExpressionStart(tn: Tokenizer): Expression | null {
|
||||||
const token: Token = tn.next();
|
const token: Token = tn.next();
|
||||||
const startPos: i32 = tn.tokenPos;
|
const startPos: i32 = tn.tokenPos;
|
||||||
let expr: Expression | null = null;
|
let expr: Expression | null = null;
|
||||||
@ -1335,7 +1347,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
if (token == Token.FALSE)
|
if (token == Token.FALSE)
|
||||||
return Node.createFalse(tn.range());
|
return Node.createFalse(tn.range());
|
||||||
|
|
||||||
let p: Precedence = determinePrecedencePrefix(token);
|
let p: Precedence = determinePrecedenceStart(token);
|
||||||
if (p != Precedence.INVALID) {
|
if (p != Precedence.INVALID) {
|
||||||
let operand: Expression | null
|
let operand: Expression | null
|
||||||
|
|
||||||
@ -1487,7 +1499,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseExpression(tn: Tokenizer, precedence: Precedence = 0): Expression | null {
|
parseExpression(tn: Tokenizer, precedence: Precedence = 0): Expression | null {
|
||||||
let expr: Expression | null = this.parseExpressionPrefix(tn);
|
let expr: Expression | null = this.parseExpressionStart(tn);
|
||||||
if (!expr)
|
if (!expr)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -1581,7 +1593,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Precedence {
|
const enum Precedence {
|
||||||
COMMA,
|
COMMA,
|
||||||
SPREAD,
|
SPREAD,
|
||||||
YIELD,
|
YIELD,
|
||||||
@ -1606,7 +1618,8 @@ enum Precedence {
|
|||||||
INVALID = -1
|
INVALID = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
function determinePrecedencePrefix(kind: Token): i32 {
|
/** Determines the precedence of a starting token. */
|
||||||
|
function determinePrecedenceStart(kind: Token): i32 {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|
||||||
case Token.DOT_DOT_DOT:
|
case Token.DOT_DOT_DOT:
|
||||||
@ -1634,7 +1647,8 @@ function determinePrecedencePrefix(kind: Token): i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function determinePrecedence(kind: Token): i32 { // non-prefix
|
/** Determines the precende of a non-starting token. */
|
||||||
|
function determinePrecedence(kind: Token): i32 {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|
||||||
case Token.COMMA:
|
case Token.COMMA:
|
||||||
@ -1718,7 +1732,8 @@ function determinePrecedence(kind: Token): i32 { // non-prefix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRightAssociative(kind: Token): bool { // non-prefix
|
/** Determines whether a non-starting token is right associative. */
|
||||||
|
function isRightAssociative(kind: Token): bool {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|
||||||
case Token.EQUALS:
|
case Token.EQUALS:
|
||||||
@ -1742,30 +1757,3 @@ function isRightAssociative(kind: Token): bool { // non-prefix
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let reusableModifiers: Modifier[] | null = null;
|
|
||||||
|
|
||||||
function createModifiers(): Modifier[] {
|
|
||||||
let ret: Modifier[];
|
|
||||||
if (reusableModifiers != null) {
|
|
||||||
ret = reusableModifiers;
|
|
||||||
reusableModifiers = null;
|
|
||||||
} else
|
|
||||||
ret = new Array(1);
|
|
||||||
ret.length = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addModifier(modifier: Modifier, modifiers: Modifier[] | null): Modifier[] {
|
|
||||||
if (modifiers == null)
|
|
||||||
modifiers = createModifiers();
|
|
||||||
modifiers.push(modifier);
|
|
||||||
return modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getModifier(kind: ModifierKind, modifiers: Modifier[]): Modifier {
|
|
||||||
for (let i: i32 = 0, k: i32 = modifiers.length; i < k; ++i)
|
|
||||||
if (modifiers[i].modifierKind == kind)
|
|
||||||
return modifiers[i];
|
|
||||||
throw new Error("no such modifier");
|
|
||||||
}
|
|
||||||
|
106
src/program.ts
106
src/program.ts
@ -216,31 +216,31 @@ export class Program extends DiagnosticEmitter {
|
|||||||
private initializeClass(declaration: ClassDeclaration, namespace: Element | null = null): void {
|
private initializeClass(declaration: ClassDeclaration, namespace: Element | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const prototype: ClassPrototype = new ClassPrototype(this, declaration.identifier.name, internalName, declaration);
|
const prototype: ClassPrototype = new ClassPrototype(this, declaration.name.name, internalName, declaration);
|
||||||
this.elements.set(internalName, prototype);
|
this.elements.set(internalName, prototype);
|
||||||
|
|
||||||
if (hasDecorator("global", declaration.decorators)) {
|
if (hasDecorator("global", declaration.decorators)) {
|
||||||
if (this.elements.has(declaration.identifier.name))
|
if (this.elements.has(declaration.name.name))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
else
|
else
|
||||||
this.elements.set(declaration.identifier.name, prototype);
|
this.elements.set(declaration.name.name, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members) {
|
if (namespace.members) {
|
||||||
if (namespace.members.has(declaration.identifier.name)) {
|
if (namespace.members.has(declaration.name.name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
namespace.members = new Map();
|
namespace.members = new Map();
|
||||||
namespace.members.set(declaration.identifier.name, prototype);
|
namespace.members.set(declaration.name.name, prototype);
|
||||||
} else if (prototype.isExported) {
|
} else if (prototype.isExported) {
|
||||||
if (this.exports.has(internalName)) {
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.exports.set(internalName, prototype);
|
this.exports.set(internalName, prototype);
|
||||||
@ -265,18 +265,18 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
|
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
|
||||||
const name: string = declaration.identifier.name;
|
const name: string = declaration.name.name;
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
|
|
||||||
// static fields become global variables
|
// static fields become global variables
|
||||||
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, declaration.internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (classPrototype.members) {
|
if (classPrototype.members) {
|
||||||
if (classPrototype.members.has(name)) {
|
if (classPrototype.members.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, declaration.internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -289,7 +289,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
} else {
|
} else {
|
||||||
if (classPrototype.instanceMembers) {
|
if (classPrototype.instanceMembers) {
|
||||||
if (classPrototype.instanceMembers.has(name)) {
|
if (classPrototype.instanceMembers.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, declaration.internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -300,18 +300,18 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
|
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
|
||||||
let name: string = declaration.identifier.name;
|
let name: string = declaration.name.name;
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
|
|
||||||
// static methods become global functions
|
// static methods become global functions
|
||||||
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, declaration.internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (classPrototype.members) {
|
if (classPrototype.members) {
|
||||||
if (classPrototype.members.has(name)) {
|
if (classPrototype.members.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, declaration.internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -324,7 +324,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
} else {
|
} else {
|
||||||
if (classPrototype.instanceMembers) {
|
if (classPrototype.instanceMembers) {
|
||||||
if (classPrototype.instanceMembers.has(name)) {
|
if (classPrototype.instanceMembers.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, declaration.internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -337,7 +337,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
private initializeEnum(declaration: EnumDeclaration, namespace: Element | null = null): void {
|
private initializeEnum(declaration: EnumDeclaration, namespace: Element | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const enm: Enum = new Enum(this, internalName, declaration);
|
const enm: Enum = new Enum(this, internalName, declaration);
|
||||||
@ -345,32 +345,32 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members) {
|
if (namespace.members) {
|
||||||
if (namespace.members.has(declaration.identifier.name)) {
|
if (namespace.members.has(declaration.name.name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
namespace.members = new Map();
|
namespace.members = new Map();
|
||||||
namespace.members.set(declaration.identifier.name, enm);
|
namespace.members.set(declaration.name.name, enm);
|
||||||
} else if (enm.isExported) {
|
} else if (enm.isExported) {
|
||||||
if (this.exports.has(internalName)) {
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.exports.set(internalName, enm);
|
this.exports.set(internalName, enm);
|
||||||
}
|
}
|
||||||
|
|
||||||
const values: EnumValueDeclaration[] = declaration.members;
|
const values: EnumValueDeclaration[] = declaration.values;
|
||||||
for (let i: i32 = 0, k: i32 = values.length; i < k; ++i)
|
for (let i: i32 = 0, k: i32 = values.length; i < k; ++i)
|
||||||
this.initializeEnumValue(values[i], enm);
|
this.initializeEnumValue(values[i], enm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeEnumValue(declaration: EnumValueDeclaration, enm: Enum): void {
|
private initializeEnumValue(declaration: EnumValueDeclaration, enm: Enum): void {
|
||||||
const name: string = declaration.identifier.name;
|
const name: string = declaration.name.name;
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (enm.members) {
|
if (enm.members) {
|
||||||
if (enm.members.has(name)) {
|
if (enm.members.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -462,31 +462,31 @@ export class Program extends DiagnosticEmitter {
|
|||||||
private initializeFunction(declaration: FunctionDeclaration, namespace: Element | null = null): void {
|
private initializeFunction(declaration: FunctionDeclaration, namespace: Element | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const prototype: FunctionPrototype = new FunctionPrototype(this, declaration.identifier.name, internalName, declaration, null);
|
const prototype: FunctionPrototype = new FunctionPrototype(this, declaration.name.name, internalName, declaration, null);
|
||||||
this.elements.set(internalName, prototype);
|
this.elements.set(internalName, prototype);
|
||||||
|
|
||||||
if (hasDecorator("global", declaration.decorators)) {
|
if (hasDecorator("global", declaration.decorators)) {
|
||||||
if (this.elements.has(declaration.identifier.name))
|
if (this.elements.has(declaration.name.name))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
else
|
else
|
||||||
this.elements.set(declaration.identifier.name, prototype);
|
this.elements.set(declaration.name.name, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members) {
|
if (namespace.members) {
|
||||||
if (namespace.members.has(declaration.identifier.name)) {
|
if (namespace.members.has(declaration.name.name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
namespace.members = new Map();
|
namespace.members = new Map();
|
||||||
namespace.members.set(declaration.identifier.name, prototype);
|
namespace.members.set(declaration.name.name, prototype);
|
||||||
} else if (prototype.isExported) {
|
} else if (prototype.isExported) {
|
||||||
if (this.exports.has(internalName)) {
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.exports.set(internalName, prototype);
|
this.exports.set(internalName, prototype);
|
||||||
@ -504,7 +504,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
private initializeImport(declaration: ImportDeclaration, internalPath: string, queuedExports: Map<string,QueuedExport>, queuedImports: QueuedImport[]): void {
|
private initializeImport(declaration: ImportDeclaration, internalPath: string, queuedExports: Map<string,QueuedExport>, queuedImports: QueuedImport[]): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,10 +548,10 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
private initializeInterface(declaration: InterfaceDeclaration, namespace: Element | null = null): void {
|
private initializeInterface(declaration: InterfaceDeclaration, namespace: Element | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const prototype: InterfacePrototype = new InterfacePrototype(this, declaration.identifier.name, internalName, declaration);
|
const prototype: InterfacePrototype = new InterfacePrototype(this, declaration.name.name, internalName, declaration);
|
||||||
|
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.elements.set(internalName, prototype);
|
this.elements.set(internalName, prototype);
|
||||||
@ -559,7 +559,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members) {
|
if (namespace.members) {
|
||||||
if (namespace.members.has(prototype.internalName)) {
|
if (namespace.members.has(prototype.internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -567,7 +567,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
namespace.members.set(prototype.internalName, prototype);
|
namespace.members.set(prototype.internalName, prototype);
|
||||||
} else if (prototype.isExported) {
|
} else if (prototype.isExported) {
|
||||||
if (this.exports.has(internalName)) {
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.exports.set(internalName, prototype);
|
this.exports.set(internalName, prototype);
|
||||||
@ -602,16 +602,16 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
if (parentNamespace) {
|
if (parentNamespace) {
|
||||||
if (parentNamespace.members) {
|
if (parentNamespace.members) {
|
||||||
if (parentNamespace.members.has(declaration.identifier.name)) {
|
if (parentNamespace.members.has(declaration.name.name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
parentNamespace.members = new Map();
|
parentNamespace.members = new Map();
|
||||||
parentNamespace.members.set(declaration.identifier.name, namespace);
|
parentNamespace.members.set(declaration.name.name, namespace);
|
||||||
} else if (namespace.isExported) {
|
} else if (namespace.isExported) {
|
||||||
if (this.exports.has(internalName)) {
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.name.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.exports.set(internalName, namespace);
|
this.exports.set(internalName, namespace);
|
||||||
@ -657,7 +657,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
const declaration: VariableDeclaration = declarations[i];
|
const declaration: VariableDeclaration = declarations[i];
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,24 +665,24 @@ export class Program extends DiagnosticEmitter {
|
|||||||
this.elements.set(internalName, global);
|
this.elements.set(internalName, global);
|
||||||
|
|
||||||
if (hasDecorator("global", declaration.decorators)) {
|
if (hasDecorator("global", declaration.decorators)) {
|
||||||
if (this.elements.has(declaration.identifier.name))
|
if (this.elements.has(declaration.name.name))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
else
|
else
|
||||||
this.elements.set(declaration.identifier.name, global);
|
this.elements.set(declaration.name.name, global);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members) {
|
if (namespace.members) {
|
||||||
if (namespace.members.has(declaration.identifier.name)) {
|
if (namespace.members.has(declaration.name.name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
namespace.members = new Map();
|
namespace.members = new Map();
|
||||||
namespace.members.set(declaration.identifier.name, global);
|
namespace.members.set(declaration.name.name, global);
|
||||||
} else if (global.isExported) {
|
} else if (global.isExported) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
|
||||||
else
|
else
|
||||||
this.exports.set(internalName, global);
|
this.exports.set(internalName, global);
|
||||||
}
|
}
|
||||||
@ -817,7 +817,7 @@ function hasDecorator(name: string, decorators: Decorator[] | null): bool {
|
|||||||
if (decorators)
|
if (decorators)
|
||||||
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
||||||
const decorator: Decorator = decorators[i];
|
const decorator: Decorator = decorators[i];
|
||||||
const expression: Expression = decorator.expression;
|
const expression: Expression = decorator.name;
|
||||||
const args: Expression[] = decorator.arguments;
|
const args: Expression[] = decorator.arguments;
|
||||||
if (expression.kind == NodeKind.IDENTIFIER && args.length <= 1 && (<IdentifierExpression>expression).name == name)
|
if (expression.kind == NodeKind.IDENTIFIER && args.length <= 1 && (<IdentifierExpression>expression).name == name)
|
||||||
return true;
|
return true;
|
||||||
@ -1192,7 +1192,7 @@ export class FunctionPrototype extends Element {
|
|||||||
if (typeNode) {
|
if (typeNode) {
|
||||||
const type: Type | null = this.program.resolveType(<TypeNode>typeNode, contextualTypeArguments, true); // reports
|
const type: Type | null = this.program.resolveType(<TypeNode>typeNode, contextualTypeArguments, true); // reports
|
||||||
if (type) {
|
if (type) {
|
||||||
parameters[i] = new Parameter(declaration.parameters[i].identifier.name, type);
|
parameters[i] = new Parameter(declaration.parameters[i].name.name, type);
|
||||||
parameterTypes[i] = <Type>type;
|
parameterTypes[i] = <Type>type;
|
||||||
} else
|
} else
|
||||||
return null;
|
return null;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -91,11 +91,11 @@ export class Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Composes the respective nullable type of this type. */
|
/** Composes the respective nullable type of this type. */
|
||||||
asNullable(): Type {
|
asNullable(): Type | null {
|
||||||
assert(this.kind == TypeKind.USIZE);
|
assert(this.kind == TypeKind.USIZE);
|
||||||
if (this.isNullable && !this.nullableType)
|
if (this.isNullable && !this.nullableType)
|
||||||
(this.nullableType = new Type(this.kind, this.size)).isNullable = true;
|
(this.nullableType = new Type(this.kind, this.size)).isNullable = true;
|
||||||
return <Type>this.nullableType;
|
return this.nullableType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts this type to its TypeScript representation. */
|
/** Converts this type to its TypeScript representation. */
|
||||||
@ -119,7 +119,7 @@ export class Type {
|
|||||||
case TypeKind.F32: return "f32";
|
case TypeKind.F32: return "f32";
|
||||||
case TypeKind.F64: return "f64";
|
case TypeKind.F64: return "f64";
|
||||||
case TypeKind.VOID: return "void";
|
case TypeKind.VOID: return "void";
|
||||||
default: assert(false); return "INVALID";
|
default: assert(false); return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: div/mod
|
// TODO: div/mod
|
||||||
|
// another option is to use a wasm-based polyfill, see examples/i64-polyfill.
|
||||||
|
|
||||||
const I64_MIN_LO: i32 = 0;
|
const I64_MIN_LO: i32 = 0;
|
||||||
const I64_MIN_HI: i32 = 0x80000000 | 0;
|
const I64_MIN_HI: i32 = 0x80000000 | 0;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { CharCode } from "./charcode";
|
import { CharCode } from "./charcode";
|
||||||
|
|
||||||
|
/** Normalizes the specified path, removing interior placeholders. Expects a posix-formatted string / not Windows compatible. */
|
||||||
export function normalize(path: string, trimExtension: bool = false, separator: CharCode = CharCode.SLASH): string {
|
export function normalize(path: string, trimExtension: bool = false, separator: CharCode = CharCode.SLASH): string {
|
||||||
// expects a relative path
|
// expects a relative path
|
||||||
|
|
||||||
@ -77,10 +78,12 @@ export function normalize(path: string, trimExtension: bool = false, separator:
|
|||||||
return len > 0 ? path : ".";
|
return len > 0 ? path : ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resolves the specified path to a normalized path relative to the specified origin. */
|
||||||
export function resolve(normalizedPath: string, normalizedOrigin: string, separator: CharCode = CharCode.SLASH): string {
|
export function resolve(normalizedPath: string, normalizedOrigin: string, separator: CharCode = CharCode.SLASH): string {
|
||||||
return normalize(dirname(normalizedOrigin, separator) + String.fromCharCode(separator) + normalizedPath);
|
return normalize(dirname(normalizedOrigin, separator) + String.fromCharCode(separator) + normalizedPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Obtains the directory portion of a normalized path. */
|
||||||
export function dirname(normalizedPath: string, separator: CharCode = CharCode.SLASH): string {
|
export function dirname(normalizedPath: string, separator: CharCode = CharCode.SLASH): string {
|
||||||
let pos: i32 = normalizedPath.length;
|
let pos: i32 = normalizedPath.length;
|
||||||
while (--pos > 0)
|
while (--pos > 0)
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
/** Shared string builder. */
|
/** A shared string builder utilized to reduce overall array allocations. */
|
||||||
export const sb: string[] = [];
|
export const sb: string[] = [];
|
||||||
|
@ -61,9 +61,9 @@
|
|||||||
heap/HEAP_OFFSET
|
heap/HEAP_OFFSET
|
||||||
heap/Heap
|
heap/Heap
|
||||||
Heap
|
Heap
|
||||||
heap/Heap.get_used
|
heap/Heap.used
|
||||||
heap/Heap.get_free
|
heap/Heap.free
|
||||||
heap/Heap.get_size
|
heap/Heap.size
|
||||||
heap/Heap.allocate
|
heap/Heap.allocate
|
||||||
heap/Heap.dispose
|
heap/Heap.dispose
|
||||||
heap/Heap.copy
|
heap/Heap.copy
|
||||||
|
@ -183,9 +183,9 @@
|
|||||||
heap/HEAP_OFFSET
|
heap/HEAP_OFFSET
|
||||||
heap/Heap
|
heap/Heap
|
||||||
Heap
|
Heap
|
||||||
heap/Heap.get_used
|
heap/Heap.used
|
||||||
heap/Heap.get_free
|
heap/Heap.free
|
||||||
heap/Heap.get_size
|
heap/Heap.size
|
||||||
heap/Heap.allocate
|
heap/Heap.allocate
|
||||||
heap/Heap.dispose
|
heap/Heap.dispose
|
||||||
heap/Heap.copy
|
heap/Heap.copy
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
0 ? unreachable() : 1;
|
||||||
|
1 ? 1 : unreachable();
|
||||||
|
(0 ? unreachable() : 1) ? 1 : unreachable();
|
||||||
|
|
||||||
let a: i32;
|
let a: i32;
|
||||||
|
|
||||||
a = 0 ? unreachable() : 1;
|
a = 0 ? unreachable() : 1;
|
||||||
|
@ -6,6 +6,31 @@
|
|||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $start (; 0 ;) (type $v)
|
(func $start (; 0 ;) (type $v)
|
||||||
|
(if
|
||||||
|
(i32.const 0)
|
||||||
|
(unreachable)
|
||||||
|
(drop
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.const 1)
|
||||||
|
(drop
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(if (result i32)
|
||||||
|
(i32.const 0)
|
||||||
|
(unreachable)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
(set_global $ternary/a
|
(set_global $ternary/a
|
||||||
(if (result i32)
|
(if (result i32)
|
||||||
(i32.const 0)
|
(i32.const 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user