mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-21 10:41:42 +00:00
Stdlib preparations
This commit is contained in:
59
src/ast.ts
59
src/ast.ts
@ -109,6 +109,7 @@ export enum NodeKind {
|
||||
SUPER,
|
||||
THIS,
|
||||
TRUE,
|
||||
CONSTRUCTOR,
|
||||
UNARYPOSTFIX,
|
||||
UNARYPREFIX,
|
||||
|
||||
@ -240,6 +241,12 @@ export abstract class Expression extends Node {
|
||||
return expr;
|
||||
}
|
||||
|
||||
static createConstructor(range: Range): ConstructorExpression {
|
||||
const expr: ConstructorExpression = new ConstructorExpression();
|
||||
expr.range = range;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static createElementAccess(expression: Expression, element: Expression, range: Range): ElementAccessExpression {
|
||||
const expr: ElementAccessExpression = new ElementAccessExpression();
|
||||
expr.range = range;
|
||||
@ -357,6 +364,16 @@ export abstract class Expression extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
export class IdentifierExpression extends Expression {
|
||||
|
||||
kind = NodeKind.IDENTIFIER;
|
||||
name: string;
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
sb.push(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
export const enum LiteralKind {
|
||||
FLOAT,
|
||||
INTEGER,
|
||||
@ -459,6 +476,11 @@ export class CallExpression extends Expression {
|
||||
}
|
||||
}
|
||||
|
||||
export class ConstructorExpression extends IdentifierExpression {
|
||||
kind = NodeKind.CONSTRUCTOR;
|
||||
name = "this";
|
||||
}
|
||||
|
||||
export class ElementAccessExpression extends Expression {
|
||||
|
||||
kind = NodeKind.ELEMENTACCESS;
|
||||
@ -483,16 +505,6 @@ export class FloatLiteralExpression extends LiteralExpression {
|
||||
}
|
||||
}
|
||||
|
||||
export class IdentifierExpression extends Expression {
|
||||
|
||||
kind = NodeKind.IDENTIFIER;
|
||||
name: string;
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
sb.push(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
export class IntegerLiteralExpression extends LiteralExpression {
|
||||
|
||||
literalKind = LiteralKind.INTEGER;
|
||||
@ -641,8 +653,9 @@ export enum ModifierKind {
|
||||
PUBLIC,
|
||||
PRIVATE,
|
||||
PROTECTED,
|
||||
READONLY,
|
||||
GET,
|
||||
SET
|
||||
SET,
|
||||
}
|
||||
|
||||
export abstract class Statement extends Node {
|
||||
@ -1052,7 +1065,7 @@ export class ClassDeclaration extends DeclarationStatement {
|
||||
if (this._cachedInternalName !== null)
|
||||
return this._cachedInternalName;
|
||||
const globalDecorator: Decorator | null = this.decorators ? getDecoratorByName("global", this.decorators) : null;
|
||||
if (globalDecorator && globalDecorator.expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>globalDecorator.expression).name == "global")
|
||||
if (globalDecorator)
|
||||
return this._cachedInternalName = this.identifier.name;
|
||||
else
|
||||
return this._cachedInternalName = mangleInternalName(this);
|
||||
@ -1589,9 +1602,10 @@ export class Modifier extends Node {
|
||||
case ModifierKind.PRIVATE: sb.push("private"); break;
|
||||
case ModifierKind.PROTECTED: sb.push("protected"); break;
|
||||
case ModifierKind.PUBLIC: sb.push("public"); break;
|
||||
case ModifierKind.READONLY: sb.push("readonly"); break;
|
||||
case ModifierKind.SET: sb.push("set"); break;
|
||||
case ModifierKind.STATIC: sb.push("static"); break;
|
||||
default: sb.push("INVALID"); break;
|
||||
default: throw new Error("unexpected modifier kind");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1772,16 +1786,21 @@ export function hasModifier(kind: ModifierKind, modifiers: Modifier[] | null): b
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getDecoratorByName(name: string, decorators: Decorator[]): Decorator | null {
|
||||
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
||||
const decorator: Decorator = decorators[i];
|
||||
const expression: Expression = decorator.expression;
|
||||
if (expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>expression).name == name)
|
||||
return decorator;
|
||||
}
|
||||
function getDecoratorByName(name: string, decorators: Decorator[] | null): Decorator | null {
|
||||
if (decorators)
|
||||
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
||||
const decorator: Decorator = decorators[i];
|
||||
const expression: Expression = decorator.expression;
|
||||
if (expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>expression).name == name)
|
||||
return decorator;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function hasDecorator(name: string, decorators: Decorator[] | null): bool {
|
||||
return getDecoratorByName(name, decorators) != null;
|
||||
}
|
||||
|
||||
export function serialize(node: Node, indent: i32 = 0): string {
|
||||
const sb: string[] = new Array(); // shared builder could grow too much
|
||||
node.serialize(sb);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Compiler, Target, ConversionKind, typeToNativeType, typeToNativeOne, typeToNativeZero } from "./compiler";
|
||||
import { DiagnosticCode } from "./diagnostics";
|
||||
import { Node, Expression } from "./ast";
|
||||
import { Node, Expression, IdentifierExpression } from "./ast";
|
||||
import { Type } from "./types";
|
||||
import { Module, ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType, FunctionTypeRef } from "./module";
|
||||
import { Program, ElementFlags, Element, Global, FunctionPrototype, Local } from "./program";
|
||||
@ -9,6 +9,9 @@ import { Program, ElementFlags, Element, Global, FunctionPrototype, Local } from
|
||||
export function initialize(program: Program): void {
|
||||
|
||||
// math
|
||||
addConstant(program, "NaN", Type.f64);
|
||||
addConstant(program, "Infinity", Type.f64);
|
||||
|
||||
addFunction(program, "isNaN", true);
|
||||
addFunction(program, "isFinite", true);
|
||||
addFunction(program, "clz", true);
|
||||
@ -96,12 +99,24 @@ export function initialize(program: Program): void {
|
||||
if (program.target == Target.WASM64) {
|
||||
program.elements.set("isize", <Element>program.elements.get("i64"));
|
||||
program.elements.set("usize", <Element>program.elements.get("u64"));
|
||||
addConstant(program, "HEAP_START", Type.usize64);
|
||||
} else {
|
||||
program.elements.set("isize", <Element>program.elements.get("i32"));
|
||||
program.elements.set("usize", <Element>program.elements.get("u32"));
|
||||
addConstant(program, "HEAP_START", Type.usize32);
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a built-in global to the specified program. */
|
||||
function addConstant(program: Program, name: string, type: Type): Global {
|
||||
const global: Global = new Global(program, name, null, null);
|
||||
global.isBuiltIn = true;
|
||||
global.isConstant = true;
|
||||
global.type = type;
|
||||
program.elements.set(name, global);
|
||||
return global;
|
||||
}
|
||||
|
||||
/** Adds a built-in function to the specified program. */
|
||||
function addFunction(program: Program, name: string, isGeneric: bool = false): FunctionPrototype {
|
||||
let prototype: FunctionPrototype = new FunctionPrototype(program, name, name, null, null);
|
||||
@ -111,6 +126,29 @@ function addFunction(program: Program, name: string, isGeneric: bool = false): F
|
||||
return prototype;
|
||||
}
|
||||
|
||||
export function compileGetGlobal(compiler: Compiler, global: Global): ExpressionRef {
|
||||
switch (global.internalName) {
|
||||
|
||||
case "NaN":
|
||||
if (compiler.currentType == Type.f32)
|
||||
return compiler.module.createF32(NaN);
|
||||
compiler.currentType = Type.f64;
|
||||
return compiler.module.createF64(NaN);
|
||||
|
||||
case "Infinity":
|
||||
if (compiler.currentType == Type.f32)
|
||||
return compiler.module.createF32(Infinity);
|
||||
compiler.currentType = Type.f64;
|
||||
return compiler.module.createF64(Infinity);
|
||||
|
||||
case "HEAP_START": // never inlined
|
||||
return compiler.module.createGetGlobal("HEAP_START", typeToNativeType(<Type>global.type));
|
||||
|
||||
default:
|
||||
throw new Error("not implemented: " + global.internalName);
|
||||
}
|
||||
}
|
||||
|
||||
/** Compiles a call to a built-in function. */
|
||||
export function compileCall(compiler: Compiler, prototype: FunctionPrototype, typeArguments: Type[], operands: Expression[], reportNode: Node): ExpressionRef {
|
||||
const module: Module = compiler.module;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { compileCall as compileBuiltinCall, initialize } from "./builtins";
|
||||
import { compileCall as compileBuiltinCall, compileGetGlobal as compileBuiltinGetGlobal, initialize } from "./builtins";
|
||||
import { PATH_DELIMITER } from "./constants";
|
||||
import { DiagnosticCode, DiagnosticEmitter } from "./diagnostics";
|
||||
import {
|
||||
@ -324,6 +324,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
compileGlobal(global: Global): bool {
|
||||
if (global.isCompiled)
|
||||
return true;
|
||||
if (global.isBuiltIn)
|
||||
if (compileBuiltinGetGlobal(this, global))
|
||||
return true;
|
||||
|
||||
const declaration: VariableLikeDeclarationStatement | null = global.declaration;
|
||||
let type: Type | null = global.type;
|
||||
if (!type) {
|
||||
@ -376,6 +380,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
initializer = typeToNativeZero(this.module, type);
|
||||
} else
|
||||
throw new Error("unexpected missing declaration or constant value");
|
||||
|
||||
const internalName: string = global.internalName;
|
||||
if (initializeInStart) {
|
||||
this.module.addGlobal(internalName, nativeType, true, typeToNativeZero(this.module, type));
|
||||
@ -1606,14 +1611,15 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
if (element.kind == ElementKind.GLOBAL) {
|
||||
this.compileGlobal(<Global>element);
|
||||
if (!(<Global>element).isMutable)
|
||||
if (!this.compileGlobal(<Global>element))
|
||||
return this.module.createUnreachable();
|
||||
this.currentType = <Type>(<Global>element).type;
|
||||
if (!(<Global>element).isMutable) {
|
||||
this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, element.internalName);
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
if (tee) {
|
||||
if (!(<Global>element).type)
|
||||
return this.module.createUnreachable();
|
||||
const globalNativeType: NativeType = typeToNativeType(<Type>(<Global>element).type);
|
||||
this.currentType = <Type>(<Global>element).type;
|
||||
return this.module.createBlock(null, [ // teeGlobal
|
||||
this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType),
|
||||
this.module.createGetGlobal((<Global>element).internalName, globalNativeType)
|
||||
@ -1759,22 +1765,6 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
||||
this.currentType = this.options.target == Target.WASM64 ? Type.u64 : Type.u32;
|
||||
return this.module.createUnreachable();
|
||||
|
||||
case NodeKind.IDENTIFIER:
|
||||
// TODO: some sort of resolveIdentifier maybe
|
||||
if ((<IdentifierExpression>expression).name == "NaN") {
|
||||
if (this.currentType == Type.f32)
|
||||
return this.module.createF32(NaN);
|
||||
this.currentType = Type.f64;
|
||||
return this.module.createF64(NaN);
|
||||
}
|
||||
if ((<IdentifierExpression>expression).name == "Infinity") {
|
||||
if (this.currentType == Type.f32)
|
||||
return this.module.createF32(Infinity);
|
||||
this.currentType = Type.f64;
|
||||
return this.module.createF64(Infinity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const element: Element | null = this.program.resolveElement(expression, this.currentFunction); // reports
|
||||
@ -1789,6 +1779,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// global
|
||||
if (element.kind == ElementKind.GLOBAL) {
|
||||
if (element.isBuiltIn)
|
||||
return compileBuiltinGetGlobal(this, <Global>element);
|
||||
|
||||
const global: Global = <Global>element;
|
||||
if (!this.compileGlobal(global)) // reports
|
||||
return this.module.createUnreachable();
|
||||
|
@ -66,6 +66,7 @@ export enum DiagnosticCode {
|
||||
Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures = 2349,
|
||||
The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access = 2357,
|
||||
The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access = 2364,
|
||||
Constructor_implementation_is_missing = 2390,
|
||||
Function_implementation_is_missing_or_not_immediately_following_the_declaration = 2391,
|
||||
Duplicate_function_implementation = 2393,
|
||||
Export_declaration_conflicts_with_exported_declaration_of_0 = 2484,
|
||||
@ -145,6 +146,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 2349: return "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures.";
|
||||
case 2357: return "The operand of an increment or decrement operator must be a variable or a property access.";
|
||||
case 2364: return "The left-hand side of an assignment expression must be a variable or a property access.";
|
||||
case 2390: return "Constructor implementation is missing.";
|
||||
case 2391: return "Function implementation is missing or not immediately following the declaration.";
|
||||
case 2393: return "Duplicate function implementation.";
|
||||
case 2484: return "Export declaration conflicts with exported declaration of '{0}'.";
|
||||
|
@ -66,6 +66,7 @@
|
||||
"Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures.": 2349,
|
||||
"The operand of an increment or decrement operator must be a variable or a property access.": 2357,
|
||||
"The left-hand side of an assignment expression must be a variable or a property access.": 2364,
|
||||
"Constructor implementation is missing.": 2390,
|
||||
"Function implementation is missing or not immediately following the declaration.": 2391,
|
||||
"Duplicate function implementation.": 2393,
|
||||
"Export declaration conflicts with exported declaration of '{0}'.": 2484,
|
||||
|
@ -694,6 +694,9 @@ export class Parser extends DiagnosticEmitter {
|
||||
else if (tn.skip(Token.ABSTRACT))
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
|
||||
|
||||
if (tn.skip(Token.READONLY))
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.READONLY, tn.range()), modifiers);
|
||||
|
||||
let isGetter: bool = false;
|
||||
let isSetter: bool = false;
|
||||
if (tn.skip(Token.GET)) {
|
||||
@ -704,16 +707,23 @@ export class Parser extends DiagnosticEmitter {
|
||||
isSetter = true;
|
||||
}
|
||||
|
||||
if (tn.skip(Token.IDENTIFIER)) {
|
||||
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
|
||||
if (tn.skip(Token.IDENTIFIER) || tn.skip(Token.CONSTRUCTOR)) {
|
||||
const identifier: IdentifierExpression = tn.token == Token.CONSTRUCTOR
|
||||
? Expression.createConstructor(tn.range())
|
||||
: Expression.createIdentifier(tn.readIdentifier(), tn.range());
|
||||
let typeParameters: TypeParameter[] | null;
|
||||
if (tn.skip(Token.LESSTHAN)) {
|
||||
if (identifier.kind == NodeKind.CONSTRUCTOR)
|
||||
this.error(DiagnosticCode.Type_parameters_cannot_appear_on_a_constructor_declaration, tn.range()); // recoverable
|
||||
typeParameters = this.parseTypeParameters(tn);
|
||||
if (!typeParameters)
|
||||
return null;
|
||||
} else
|
||||
typeParameters = [];
|
||||
|
||||
if (identifier.kind == NodeKind.CONSTRUCTOR && tn.peek() != Token.OPENPAREN)
|
||||
this.error(DiagnosticCode.Constructor_implementation_is_missing, tn.range());
|
||||
|
||||
// method: '(' Parameters (':' Type)? '{' Statement* '}' ';'?
|
||||
if (tn.skip(Token.OPENPAREN)) {
|
||||
let parameters = this.parseParameters(tn);
|
||||
@ -729,14 +739,18 @@ export class Parser extends DiagnosticEmitter {
|
||||
}
|
||||
let returnType: TypeNode | null = null;
|
||||
if (tn.skip(Token.COLON)) {
|
||||
returnType = this.parseType(tn, isSetter);
|
||||
if (identifier.kind == NodeKind.CONSTRUCTOR)
|
||||
this.error(DiagnosticCode.Type_annotation_cannot_appear_on_a_constructor_declaration, tn.range());
|
||||
else if (isSetter)
|
||||
this.error(DiagnosticCode.A_set_accessor_cannot_have_a_return_type_annotation, tn.range());
|
||||
returnType = this.parseType(tn, identifier.kind == NodeKind.CONSTRUCTOR || isSetter);
|
||||
if (!returnType)
|
||||
return null;
|
||||
} else {
|
||||
if (isSetter) {
|
||||
if (parameters.length)
|
||||
returnType = parameters[0].type;
|
||||
} else
|
||||
} else if (identifier.kind != NodeKind.CONSTRUCTOR)
|
||||
this.error(DiagnosticCode.Type_expected, tn.range()); // recoverable
|
||||
}
|
||||
let statements: Statement[] | null = null;
|
||||
@ -1323,36 +1337,21 @@ export class Parser extends DiagnosticEmitter {
|
||||
|
||||
let p: Precedence = determinePrecedencePrefix(token);
|
||||
if (p != Precedence.INVALID) {
|
||||
const operand: Expression | null = this.parseExpression(tn, p);
|
||||
if (!operand)
|
||||
return null;
|
||||
let operand: Expression | null
|
||||
|
||||
// TODO: SpreadExpression, YieldExpression (currently become unsupported UnaryPrefixExpressions)
|
||||
|
||||
// NewExpression
|
||||
if (token == Token.NEW) {
|
||||
if (operand.kind == NodeKind.IDENTIFIER || operand.kind == NodeKind.PROPERTYACCESS) {
|
||||
const args: Expression[] = new Array();
|
||||
if (tn.skip(Token.OPENPAREN)) {
|
||||
if (tn.peek() != Token.CLOSEPAREN) {
|
||||
do {
|
||||
expr = this.parseExpression(tn, Precedence.COMMA + 1);
|
||||
if (!expr)
|
||||
return null;
|
||||
args.push(expr);
|
||||
} while (tn.skip(Token.COMMA));
|
||||
}
|
||||
if (!tn.skip(Token.CLOSEPAREN)) {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), ")");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return Expression.createNew(operand, [], args, tn.range(startPos, tn.pos));
|
||||
} else {
|
||||
this.error(DiagnosticCode.Identifier_expected, tn.range());
|
||||
operand = this.parseExpression(tn, Precedence.CALL);
|
||||
if (!operand)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (operand.kind == NodeKind.CALL)
|
||||
return Expression.createNew((<CallExpression>operand).expression, (<CallExpression>operand).typeArguments, (<CallExpression>operand).arguments, tn.range(startPos, tn.pos));
|
||||
this.error(DiagnosticCode.Operation_not_supported, tn.range());
|
||||
return null;
|
||||
} else
|
||||
operand = this.parseExpression(tn, p);
|
||||
|
||||
// UnaryPrefixExpression
|
||||
if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS)
|
||||
@ -1406,7 +1405,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), ">");
|
||||
return null;
|
||||
}
|
||||
expr = this.parseExpressionPrefix(tn);
|
||||
expr = this.parseExpression(tn, Precedence.CALL);
|
||||
if (!expr)
|
||||
return null;
|
||||
return Expression.createAssertion(AssertionKind.PREFIX, <Expression>expr, <TypeNode>toType, tn.range(startPos, tn.pos));
|
||||
@ -1416,6 +1415,15 @@ export class Parser extends DiagnosticEmitter {
|
||||
case Token.IDENTIFIER:
|
||||
return Expression.createIdentifier(tn.readIdentifier(), tn.range(startPos, tn.pos));
|
||||
|
||||
case Token.THIS:
|
||||
return Expression.createThis(tn.range(startPos, tn.pos));
|
||||
|
||||
case Token.CONSTRUCTOR:
|
||||
return Expression.createConstructor(tn.range(startPos, tn.pos));
|
||||
|
||||
case Token.SUPER:
|
||||
return Expression.createSuper(tn.range(startPos, tn.pos));
|
||||
|
||||
// StringLiteralExpression
|
||||
case Token.STRINGLITERAL:
|
||||
return Expression.createStringLiteral(tn.readString(), tn.range(startPos, tn.pos));
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
LiteralKind,
|
||||
PropertyAccessExpression,
|
||||
StringLiteralExpression,
|
||||
CallExpression,
|
||||
|
||||
ClassDeclaration,
|
||||
DeclarationStatement,
|
||||
@ -101,7 +102,9 @@ export class Program extends DiagnosticEmitter {
|
||||
["bool", Type.bool],
|
||||
["f32", Type.f32],
|
||||
["f64", Type.f64],
|
||||
["void", Type.void]
|
||||
["void", Type.void],
|
||||
["number", Type.f64],
|
||||
["boolean", Type.bool]
|
||||
]);
|
||||
|
||||
initializeBuiltins(this);
|
||||
@ -779,27 +782,26 @@ export class Program extends DiagnosticEmitter {
|
||||
// static or instance property (incl. enum values) or method
|
||||
} else if (expression.kind == NodeKind.PROPERTYACCESS) {
|
||||
return this.resolvePropertyAccess(<PropertyAccessExpression>expression, contextualFunction);
|
||||
|
||||
// instantiation
|
||||
} else if (expression.kind == NodeKind.NEW) {
|
||||
return this.resolveElement((<CallExpression>expression).expression, contextualFunction);
|
||||
}
|
||||
|
||||
throw new Error("not implemented: " + expression.kind);
|
||||
}
|
||||
}
|
||||
|
||||
function checkGlobalDecorator(decorators: Decorator[]): string | null {
|
||||
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
||||
const decorator: Decorator = decorators[i];
|
||||
const expression: Expression = decorator.expression;
|
||||
const args: Expression[] = decorator.arguments;
|
||||
if (expression.kind == NodeKind.IDENTIFIER && args.length <= 1 && (<IdentifierExpression>expression).name == "global") {
|
||||
if (args.length) {
|
||||
const firstArg: Expression = args[0];
|
||||
if (firstArg.kind == NodeKind.LITERAL && (<LiteralExpression>firstArg).literalKind == LiteralKind.STRING)
|
||||
return (<StringLiteralExpression>firstArg).value;
|
||||
} else
|
||||
return ""; // instead inherits declaration identifier
|
||||
function hasDecorator(name: string, decorators: Decorator[] | null): bool {
|
||||
if (decorators)
|
||||
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
||||
const decorator: Decorator = decorators[i];
|
||||
const expression: Expression = decorator.expression;
|
||||
const args: Expression[] = decorator.arguments;
|
||||
if (expression.kind == NodeKind.IDENTIFIER && args.length <= 1 && (<IdentifierExpression>expression).name == name)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Indicates the specific kind of an {@link Element}. */
|
||||
@ -857,7 +859,11 @@ export enum ElementFlags {
|
||||
/** Is getter. */
|
||||
GETTER = 1 << 9,
|
||||
/** Is setter. */
|
||||
SETTER = 1 << 10
|
||||
SETTER = 1 << 10,
|
||||
/** Is global. */
|
||||
GLOBAL = 1 << 11,
|
||||
/** Is read-only. */
|
||||
READONLY = 1 << 12
|
||||
}
|
||||
|
||||
/** Base class of all program elements. */
|
||||
@ -919,9 +925,13 @@ export abstract class Element {
|
||||
/** Whether an instance member or not. */
|
||||
get isInstance(): bool { return (this.flags & ElementFlags.INSTANCE) != 0; }
|
||||
set isInstance(is: bool) { if (is) this.flags |= ElementFlags.INSTANCE; else this.flags &= ~ElementFlags.INSTANCE; }
|
||||
|
||||
/** Whether a member of the global namespace or not. */
|
||||
get isGlobal(): bool { return (this.flags & ElementFlags.GLOBAL) != 0; }
|
||||
set isGlobal(is: bool) { if (is) this.flags |= ElementFlags.GLOBAL; else this.flags &= ~ElementFlags.GLOBAL; }
|
||||
}
|
||||
|
||||
/** A namespace. Also the base class of other namespace-like program elements. */
|
||||
/** A namespace. */
|
||||
export class Namespace extends Element {
|
||||
|
||||
kind = ElementKind.NAMESPACE;
|
||||
@ -985,8 +995,7 @@ export class EnumValue extends Element {
|
||||
constructor(enm: Enum, program: Program, internalName: string, declaration: EnumValueDeclaration | null = null) {
|
||||
super(program, internalName);
|
||||
this.enum = enm;
|
||||
if (!(this.declaration = declaration))
|
||||
this.hasConstantValue = true; // built-ins have constant values
|
||||
this.declaration = declaration;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1185,7 +1194,7 @@ export class FunctionPrototype extends Element {
|
||||
resolveInclTypeArguments(typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null, alternativeReportNode: Node | null): Function | null {
|
||||
let resolvedTypeArguments: Type[] | null;
|
||||
if (this.isGeneric) {
|
||||
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
|
||||
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0, "" + this);
|
||||
if (!this.declaration)
|
||||
throw new Error("missing declaration");
|
||||
resolvedTypeArguments = this.program.resolveTypeArguments(this.declaration.typeParameters, typeArgumentNodes, contextualTypeArguments, alternativeReportNode);
|
||||
@ -1372,11 +1381,17 @@ export class FieldPrototype extends Element {
|
||||
for (let i: i32 = 0, k = this.declaration.modifiers.length; i < k; ++i) {
|
||||
switch (this.declaration.modifiers[i].modifierKind) {
|
||||
case ModifierKind.EXPORT: this.isExported = true; break;
|
||||
case ModifierKind.READONLY: this.isReadonly = true; break;
|
||||
case ModifierKind.STATIC: break; // already handled
|
||||
default: throw new Error("unexpected modifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether the field is read-only or not. */
|
||||
get isReadonly(): bool { return (this.flags & ElementFlags.READONLY) != 0; }
|
||||
set isReadonly(is: bool) { if (is) this.flags |= ElementFlags.READONLY; else this.flags &= ~ElementFlags.READONLY; }
|
||||
}
|
||||
|
||||
/** A resolved instance field. */
|
||||
|
Reference in New Issue
Block a user