mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-15 07:51:32 +00:00
Reintroduce builtin decorator so these can appear anywhere in stdlib again
Avoids wrapping an undocumented function within 'memory.size' for example.
This commit is contained in:
@ -1122,7 +1122,8 @@ export enum DecoratorKind {
|
||||
UNMANAGED,
|
||||
SEALED,
|
||||
INLINE,
|
||||
EXTERNAL
|
||||
EXTERNAL,
|
||||
BUILTIN
|
||||
}
|
||||
|
||||
/** Returns the kind of the specified decorator. Defaults to {@link DecoratorKind.CUSTOM}. */
|
||||
@ -1132,6 +1133,10 @@ export function decoratorNameToKind(name: Expression): DecoratorKind {
|
||||
let nameStr = (<IdentifierExpression>name).text;
|
||||
assert(nameStr.length);
|
||||
switch (nameStr.charCodeAt(0)) {
|
||||
case CharCode.b: {
|
||||
if (nameStr == "builtin") return DecoratorKind.BUILTIN;
|
||||
break;
|
||||
}
|
||||
case CharCode.e: {
|
||||
if (nameStr == "external") return DecoratorKind.EXTERNAL;
|
||||
break;
|
||||
|
@ -1871,7 +1871,7 @@ export function compileCall(
|
||||
|
||||
// host operations
|
||||
|
||||
case "__memory_size": { // __memory_size() -> i32
|
||||
case "memory.size": { // memory.size() -> i32
|
||||
compiler.currentType = Type.i32;
|
||||
if (operands.length != 0) {
|
||||
compiler.error(
|
||||
@ -1887,7 +1887,7 @@ export function compileCall(
|
||||
}
|
||||
return module.createHost(HostOp.CurrentMemory);
|
||||
}
|
||||
case "__memory_grow": { // __memory_grow(pages: i32) -> i32
|
||||
case "memory.grow": { // memory.grow(pages: i32) -> i32
|
||||
compiler.currentType = Type.i32;
|
||||
if (operands.length != 1) {
|
||||
compiler.error(
|
||||
@ -1907,7 +1907,7 @@ export function compileCall(
|
||||
return module.createHost(HostOp.GrowMemory, null, [ arg0 ]);
|
||||
}
|
||||
// see: https://github.com/WebAssembly/bulk-memory-operations
|
||||
case "__memory_copy": { // __memory_copy(dest: usize, src: usize: n: usize) -> void
|
||||
case "memory.copy": { // memory.copy(dest: usize, src: usize: n: usize) -> void
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_generic,
|
||||
@ -1944,7 +1944,7 @@ export function compileCall(
|
||||
throw new Error("not implemented");
|
||||
// return module.createHost(HostOp.MoveMemory, null, [ arg0, arg1, arg2 ]);
|
||||
}
|
||||
case "__memory_fill": { // __memory_fill(dest: usize, value: u8, n: usize) -> void
|
||||
case "memory.fill": { // memory.fill(dest: usize, value: u8, n: usize) -> void
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_generic,
|
||||
@ -2629,7 +2629,7 @@ export function compileCall(
|
||||
|
||||
// gc
|
||||
|
||||
case "__gc_iterate_roots": {
|
||||
case "gc.iterateRoots": {
|
||||
// TOOD: make it so that this can only be called from a library file?
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
|
@ -58,24 +58,22 @@ export enum CommonFlags {
|
||||
|
||||
// Compilation states
|
||||
|
||||
/** Is a builtin. */
|
||||
BUILTIN = 1 << 21,
|
||||
/** Is compiled. */
|
||||
COMPILED = 1 << 22,
|
||||
COMPILED = 1 << 21,
|
||||
/** Has a constant value and is therefore inlined. */
|
||||
INLINED = 1 << 23,
|
||||
INLINED = 1 << 22,
|
||||
/** Is scoped. */
|
||||
SCOPED = 1 << 24,
|
||||
SCOPED = 1 << 23,
|
||||
/** Is a trampoline. */
|
||||
TRAMPOLINE = 1 << 25,
|
||||
TRAMPOLINE = 1 << 24,
|
||||
/** Is a virtual method. */
|
||||
VIRTUAL = 1 << 26,
|
||||
VIRTUAL = 1 << 25,
|
||||
/** Is the main function. */
|
||||
MAIN = 1 << 27,
|
||||
MAIN = 1 << 26,
|
||||
|
||||
// Other
|
||||
|
||||
QUOTED = 1 << 28
|
||||
QUOTED = 1 << 27
|
||||
}
|
||||
|
||||
/** Path delimiter inserted between file system levels. */
|
||||
|
@ -727,7 +727,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
// ambient builtins like 'HEAP_BASE' need to be resolved but are added explicitly
|
||||
if (global.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) return true;
|
||||
if (global.is(CommonFlags.AMBIENT) && global.hasDecorator(DecoratorFlags.BUILTIN)) return true;
|
||||
|
||||
var nativeType = global.type.toNativeType();
|
||||
var isDeclaredConstant = global.is(CommonFlags.CONST) || global.is(CommonFlags.STATIC | CommonFlags.READONLY);
|
||||
@ -1007,7 +1007,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
/** Compiles a readily resolved function instance. */
|
||||
compileFunction(instance: Function): bool {
|
||||
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||
assert(!instance.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN));
|
||||
assert(!(instance.is(CommonFlags.AMBIENT) && instance.hasDecorator(DecoratorFlags.BUILTIN)));
|
||||
instance.set(CommonFlags.COMPILED);
|
||||
|
||||
// check that modifiers are matching
|
||||
@ -1229,6 +1229,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
noTreeShaking || (<FunctionPrototype>element).is(CommonFlags.EXPORT)
|
||||
) && !(<FunctionPrototype>element).is(CommonFlags.GENERIC)
|
||||
) {
|
||||
if (element.hasDecorator(DecoratorFlags.BUILTIN)) break;
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
<FunctionPrototype>element,
|
||||
[],
|
||||
@ -2342,7 +2343,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
: this.module.createI64(0);
|
||||
}
|
||||
case TypeKind.F64: {
|
||||
if (!(element.is(CommonFlags.BUILTIN) && contextualType == Type.f32)) {
|
||||
// monkey-patch for converting built-in floats to f32 implicitly
|
||||
if (!(element.hasDecorator(DecoratorFlags.BUILTIN) && contextualType == Type.f32)) {
|
||||
return this.module.createF64((<VariableLikeElement>element).constantFloatValue);
|
||||
}
|
||||
// otherwise fall-through: basically precomputes f32.demote/f64 of NaN / Infinity
|
||||
@ -4967,7 +4969,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let typeArguments = expression.typeArguments;
|
||||
|
||||
// builtins handle present respectively omitted type arguments on their own
|
||||
if (prototype.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) {
|
||||
if (prototype.hasDecorator(DecoratorFlags.BUILTIN)) {
|
||||
return this.compileCallExpressionBuiltin(prototype, expression, contextualType);
|
||||
}
|
||||
|
||||
|
@ -86,8 +86,6 @@ import {
|
||||
nodeIsGenericCallable
|
||||
} from "./ast";
|
||||
|
||||
const builtinsFile = LIBRARY_PREFIX + "builtins.ts";
|
||||
|
||||
/** Parser interface. */
|
||||
export class Parser extends DiagnosticEmitter {
|
||||
|
||||
@ -135,11 +133,6 @@ export class Parser extends DiagnosticEmitter {
|
||||
var program = this.program;
|
||||
program.sources.push(source);
|
||||
|
||||
// mark the special builtins library file
|
||||
if (source.normalizedPath == builtinsFile) {
|
||||
source.set(CommonFlags.BUILTIN);
|
||||
}
|
||||
|
||||
// tokenize and parse
|
||||
var tn = new Tokenizer(source, program.diagnostics);
|
||||
tn.onComment = this.onComment;
|
||||
@ -176,9 +169,6 @@ export class Parser extends DiagnosticEmitter {
|
||||
decorators.push(decorator);
|
||||
}
|
||||
|
||||
// mark builtins
|
||||
flags |= (tn.source.flags & CommonFlags.BUILTIN);
|
||||
|
||||
// check modifiers
|
||||
var exportStart: i32 = 0;
|
||||
var exportEnd: i32 = 0;
|
||||
|
@ -708,7 +708,16 @@ export class Program extends DiagnosticEmitter {
|
||||
let kind = decoratorNameToKind(decorator.name);
|
||||
let flag = decoratorKindToFlag(kind);
|
||||
if (flag) {
|
||||
if (!(acceptedFlags & flag)) {
|
||||
if (flag == DecoratorFlags.BUILTIN) {
|
||||
if (decorator.range.source.isLibrary) {
|
||||
presentFlags |= flag;
|
||||
} else {
|
||||
this.error(
|
||||
DiagnosticCode.Decorator_0_is_not_valid_here,
|
||||
decorator.range, decorator.name.range.toString()
|
||||
);
|
||||
}
|
||||
} else if (!(acceptedFlags & flag)) {
|
||||
this.error(
|
||||
DiagnosticCode.Decorator_0_is_not_valid_here,
|
||||
decorator.range, decorator.name.range.toString()
|
||||
@ -732,13 +741,9 @@ export class Program extends DiagnosticEmitter {
|
||||
declaration: DeclarationStatement
|
||||
): void {
|
||||
var parentNode = declaration.parent;
|
||||
// alias the element globally if it is ...
|
||||
// alias globally if explicitly annotated @global or exported from a top-level library file
|
||||
if (
|
||||
// explicitly annotated with @global - or -
|
||||
(element.hasDecorator(DecoratorFlags.GLOBAL)) ||
|
||||
// part of the special builtins library file - or -
|
||||
(declaration.range.source.is(CommonFlags.BUILTIN)) ||
|
||||
// exported from a top-level library file
|
||||
(
|
||||
declaration.range.source.isLibrary &&
|
||||
element.is(CommonFlags.EXPORT) &&
|
||||
@ -758,10 +763,12 @@ export class Program extends DiagnosticEmitter {
|
||||
);
|
||||
} else {
|
||||
this.elementsLookup.set(globalName, element);
|
||||
// builtins can use the global name directly instead of being just an alias
|
||||
if (element.is(CommonFlags.BUILTIN)) element.internalName = globalName;
|
||||
}
|
||||
}
|
||||
// builtins use the global name directly
|
||||
if (element.hasDecorator(DecoratorFlags.BUILTIN)) {
|
||||
element.internalName = declaration.programLevelInternalName;
|
||||
}
|
||||
}
|
||||
|
||||
/** Initializes a class declaration. */
|
||||
@ -2040,7 +2047,9 @@ export enum DecoratorFlags {
|
||||
/** Is always inlined. */
|
||||
INLINE = 1 << 6,
|
||||
/** Is using a different external name. */
|
||||
EXTERNAL = 1 << 7
|
||||
EXTERNAL = 1 << 7,
|
||||
/** Is a builtin. */
|
||||
BUILTIN = 1 << 8
|
||||
}
|
||||
|
||||
export function decoratorKindToFlag(kind: DecoratorKind): DecoratorFlags {
|
||||
@ -2054,6 +2063,7 @@ export function decoratorKindToFlag(kind: DecoratorKind): DecoratorFlags {
|
||||
case DecoratorKind.SEALED: return DecoratorFlags.SEALED;
|
||||
case DecoratorKind.INLINE: return DecoratorFlags.INLINE;
|
||||
case DecoratorKind.EXTERNAL: return DecoratorFlags.EXTERNAL;
|
||||
case DecoratorKind.BUILTIN: return DecoratorFlags.BUILTIN;
|
||||
default: return DecoratorFlags.NONE;
|
||||
}
|
||||
}
|
||||
@ -2375,7 +2385,7 @@ export class Function extends Element {
|
||||
this.flags = prototype.flags;
|
||||
this.decoratorFlags = prototype.decoratorFlags;
|
||||
this.contextualTypeArguments = contextualTypeArguments;
|
||||
if (!(prototype.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN) || prototype.is(CommonFlags.DECLARE))) {
|
||||
if (!(prototype.is(CommonFlags.AMBIENT))) {
|
||||
let localIndex = 0;
|
||||
if (parent && parent.kind == ElementKind.CLASS) {
|
||||
assert(this.is(CommonFlags.INSTANCE));
|
||||
|
Reference in New Issue
Block a user