mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 23:12:19 +00:00
Add a way to ensure that lazy globals are resolved, fixes #355
This only affects static fields that currently must have a type annotation, while it wouldn't work if there wasn't an annotated type, like on normal globals, which aren't compiled lazily, though. Must be revisted if requirements on type annotations on fields ever become relaxed.
This commit is contained in:
parent
a661ff7d89
commit
0e33806cf6
@ -60,22 +60,24 @@ export enum CommonFlags {
|
|||||||
|
|
||||||
// Compilation states
|
// Compilation states
|
||||||
|
|
||||||
|
/** Is resolved. */
|
||||||
|
RESOLVED = 1 << 22,
|
||||||
/** Is compiled. */
|
/** Is compiled. */
|
||||||
COMPILED = 1 << 22,
|
COMPILED = 1 << 23,
|
||||||
/** Has a constant value and is therefore inlined. */
|
/** Has a constant value and is therefore inlined. */
|
||||||
INLINED = 1 << 23,
|
INLINED = 1 << 24,
|
||||||
/** Is scoped. */
|
/** Is scoped. */
|
||||||
SCOPED = 1 << 24,
|
SCOPED = 1 << 25,
|
||||||
/** Is a trampoline. */
|
/** Is a trampoline. */
|
||||||
TRAMPOLINE = 1 << 25,
|
TRAMPOLINE = 1 << 26,
|
||||||
/** Is a virtual method. */
|
/** Is a virtual method. */
|
||||||
VIRTUAL = 1 << 26,
|
VIRTUAL = 1 << 27,
|
||||||
/** Is the main function. */
|
/** Is the main function. */
|
||||||
MAIN = 1 << 27,
|
MAIN = 1 << 28,
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
QUOTED = 1 << 28
|
QUOTED = 1 << 29
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Path delimiter inserted between file system levels. */
|
/** Path delimiter inserted between file system levels. */
|
||||||
|
@ -696,7 +696,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var declaration = global.declaration;
|
var declaration = global.declaration;
|
||||||
var initExpr: ExpressionRef = 0;
|
var initExpr: ExpressionRef = 0;
|
||||||
|
|
||||||
if (global.type == Type.void) { // type is void if not yet resolved or not annotated
|
if (!global.is(CommonFlags.RESOLVED)) {
|
||||||
if (declaration) {
|
if (declaration) {
|
||||||
|
|
||||||
// resolve now if annotated
|
// resolve now if annotated
|
||||||
@ -711,6 +711,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
global.type = resolvedType;
|
global.type = resolvedType;
|
||||||
|
global.set(CommonFlags.RESOLVED);
|
||||||
|
|
||||||
// infer from initializer if not annotated
|
// infer from initializer if not annotated
|
||||||
} else if (declaration.initializer) { // infer type using void/NONE for literal inference
|
} else if (declaration.initializer) { // infer type using void/NONE for literal inference
|
||||||
@ -727,6 +728,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
global.type = this.currentType;
|
global.type = this.currentType;
|
||||||
|
global.set(CommonFlags.RESOLVED);
|
||||||
|
|
||||||
// must either be annotated or have an initializer
|
// must either be annotated or have an initializer
|
||||||
} else {
|
} else {
|
||||||
@ -737,7 +739,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(false); // must have a declaration if 'void' (and thus resolved later on)
|
assert(false); // must have a declaration if resolved lazily
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Options,
|
Options,
|
||||||
Feature
|
Feature,
|
||||||
|
Compiler
|
||||||
} from "./compiler";
|
} from "./compiler";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -730,19 +731,19 @@ export class Program extends DiagnosticEmitter {
|
|||||||
/** Sets a constant integer value. */
|
/** Sets a constant integer value. */
|
||||||
setConstantInteger(globalName: string, type: Type, value: I64): void {
|
setConstantInteger(globalName: string, type: Type, value: I64): void {
|
||||||
assert(type.is(TypeFlags.INTEGER));
|
assert(type.is(TypeFlags.INTEGER));
|
||||||
this.elementsLookup.set(globalName,
|
var global = new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
|
||||||
new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
|
.withConstantIntegerValue(value);
|
||||||
.withConstantIntegerValue(value)
|
global.set(CommonFlags.RESOLVED);
|
||||||
);
|
this.elementsLookup.set(globalName, global);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets a constant float value. */
|
/** Sets a constant float value. */
|
||||||
setConstantFloat(globalName: string, type: Type, value: f64): void {
|
setConstantFloat(globalName: string, type: Type, value: f64): void {
|
||||||
assert(type.is(TypeFlags.FLOAT));
|
assert(type.is(TypeFlags.FLOAT));
|
||||||
this.elementsLookup.set(globalName,
|
var global = new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
|
||||||
new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
|
.withConstantFloatValue(value);
|
||||||
.withConstantFloatValue(value)
|
global.set(CommonFlags.RESOLVED);
|
||||||
);
|
this.elementsLookup.set(globalName, global);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tries to locate an import by traversing exports and queued exports. */
|
/** Tries to locate an import by traversing exports and queued exports. */
|
||||||
|
@ -24,7 +24,8 @@ import {
|
|||||||
Property,
|
Property,
|
||||||
DecoratorFlags,
|
DecoratorFlags,
|
||||||
FieldPrototype,
|
FieldPrototype,
|
||||||
Field
|
Field,
|
||||||
|
Global
|
||||||
} from "./program";
|
} from "./program";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -358,6 +359,18 @@ export class Resolver extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resolves a lazily compiled global, i.e. a static class field. */
|
||||||
|
ensureResolvedLazyGlobal(global: Global, reportMode: ReportMode = ReportMode.REPORT): bool {
|
||||||
|
if (global.is(CommonFlags.RESOLVED)) return true;
|
||||||
|
var resolveType = assert(global.declaration).type;
|
||||||
|
if (!resolveType) return false;
|
||||||
|
var resolvedType = this.resolveType(resolveType, null, reportMode);
|
||||||
|
if (!resolvedType) return false;
|
||||||
|
global.type = resolvedType;
|
||||||
|
global.set(CommonFlags.RESOLVED);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** Resolves a property access to the element it refers to. */
|
/** Resolves a property access to the element it refers to. */
|
||||||
resolvePropertyAccess(
|
resolvePropertyAccess(
|
||||||
propertyAccess: PropertyAccessExpression,
|
propertyAccess: PropertyAccessExpression,
|
||||||
@ -374,7 +387,7 @@ export class Resolver extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// Resolve variable-likes to the class type they reference first
|
// Resolve variable-likes to the class type they reference first
|
||||||
switch (target.kind) {
|
switch (target.kind) {
|
||||||
case ElementKind.GLOBAL:
|
case ElementKind.GLOBAL: if (!this.ensureResolvedLazyGlobal(<Global>target, reportMode)) return null;
|
||||||
case ElementKind.LOCAL:
|
case ElementKind.LOCAL:
|
||||||
case ElementKind.FIELD: {
|
case ElementKind.FIELD: {
|
||||||
let type = (<VariableLikeElement>target).type;
|
let type = (<VariableLikeElement>target).type;
|
||||||
@ -494,7 +507,7 @@ export class Resolver extends DiagnosticEmitter {
|
|||||||
var target = this.resolveExpression(targetExpression, contextualFunction, reportMode);
|
var target = this.resolveExpression(targetExpression, contextualFunction, reportMode);
|
||||||
if (!target) return null;
|
if (!target) return null;
|
||||||
switch (target.kind) {
|
switch (target.kind) {
|
||||||
case ElementKind.GLOBAL:
|
case ElementKind.GLOBAL: if (!this.ensureResolvedLazyGlobal(<Global>target, reportMode)) return null;
|
||||||
case ElementKind.LOCAL:
|
case ElementKind.LOCAL:
|
||||||
case ElementKind.FIELD: {
|
case ElementKind.FIELD: {
|
||||||
let type = (<VariableLikeElement>target).type;
|
let type = (<VariableLikeElement>target).type;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user