mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-18 09:21:35 +00:00
Rename lib prefix to '~lib' (parens aren't valid); Add built-in alignof<T>; Prepare for ArrayBufferView
This commit is contained in:
14
src/ast.ts
14
src/ast.ts
@ -534,7 +534,7 @@ export abstract class Node {
|
||||
identifier: IdentifierExpression,
|
||||
typeParameters: TypeParameterNode[],
|
||||
extendsType: TypeNode | null, // can't be a function
|
||||
implementsTypes: TypeNode[], // can't be a function
|
||||
implementsTypes: TypeNode[] | null, // can't be functions
|
||||
members: DeclarationStatement[],
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
@ -546,7 +546,7 @@ export abstract class Node {
|
||||
stmt.name = identifier; identifier.parent = stmt;
|
||||
stmt.typeParameters = typeParameters; setParent(typeParameters, stmt);
|
||||
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
||||
stmt.implementsTypes = implementsTypes; setParent(implementsTypes, stmt);
|
||||
stmt.implementsTypes = implementsTypes; if (implementsTypes) setParent(implementsTypes, stmt);
|
||||
stmt.members = members; setParent(members, stmt);
|
||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||
return stmt;
|
||||
@ -756,8 +756,10 @@ export abstract class Node {
|
||||
|
||||
static createInterfaceDeclaration(
|
||||
name: IdentifierExpression,
|
||||
typeParameters: TypeParameterNode[],
|
||||
extendsType: TypeNode | null, // can't be a function
|
||||
members: DeclarationStatement[],
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): InterfaceDeclaration {
|
||||
@ -765,8 +767,10 @@ export abstract class Node {
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
||||
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
||||
stmt.members = members; setParent(members, stmt);
|
||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -1487,10 +1491,10 @@ export class ClassDeclaration extends DeclarationStatement {
|
||||
|
||||
/** Accepted type parameters. */
|
||||
typeParameters: TypeParameterNode[];
|
||||
/** Base class type being extended. */
|
||||
/** Base class type being extended, if any. */
|
||||
extendsType: TypeNode | null; // can't be a function
|
||||
/** Interface types being implemented. */
|
||||
implementsTypes: TypeNode[]; // can't be a function
|
||||
/** Interface types being implemented, if any. */
|
||||
implementsTypes: TypeNode[] | null; // can't be functions
|
||||
/** Class member declarations. */
|
||||
members: DeclarationStatement[];
|
||||
|
||||
|
@ -1790,6 +1790,55 @@ export function compileCall(
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case "alignof": { // alignof<T!>() -> usize
|
||||
compiler.currentType = compiler.options.usizeType;
|
||||
if (operands.length != 0) {
|
||||
if (!(typeArguments && typeArguments.length == 1)) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
||||
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
||||
);
|
||||
}
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||
reportNode.range, "0", operands.length.toString(10)
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
if (!(typeArguments && typeArguments.length == 1)) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
||||
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
||||
);
|
||||
}
|
||||
let byteSize = (<Type[]>typeArguments)[0].byteSize;
|
||||
let alignLog2: i32;
|
||||
switch (byteSize) {
|
||||
case 1: { alignLog2 = 0; break; }
|
||||
case 2: { alignLog2 = 1; break; }
|
||||
case 4: { alignLog2 = 2; break; }
|
||||
case 8: { alignLog2 = 3; break; }
|
||||
default: { assert(false); return module.createUnreachable(); }
|
||||
}
|
||||
if (compiler.options.isWasm64) {
|
||||
// implicitly wrap if contextual type is a 32-bit integer
|
||||
if (contextualType.is(TypeFlags.INTEGER) && contextualType.size <= 32) {
|
||||
compiler.currentType = Type.u32;
|
||||
ret = module.createI32(alignLog2);
|
||||
} else {
|
||||
ret = module.createI64(alignLog2, 0);
|
||||
}
|
||||
} else {
|
||||
// implicitly extend if contextual type is a 64-bit integer
|
||||
if (contextualType.is(TypeFlags.INTEGER) && contextualType.size == 64) {
|
||||
compiler.currentType = Type.u64;
|
||||
ret = module.createI64(alignLog2, 0);
|
||||
} else {
|
||||
ret = module.createI32(alignLog2);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case "offsetof": { // offsetof<T!>(fieldName?: string) -> usize
|
||||
compiler.currentType = compiler.options.usizeType;
|
||||
if (operands.length > 1) {
|
||||
|
@ -367,7 +367,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
// try (lib)/file.ts
|
||||
// try ~lib/file.ts
|
||||
expected = LIBRARY_PREFIX + normalizedPathWithoutExtension + ".ts";
|
||||
for (let i = 0, k = sources.length; i < k; ++i) {
|
||||
let source = sources[i];
|
||||
|
@ -64,6 +64,7 @@ export enum DiagnosticCode {
|
||||
Declaration_expected = 1146,
|
||||
_const_declarations_must_be_initialized = 1155,
|
||||
Unterminated_regular_expression_literal = 1161,
|
||||
Interface_declaration_cannot_have_implements_clause = 1176,
|
||||
Binary_digit_expected = 1177,
|
||||
Octal_digit_expected = 1178,
|
||||
An_implementation_cannot_be_declared_in_ambient_contexts = 1183,
|
||||
@ -169,6 +170,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 1146: return "Declaration expected.";
|
||||
case 1155: return "'const' declarations must be initialized.";
|
||||
case 1161: return "Unterminated regular expression literal.";
|
||||
case 1176: return "Interface declaration cannot have 'implements' clause.";
|
||||
case 1177: return "Binary digit expected.";
|
||||
case 1178: return "Octal digit expected.";
|
||||
case 1183: return "An implementation cannot be declared in ambient contexts.";
|
||||
|
@ -57,6 +57,7 @@
|
||||
"Declaration expected.": 1146,
|
||||
"'const' declarations must be initialized.": 1155,
|
||||
"Unterminated regular expression literal.": 1161,
|
||||
"Interface declaration cannot have 'implements' clause.": 1176,
|
||||
"Binary digit expected.": 1177,
|
||||
"Octal digit expected.": 1178,
|
||||
"An implementation cannot be declared in ambient contexts.": 1183,
|
||||
|
@ -784,13 +784,15 @@ export class ASTBuilder {
|
||||
this.visitTypeNode(extendsType);
|
||||
}
|
||||
var implementsTypes = node.implementsTypes;
|
||||
var numImplementsTypes = implementsTypes.length;
|
||||
if (numImplementsTypes) {
|
||||
sb.push(" implements ");
|
||||
this.visitTypeNode(implementsTypes[0]);
|
||||
for (let i = 1; i < numImplementsTypes; ++i) {
|
||||
sb.push(", ");
|
||||
this.visitTypeNode(implementsTypes[i]);
|
||||
if (implementsTypes) {
|
||||
let numImplementsTypes = implementsTypes.length;
|
||||
if (numImplementsTypes) {
|
||||
sb.push(" implements ");
|
||||
this.visitTypeNode(implementsTypes[0]);
|
||||
for (let i = 1; i < numImplementsTypes; ++i) {
|
||||
sb.push(", ");
|
||||
this.visitTypeNode(implementsTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
var members = node.members;
|
||||
@ -1123,6 +1125,7 @@ export class ASTBuilder {
|
||||
sb.push(" extends ");
|
||||
this.visitTypeNode(extendsType);
|
||||
}
|
||||
// must not have implementsTypes
|
||||
sb.push(" {\n");
|
||||
var indentLevel = ++this.indentLevel;
|
||||
var members = node.members;
|
||||
|
@ -262,9 +262,10 @@ export class Parser extends DiagnosticEmitter {
|
||||
}
|
||||
// fall through
|
||||
}
|
||||
case Token.CLASS: {
|
||||
case Token.CLASS:
|
||||
case Token.INTERFACE: {
|
||||
tn.next();
|
||||
statement = this.parseClass(tn, flags, decorators, startPos);
|
||||
statement = this.parseClassOrInterface(tn, flags, decorators, startPos);
|
||||
decorators = null;
|
||||
break;
|
||||
}
|
||||
@ -1381,20 +1382,22 @@ export class Parser extends DiagnosticEmitter {
|
||||
return Node.createFunctionExpression(declaration);
|
||||
}
|
||||
|
||||
parseClass(
|
||||
parseClassOrInterface(
|
||||
tn: Tokenizer,
|
||||
flags: CommonFlags,
|
||||
decorators: DecoratorNode[] | null,
|
||||
startPos: i32
|
||||
): ClassDeclaration | null {
|
||||
|
||||
// at 'class':
|
||||
// at ('class' | 'interface'):
|
||||
// Identifier
|
||||
// ('<' TypeParameters)?
|
||||
// ('extends' Type)?
|
||||
// ('implements' Type (',' Type)*)?
|
||||
// '{' ClassMember* '}'
|
||||
|
||||
var isInterface = tn.token == Token.INTERFACE;
|
||||
|
||||
if (!tn.skip(Token.IDENTIFIER)) {
|
||||
this.error(
|
||||
DiagnosticCode.Identifier_expected,
|
||||
@ -1431,12 +1434,21 @@ export class Parser extends DiagnosticEmitter {
|
||||
extendsType = <TypeNode>t;
|
||||
}
|
||||
|
||||
var implementsTypes = new Array<TypeNode>();
|
||||
var implementsTypes: TypeNode[] | null = null;
|
||||
if (tn.skip(Token.IMPLEMENTS)) {
|
||||
if (isInterface) {
|
||||
this.error(
|
||||
DiagnosticCode.Interface_declaration_cannot_have_implements_clause,
|
||||
tn.range()
|
||||
); // recoverable
|
||||
}
|
||||
do {
|
||||
let type = this.parseType(tn);
|
||||
if (!type) return null;
|
||||
implementsTypes.push(<TypeNode>type);
|
||||
if (!isInterface) {
|
||||
if (!implementsTypes) implementsTypes = [];
|
||||
implementsTypes.push(<TypeNode>type);
|
||||
}
|
||||
} while (tn.skip(Token.COMMA));
|
||||
}
|
||||
|
||||
@ -1449,16 +1461,30 @@ export class Parser extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
var members = new Array<DeclarationStatement>();
|
||||
var declaration = Node.createClassDeclaration(
|
||||
identifier,
|
||||
typeParameters,
|
||||
extendsType,
|
||||
implementsTypes,
|
||||
members,
|
||||
decorators,
|
||||
flags,
|
||||
tn.range(startPos, tn.pos)
|
||||
);
|
||||
var declaration: ClassDeclaration;
|
||||
if (isInterface) {
|
||||
assert(!implementsTypes);
|
||||
declaration = Node.createInterfaceDeclaration(
|
||||
identifier,
|
||||
typeParameters,
|
||||
extendsType,
|
||||
members,
|
||||
decorators,
|
||||
flags,
|
||||
tn.range(startPos, tn.pos)
|
||||
);
|
||||
} else {
|
||||
declaration = Node.createClassDeclaration(
|
||||
identifier,
|
||||
typeParameters,
|
||||
extendsType,
|
||||
implementsTypes,
|
||||
members,
|
||||
decorators,
|
||||
flags,
|
||||
tn.range(startPos, tn.pos)
|
||||
);
|
||||
}
|
||||
if (!tn.skip(Token.CLOSEBRACE)) {
|
||||
do {
|
||||
let member = this.parseClassMember(tn, declaration);
|
||||
|
@ -85,7 +85,7 @@ export const INSTANCE_DELIMITER = "#";
|
||||
/** Delimiter used between class and namespace names and static members. */
|
||||
export const STATIC_DELIMITER = ".";
|
||||
/** Substitution used to indicate a library directory. */
|
||||
export const LIBRARY_SUBST = "(lib)";
|
||||
export const LIBRARY_SUBST = "~lib";
|
||||
/** Library directory prefix. */
|
||||
export const LIBRARY_PREFIX = LIBRARY_SUBST + PATH_DELIMITER;
|
||||
|
||||
@ -417,23 +417,25 @@ export class Program extends DiagnosticEmitter {
|
||||
this.elementsLookup.set(internalName, prototype);
|
||||
|
||||
var implementsTypes = declaration.implementsTypes;
|
||||
var numImplementsTypes = implementsTypes.length;
|
||||
if (prototype.is(CommonFlags.UNMANAGED)) {
|
||||
if (implementsTypes && numImplementsTypes) {
|
||||
this.error(
|
||||
DiagnosticCode.Structs_cannot_implement_interfaces,
|
||||
Range.join(
|
||||
declaration.name.range,
|
||||
implementsTypes[numImplementsTypes - 1].range
|
||||
)
|
||||
);
|
||||
}
|
||||
} else if (numImplementsTypes) {
|
||||
for (let i = 0; i < numImplementsTypes; ++i) {
|
||||
this.error(
|
||||
DiagnosticCode.Operation_not_supported,
|
||||
implementsTypes[i].range
|
||||
);
|
||||
if (implementsTypes) {
|
||||
let numImplementsTypes = implementsTypes.length;
|
||||
if (prototype.is(CommonFlags.UNMANAGED)) {
|
||||
if (implementsTypes && numImplementsTypes) {
|
||||
this.error(
|
||||
DiagnosticCode.Structs_cannot_implement_interfaces,
|
||||
Range.join(
|
||||
declaration.name.range,
|
||||
implementsTypes[numImplementsTypes - 1].range
|
||||
)
|
||||
);
|
||||
}
|
||||
} else if (numImplementsTypes) {
|
||||
for (let i = 0; i < numImplementsTypes; ++i) {
|
||||
this.error(
|
||||
DiagnosticCode.Operation_not_supported,
|
||||
implementsTypes[i].range
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user