Accessor parsing; Cleanup

This commit is contained in:
dcodeIO 2017-12-14 11:55:35 +01:00
parent 99b0fdf7a8
commit c6c36613e6
30 changed files with 171 additions and 124 deletions

View File

@ -68,16 +68,20 @@
import { GETTER_PREFIX, SETTER_PREFIX, PATH_DELIMITER, PARENT_SUBST, STATIC_DELIMITER, INSTANCE_DELIMITER } from "./constants";
import { Token, Tokenizer, operatorTokenToString, Range } from "./tokenizer";
import { CharCode, I64, normalizePath, resolvePath } from "./util";
import { CharCode } from "./util/charcode";
import { I64 } from "./util/i64";
import { normalize as normalizePath, resolve as resolvePath } from "./util/path";
export { Range } from "./tokenizer";
/** Base class of all AST nodes. */
export abstract class Node {
kind: NodeKind;
range: Range;
parent: Node | null = null;
/** Serializes this node to its TypeScript representation. */
abstract serialize(sb: string[]): void;
}
@ -1374,7 +1378,7 @@ export class FunctionDeclaration extends DeclarationStatement {
sb.push(", ");
this.parameters[i].serialize(sb);
}
if (this.returnType) {
if (this.returnType && !hasModifier(ModifierKind.SET, this.modifiers)) {
sb.push("): ");
(<TypeNode>this.returnType).serialize(sb);
} else

View File

@ -1,4 +1,4 @@
import { Compiler, Target, typeToNativeType, typeToNativeOne } from "./compiler";
import { Compiler, Target, typeToNativeType, typeToNativeOne, typeToNativeZero } from "./compiler";
import { DiagnosticCode } from "./diagnostics";
import { Node, Expression } from "./ast";
import { Type } from "./types";
@ -490,15 +490,26 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
case "assert": // assert(isTrue: bool) -> void
compiler.currentType = Type.void;
if (!validateCall(compiler, typeArguments, 0, operands, 1, reportNode))
if (typeArguments.length != 0) {
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "0", typeArguments.length.toString(10));
return module.createUnreachable();
}
if (operands.length < 1) {
compiler.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, "1", operands.length.toString(10));
return module.createUnreachable();
}
if (operands.length > 2) {
compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "2", operands.length.toString(10));
return module.createUnreachable();
}
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
arg1 = operands.length > 1 ? compiler.compileExpression(operands[1], usizeType) : typeToNativeZero(module, usizeType); // TODO: string type
compiler.currentType = Type.void;
return compiler.options.noAssert
? module.createNop()
: module.createIf(
module.createUnary(UnaryOp.EqzI32, arg0),
module.createUnreachable()
module.createUnreachable() // TODO: report message to embedder
);
case "parseInt": // takes a pointer to the string
@ -541,7 +552,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
return 0;
}
/** Validates a call to a built-in function. */
/** Pre-validates a call to a built-in function. */
function validateCall(compiler: Compiler, typeArguments: Type[], expectedTypeArguments: i32, operands: Expression[], expectedOperands: i32, reportNode: Node): bool {
if (typeArguments.length != expectedTypeArguments) {
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, expectedTypeArguments.toString(10), typeArguments.length.toString(10));

View File

@ -31,7 +31,6 @@ import {
EnumValue
} from "./program";
import { I64, U64, sb } from "./util";
import { Token } from "./tokenizer";
import {
@ -103,7 +102,10 @@ import {
TypeKind,
} from "./types";
import { I64, U64 } from "./util/i64";
import { sb } from "./util/sb";
/** Compilation target. */
export enum Target {
/** WebAssembly with 32-bit pointers. */
WASM32,
@ -111,6 +113,7 @@ export enum Target {
WASM64
}
/** Compiler options. */
export class Options {
/** WebAssembly target. Defaults to {@link Target.WASM32}. */
target: Target = Target.WASM32;
@ -122,6 +125,7 @@ export class Options {
noAssert: bool = false;
}
/** Indicates the desired kind of a conversion. */
const enum ConversionKind {
/** No conversion. */
NONE,
@ -131,6 +135,7 @@ const enum ConversionKind {
EXPLICIT
}
/** Compiler interface. */
export class Compiler extends DiagnosticEmitter {
/** Program reference. */
@ -323,8 +328,10 @@ export class Compiler extends DiagnosticEmitter {
if (!type) {
if (!declaration)
throw new Error("unexpected missing declaration");
if (!declaration.type)
return false; // TODO: infer type? currently reported by parser
if (!declaration.type) { // TODO: infer type
this.error(DiagnosticCode.Type_expected, declaration.identifier.range);
return false;
}
type = this.program.resolveType(declaration.type); // reports
if (!type)
return false;
@ -336,6 +343,7 @@ export class Compiler extends DiagnosticEmitter {
let initializer: ExpressionRef;
let initializeInStart: bool = false;
if (global.hasConstantValue) {
assert(type != null);
if (type.isLongInteger)
initializer = global.constantIntegerValue ? this.module.createI64(global.constantIntegerValue.lo, global.constantIntegerValue.hi) : this.module.createI64(0, 0);
else if (type.kind == TypeKind.F32)
@ -513,17 +521,17 @@ export class Compiler extends DiagnosticEmitter {
// create the function type
let k: i32 = instance.parameters.length;
const binaryenResultType: NativeType = typeToNativeType(instance.returnType);
const binaryenParamTypes: NativeType[] = new Array(k);
const nativeResultType: NativeType = typeToNativeType(instance.returnType);
const nativeParamTypes: NativeType[] = new Array(k);
const signatureNameParts: string[] = new Array(k + 1);
for (let i: i32 = 0; i < k; ++i) {
binaryenParamTypes[i] = typeToNativeType(instance.parameters[i].type);
nativeParamTypes[i] = typeToNativeType(instance.parameters[i].type);
signatureNameParts[i] = typeToSignatureNamePart(instance.parameters[i].type);
}
signatureNameParts[k] = typeToSignatureNamePart(instance.returnType);
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(binaryenResultType, binaryenParamTypes);
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(nativeResultType, nativeParamTypes);
if (!typeRef)
typeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes);
typeRef = this.module.addFunctionType(signatureNameParts.join(""), nativeResultType, nativeParamTypes);
// create the function
const internalName: string = instance.internalName;
@ -673,6 +681,7 @@ export class Compiler extends DiagnosticEmitter {
// memory
/** Adds a static memory segment with the specified data. */
addMemorySegment(buffer: Uint8Array): MemorySegment {
if (this.memoryOffset.lo & 7) { // align to 8 bytes so any native data type is aligned here
this.memoryOffset.or32(7);
@ -686,6 +695,7 @@ export class Compiler extends DiagnosticEmitter {
// types
// TODO: try to get rid of this
determineExpressionType(expression: Expression, contextualType: Type): Type {
const previousType: Type = this.currentType;
const previousNoEmit: bool = this.module.noEmit;
@ -945,6 +955,8 @@ export class Compiler extends DiagnosticEmitter {
if (declaration.initializer)
initializers.push(this.compileAssignment(declaration.identifier, <Expression>declaration.initializer, Type.void));
}
} else {
this.error(DiagnosticCode.Type_expected, declaration.identifier.range);
}
}
return initializers.length ? this.module.createBlock(null, initializers, NativeType.None) : this.module.createNop();
@ -1160,11 +1172,14 @@ export class Compiler extends DiagnosticEmitter {
expr = mod.createUnary(UnaryOp.ConvertI64_F32, expr);
else
expr = mod.createUnary(UnaryOp.ConvertU64_F32, expr);
} else
} else {
if (!fromType.isSmallInteger)
losesInformation = true;
if (fromType.isSignedInteger)
expr = mod.createUnary(UnaryOp.ConvertI32_F32, expr);
else
expr = mod.createUnary(UnaryOp.ConvertU32_F32, expr);
}
// int to f64
} else {
@ -1205,8 +1220,8 @@ export class Compiler extends DiagnosticEmitter {
else
expr = mod.createUnary(UnaryOp.ExtendU32, expr);
// i32 to smaller/change of signage i32
} else if (toType.isSmallInteger && (fromType.size > toType.size || (fromType.size == toType.size && fromType.kind != toType.kind))) {
// i32 or smaller to even smaller int
} else if (toType.isSmallInteger && fromType.size > toType.size) {
losesInformation = true;
if (toType.isSignedInteger) {
expr = mod.createBinary(BinaryOp.ShlI32, expr, mod.createI32(toType.smallIntegerShift));
@ -1813,7 +1828,7 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createI64(intValue.lo, intValue.hi);
if (contextualType.isSmallInteger)
return this.module.createI32(intValue.toI32());
this.currentType = Type.i32;
this.currentType = contextualType.isSignedInteger ? Type.i32 : Type.u32;
return this.module.createI32(intValue.toI32());
}

View File

@ -14,7 +14,7 @@ import {
readString
} from "./module";
import { I64 } from "./util";
import { I64 } from "./util/i64";
// TODO :-)

View File

@ -20,6 +20,9 @@ export enum DiagnosticCode {
Statements_are_not_allowed_in_ambient_contexts = 1036,
Initializers_are_not_allowed_in_ambient_contexts = 1039,
_0_modifier_cannot_be_used_here = 1042,
A_set_accessor_must_have_exactly_one_parameter = 1049,
A_set_accessor_parameter_cannot_have_an_initializer = 1052,
A_get_accessor_cannot_have_parameters = 1054,
Type_parameters_cannot_appear_on_a_constructor_declaration = 1092,
Type_annotation_cannot_appear_on_a_constructor_declaration = 1093,
An_accessor_cannot_have_type_parameters = 1094,
@ -42,6 +45,7 @@ export enum DiagnosticCode {
String_literal_expected = 1141,
Line_break_not_permitted_here = 1142,
Declaration_expected = 1146,
_const_declarations_must_be_initialized = 1155,
Unterminated_regular_expression_literal = 1161,
Binary_digit_expected = 1177,
Octal_digit_expected = 1178,
@ -95,6 +99,9 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 1036: return "Statements are not allowed in ambient contexts.";
case 1039: return "Initializers are not allowed in ambient contexts.";
case 1042: return "'{0}' modifier cannot be used here.";
case 1049: return "A 'set' accessor must have exactly one parameter.";
case 1052: return "A 'set' accessor parameter cannot have an initializer.";
case 1054: return "A 'get' accessor cannot have parameters.";
case 1092: return "Type parameters cannot appear on a constructor declaration.";
case 1093: return "Type annotation cannot appear on a constructor declaration.";
case 1094: return "An accessor cannot have type parameters.";
@ -117,6 +124,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 1141: return "String literal expected.";
case 1142: return "Line break not permitted here.";
case 1146: return "Declaration expected.";
case 1155: return "'const' declarations must be initialized.";
case 1161: return "Unterminated regular expression literal.";
case 1177: return "Binary digit expected.";
case 1178: return "Octal digit expected.";

View File

@ -19,6 +19,9 @@
"Statements are not allowed in ambient contexts.": 1036,
"Initializers are not allowed in ambient contexts.": 1039,
"'{0}' modifier cannot be used here.": 1042,
"A 'set' accessor must have exactly one parameter.": 1049,
"A 'set' accessor parameter cannot have an initializer.": 1052,
"A 'get' accessor cannot have parameters.": 1054,
"Type parameters cannot appear on a constructor declaration.": 1092,
"Type annotation cannot appear on a constructor declaration.": 1093,
"An accessor cannot have type parameters.": 1094,
@ -41,6 +44,7 @@
"String literal expected.": 1141,
"Line break not permitted here.": 1142,
"Declaration expected.": 1146,
"'const' declarations must be initialized.": 1155,
"Unterminated regular expression literal.": 1161,
"Binary digit expected.": 1177,
"Octal digit expected.": 1178,

View File

@ -1,6 +1,7 @@
import { Range } from "./ast";
import { CharCode, isLineBreak, sb } from "./util";
import { DiagnosticCode, diagnosticCodeToString } from "./diagnosticMessages.generated";
import { CharCode, isLineBreak } from "./util/charcode";
import { sb } from "./util/sb";
export { DiagnosticCode, diagnosticCodeToString } from "./diagnosticMessages.generated";
@ -71,6 +72,12 @@ export class DiagnosticMessage {
this.range = range;
return this;
}
toString(): string {
if (this.range)
return diagnosticCategoryToString(this.category) + " " + this.code + ": \"" + this.message + "\" in " + this.range.source.path + " @ " + this.range.start + "," + this.range.end;
return diagnosticCategoryToString(this.category) + " " + this.code + ": " + this.message;
}
}
export function formatDiagnosticMessage(message: DiagnosticMessage, useColors: bool = false, showContext: bool = false): string {
@ -146,6 +153,7 @@ export function formatDiagnosticContext(range: Range, useColors: bool = false):
export abstract class DiagnosticEmitter {
diagnostics: DiagnosticMessage[];
silentDiagnostics: bool = false;
constructor(diagnostics: DiagnosticMessage[] | null = null) {
this.diagnostics = diagnostics ? <DiagnosticMessage[]>diagnostics : new Array();
@ -154,8 +162,10 @@ export abstract class DiagnosticEmitter {
emitDiagnostic(code: DiagnosticCode, category: DiagnosticCategory, range: Range, arg0: string | null = null, arg1: string | null = null) {
const message: DiagnosticMessage = DiagnosticMessage.create(code, category, arg0, arg1).withRange(range);
this.diagnostics.push(message);
console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
console.log(<string>new Error("stack").stack);
if (!this.silentDiagnostics) {
console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
console.log(<string>new Error("stack").stack);
}
}
error(code: DiagnosticCode, range: Range, arg0: string | null = null, arg1: string | null = null): void {

View File

@ -1,68 +0,0 @@
// TODO: not yet decided whether we'll need this
// https://github.com/WebAssembly/binaryen/pull/1294
// https://github.com/WebAssembly/binaryen/pull/1295
import { Type } from "./types";
import { I64 } from "./util";
import {
NodeKind,
Expression,
BinaryExpression,
LiteralExpression,
UnaryExpression,
UnaryPostfixExpression,
UnaryPrefixExpression
} from "./ast";
export class Evaluator {
success: bool = false;
type: Type;
integerValue: I64;
floatValue: f64;
stringValue: string;
constructor(initialType: Type) {
this.type = initialType;
}
evaluate(expression: Expression): this {
switch (expression.kind) {
case NodeKind.BINARY:
this.evaluateBinary(<BinaryExpression>expression);
break;
case NodeKind.LITERAL:
this.evaluateLiteral(<LiteralExpression>expression);
break;
case NodeKind.UNARYPREFIX:
this.evaluateUnaryPrefix(<UnaryPrefixExpression>expression);
break;
}
return this;
}
private evaluateBinary(expression: BinaryExpression): this {
// TODO
return this;
}
private evaluateLiteral(expression: LiteralExpression): this {
// TODO
return this;
}
private evaluateUnaryPrefix(expression: UnaryPrefixExpression): this {
// TODO
return this;
}
}
export function evaluate(expression: Expression, contextualType: Type): Evaluator {
return new Evaluator(contextualType).evaluate(expression);
}

View File

@ -17,6 +17,9 @@
compile(parser) -> module
[check diagnostics again]
[output module]
*/
import { Module } from "./module";

View File

@ -1,5 +1,5 @@
import { I64, U64 } from "./util";
import { Target } from "./compiler";
import { I64, U64 } from "./util/i64";
export type ModuleRef = usize;
export type FunctionTypeRef = usize;

View File

@ -10,7 +10,8 @@
import { Program } from "./program";
import { Tokenizer, Token, Range } from "./tokenizer";
import { DiagnosticCode, DiagnosticEmitter } from "./diagnostics";
import { normalizePath, I64 } from "./util";
import { I64 } from "./util/i64";
import { normalize as normalizePath } from "./util/path";
import {
Node,
@ -386,10 +387,8 @@ export class Parser extends DiagnosticEmitter {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
let type: TypeNode | null = null;
if (tn.skip(Token.COLON)) {
if (tn.skip(Token.COLON))
type = this.parseType(tn);
} else
this.error(DiagnosticCode.Type_expected, tn.range(tn.pos)); // recoverable
let initializer: Expression | null = null;
if (tn.skip(Token.EQUALS)) {
@ -398,6 +397,11 @@ export class Parser extends DiagnosticEmitter {
initializer = this.parseExpression(tn, Precedence.COMMA + 1);
if (!initializer)
return null;
} else {
if (hasModifier(ModifierKind.CONST, parentModifiers))
this.error(DiagnosticCode._const_declarations_must_be_initialized, identifier.range);
else if (!type) // neither type nor initializer
this.error(DiagnosticCode.Type_expected, tn.range(tn.pos)); // recoverable
}
return Statement.createVariableDeclaration(identifier, type, initializer, parentModifiers, parentDecorators, Range.join(identifier.range, tn.range()));
}
@ -567,13 +571,28 @@ export class Parser extends DiagnosticEmitter {
const parameters: Parameter[] | null = this.parseParameters(tn);
if (!parameters)
return null;
let isSetter: bool = hasModifier(ModifierKind.SET, modifiers);
if (isSetter) {
if (parameters.length != 1)
this.error(DiagnosticCode.A_set_accessor_must_have_exactly_one_parameter, identifier.range); // recoverable
if (parameters.length && parameters[0].initializer)
this.error(DiagnosticCode.A_set_accessor_parameter_cannot_have_an_initializer, identifier.range); // recoverable
}
let isGetter: bool = hasModifier(ModifierKind.GET, modifiers);
if (isGetter && parameters.length)
this.error(DiagnosticCode.A_get_accessor_cannot_have_parameters, identifier.range); // recoverable
let returnType: TypeNode | null = null;
if (tn.skip(Token.COLON)) {
returnType = this.parseType(tn);
returnType = this.parseType(tn, isSetter);
if (!returnType)
return null;
} else
this.error(DiagnosticCode.Type_expected, tn.range(tn.pos)); // recoverable
} else {
if (isSetter) {
if (parameters.length)
returnType = parameters[0].type;
} else
this.error(DiagnosticCode.Type_expected, tn.range(tn.pos)); // recoverable
}
const isDeclare: bool = hasModifier(ModifierKind.DECLARE, modifiers);
let statements: Statement[] | null = null;
if (tn.skip(Token.OPENBRACE)) {
@ -675,10 +694,15 @@ export class Parser extends DiagnosticEmitter {
else if (tn.skip(Token.ABSTRACT))
modifiers = addModifier(Statement.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
if (tn.skip(Token.GET))
let isGetter: bool = false;
let isSetter: bool = false;
if (tn.skip(Token.GET)) {
modifiers = addModifier(Statement.createModifier(ModifierKind.GET, tn.range()), modifiers);
else if (tn.skip(Token.SET))
isGetter = true;
} else if (tn.skip(Token.SET)) { // can't be both
modifiers = addModifier(Statement.createModifier(ModifierKind.SET, tn.range()), modifiers);
isSetter = true;
}
if (tn.skip(Token.IDENTIFIER)) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
@ -695,13 +719,26 @@ export class Parser extends DiagnosticEmitter {
let parameters = this.parseParameters(tn);
if (!parameters)
return null;
if (isGetter && parameters.length)
this.error(DiagnosticCode.A_get_accessor_cannot_have_parameters, identifier.range);
if (isSetter) {
if (parameters.length != 1)
this.error(DiagnosticCode.A_set_accessor_must_have_exactly_one_parameter, identifier.range);
if (parameters.length && parameters[0].initializer)
this.error(DiagnosticCode.A_set_accessor_parameter_cannot_have_an_initializer, identifier.range);
}
let returnType: TypeNode | null = null;
if (tn.skip(Token.COLON)) {
returnType = this.parseType(tn);
returnType = this.parseType(tn, isSetter);
if (!returnType)
return null;
} else
this.error(DiagnosticCode.Type_expected, tn.range()); // recoverable
} else {
if (isSetter) {
if (parameters.length)
returnType = parameters[0].type;
} else
this.error(DiagnosticCode.Type_expected, tn.range()); // recoverable
}
let statements: Statement[] | null = null;
if (tn.skip(Token.OPENBRACE)) {
if (parentIsDeclare)

View File

@ -3,7 +3,7 @@ import { Target, typeToNativeType } from "./compiler";
import { GETTER_PREFIX, SETTER_PREFIX, PATH_DELIMITER } from "./constants";
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
import { Type, typesToString } from "./types";
import { I64 } from "./util";
import { I64 } from "./util/i64";
import {
ModifierKind,

View File

@ -21,7 +21,8 @@
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter, formatDiagnosticMessage } from "./diagnostics";
import { Source } from "./ast";
import { I64, CharCode, isLineBreak } from "./util";
import { CharCode, isLineBreak } from "./util/charcode";
import { I64 } from "./util/i64";
export enum Token {

View File

@ -1,5 +1,5 @@
import { Class } from "./program";
import { sb } from "./util";
import { sb } from "./util/sb";
export const enum TypeKind {
@ -103,6 +103,7 @@ export class Type {
static readonly f32: Type = new Type(TypeKind.F32, 32);
static readonly f64: Type = new Type(TypeKind.F64, 64);
static readonly void: Type = new Type(TypeKind.VOID, 0);
static readonly infer: Type = Type.void;
}
export function typesToString(types: Type[], prefix: string = "<", postfix: string = ">"): string {

View File

@ -1,4 +0,0 @@
export { CharCode, isLineBreak} from "./util/charcode";
export { I64, U64 } from "./util/i64";
export { normalize as normalizePath, resolve as resolvePath, dirname } from "./util/path";
export const sb: string[] = new Array(256); // shared string builder. 64-bit without growing: (4+4+8) + 8*256 = 16b + 2kb

2
src/util/sb.ts Normal file
View File

@ -0,0 +1,2 @@
/** Shared string builder. */
export const sb: string[] = [];

2
std/assembly.d.ts vendored
View File

@ -89,7 +89,7 @@ declare function isNaN<T = f32 | f64>(value: T): bool;
/** Tests if a 32-bit or 64-bit float is finite, that is not NaN or +/-Infinity. */
declare function isFinite<T = f32 | f64>(value: T): bool;
/** Traps if the specified value evaluates to `false`. */
declare function assert(isTrue: bool): void;
declare function assert(isTrue: bool, message?: string): void;
/** Parses an integer string to a 64-bit float. */
declare function parseInt(str: string, radix?: i32): f64;
/** Parses a string to a 64-bit float. */

View File

@ -2,6 +2,7 @@
"extends": "../tsconfig-base.json",
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"noLib": true,
"types": [],
"rootDirs": [

2
std/portable.d.ts vendored
View File

@ -51,7 +51,7 @@ declare function unreachable(): any; // sic
/** Changes the type of a value to another one. Useful for casting class instances to their pointer values and vice-versa. */
declare function changetype<T1,T2>(value: T1): T2;
/** Traps if the specified value evaluates to `false`. */
declare function assert(isTrue: bool): void;
declare function assert(isTrue: bool, message?: string): void;
/** Parses an integer string to a 64-bit float. */
declare function parseInt(str: string, radix?: i32): f64;
/** Parses a floating point string to a 64-bit float. */

View File

@ -19,14 +19,14 @@ UnreachableError.prototype.message = "unreachable";
globalScope["unreachable"] = function unreachable() { throw new UnreachableError(); };
function AssertionError() {
function AssertionError(message) {
this.message = message || "assertion failed";
this.stack = new Error().stack;
}
AssertionError.prototype = new Error;
AssertionError.prototype.name = "AssertionError";
AssertionError.prototype.message = "assertion failed";
globalScope["assert"] = function assert(isTrue) { if (!isTrue) throw new AssertionError(); };
globalScope["assert"] = function assert(isTrue, message) { if (!isTrue) throw new AssertionError(message); };
globalScope["changetype"] = function changetype(value) { return value; }
String["fromCharCodes"] = function fromCharCodes(arr) { return String.fromCharCode.apply(String, arr); }

View File

@ -2,8 +2,6 @@
// Useful as a compiler test in this state, but nothing more.
// based upon: https://github.com/mattconte/tlsf/blob/master/tlsf.c (BSD)
/// <reference path="../../assembly.d.ts" />
/** Finds the index of the least bit set. */
function fls(word: u32): i32 {
return !word ? -1: 31 - clz<i32>(word);

View File

@ -0,0 +1,6 @@
{
"extends": "../../std/assembly.json",
"include": [
"./*.ts"
]
}

View File

@ -18,12 +18,13 @@ glob.sync(filter, { cwd: __dirname + "/parser" }).forEach(filename => {
console.log(chalk.default.whiteBright("Testing parser/" + filename));
var parser = new Parser();
parser.silentDiagnostics = true;
var sourceText = fs.readFileSync(__dirname + "/parser/" + filename, { encoding: "utf8" }).replace(/\r?\n/g, "\n").replace(/^\/\/.*\r?\n/mg, "");
parser.parseFile(sourceText, filename, true);
var sb = [];
parser.program.sources[0].serialize(sb);
var actual = sb.join("");
var actual = sb.join("") + parser.diagnostics.map(diagnostic => "// " + diagnostic + "\n").join("");;
var fixture = filename + ".fixture.ts";
if (isCreate) {

View File

@ -4,8 +4,9 @@ export class Test<T> {
static staticFunction(): void {
}
get instanceGetter(): i32 {
return 0;
}
static set staticSetter(v: i32): i32 {
static set staticSetter(v: i32) {
}
instanceField: i32;
static staticField: i32;

View File

@ -4,8 +4,9 @@ instanceFunction(): void {
static staticFunction(): void {
}
get instanceGetter(): i32 {
return 0;
}
static set staticSetter(v: i32): i32 {
static set staticSetter(v: i32) {
}
instanceField: i32;
static staticField: i32;

View File

@ -2,7 +2,7 @@ declare namespace A {
namespace B {
export namespace C {
let aVar: i32;
const aConst: i32;
const aConst: i32 = 0;
function aFunc(): void {}
enum AnEnum {}
class AClass {}

View File

@ -2,7 +2,7 @@ declare namespace A {
namespace B {
export namespace C {
let aVar: i32;
const aConst: i32;
const aConst: i32 = 0;
function aFunc(): void {
}
enum AnEnum {

View File

@ -0,0 +1,6 @@
{
"extends": "../../std/assembly.json",
"include": [
"./*.ts"
]
}

View File

@ -1,3 +1,7 @@
var a: i32;
let b: i32;
const c: i32;
const c: i32 = 0;
let d = 2;
let e; // type expected
const f: i32; // must be initialized

View File

@ -1,3 +1,8 @@
let a: i32;
let b: i32;
const c: i32;
const c: i32 = 0;
let d = 2;
let e;
const f: i32;
// ERROR 1110: "Type expected." in var.ts @ 59,59
// ERROR 1155: "'const' declarations must be initialized." in var.ts @ 84,85