mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 15:12:12 +00:00
Properly resolve enum value siblings
This commit is contained in:
parent
29935948f2
commit
b548b5c81f
@ -187,6 +187,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
/** Current function in compilation. */
|
/** Current function in compilation. */
|
||||||
currentFunction: Function;
|
currentFunction: Function;
|
||||||
|
/** Current enum in compilation. */
|
||||||
|
currentEnum: Enum | null = null;
|
||||||
/** Current type in compilation. */
|
/** Current type in compilation. */
|
||||||
currentType: Type = Type.void;
|
currentType: Type = Type.void;
|
||||||
|
|
||||||
@ -214,6 +216,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// set up start function
|
// set up start function
|
||||||
var startFunctionTemplate = new FunctionPrototype(program, "start", "start", null);
|
var startFunctionTemplate = new FunctionPrototype(program, "start", "start", null);
|
||||||
var startFunctionInstance = new Function(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
|
var startFunctionInstance = new Function(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
|
||||||
|
startFunctionInstance.set(ElementFlags.START);
|
||||||
this.currentFunction = this.startFunction = startFunctionInstance;
|
this.currentFunction = this.startFunction = startFunctionInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,6 +475,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// members might reference each other, triggering another compile
|
// members might reference each other, triggering another compile
|
||||||
element.set(ElementFlags.COMPILED);
|
element.set(ElementFlags.COMPILED);
|
||||||
|
|
||||||
|
this.currentEnum = element;
|
||||||
var previousValue: EnumValue | null = null;
|
var previousValue: EnumValue | null = null;
|
||||||
if (element.members)
|
if (element.members)
|
||||||
for (var member of element.members.values()) {
|
for (var member of element.members.values()) {
|
||||||
@ -480,6 +484,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var initInStart = false;
|
var initInStart = false;
|
||||||
var val = <EnumValue>member;
|
var val = <EnumValue>member;
|
||||||
var valueDeclaration = val.declaration;
|
var valueDeclaration = val.declaration;
|
||||||
|
val.set(ElementFlags.COMPILED);
|
||||||
if (val.is(ElementFlags.INLINED)) {
|
if (val.is(ElementFlags.INLINED)) {
|
||||||
if (!element.declaration || element.declaration.isTopLevelExport)
|
if (!element.declaration || element.declaration.isTopLevelExport)
|
||||||
this.module.addGlobal(val.internalName, NativeType.I32, false, this.module.createI32(val.constantValue));
|
this.module.addGlobal(val.internalName, NativeType.I32, false, this.module.createI32(val.constantValue));
|
||||||
@ -533,6 +538,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
this.warning(DiagnosticCode.Cannot_export_a_mutable_global, valueDeclaration.range);
|
this.warning(DiagnosticCode.Cannot_export_a_mutable_global, valueDeclaration.range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.currentEnum = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2775,7 +2781,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// otherwise resolve
|
// otherwise resolve
|
||||||
var resolved = this.program.resolveIdentifier(expression, this.currentFunction); // reports
|
var resolved = this.program.resolveIdentifier(expression, this.currentFunction, this.currentEnum); // reports
|
||||||
if (!resolved)
|
if (!resolved)
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
|
|
||||||
@ -2799,6 +2805,17 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.compileInlineConstant(<Global>element, contextualType);
|
return this.compileInlineConstant(<Global>element, contextualType);
|
||||||
this.currentType = (<Global>element).type;
|
this.currentType = (<Global>element).type;
|
||||||
return this.module.createGetGlobal((<Global>element).internalName, this.currentType.toNativeType());
|
return this.module.createGetGlobal((<Global>element).internalName, this.currentType.toNativeType());
|
||||||
|
|
||||||
|
case ElementKind.ENUMVALUE: // here: if referenced from within the same enum
|
||||||
|
if (!element.is(ElementFlags.COMPILED)) {
|
||||||
|
this.error(DiagnosticCode.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums, expression.range);
|
||||||
|
this.currentType = Type.i32;
|
||||||
|
return this.module.createUnreachable();
|
||||||
|
}
|
||||||
|
this.currentType = Type.i32;
|
||||||
|
if ((<EnumValue>element).is(ElementFlags.INLINED))
|
||||||
|
return this.module.createI32((<EnumValue>element).constantValue);
|
||||||
|
return this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
||||||
}
|
}
|
||||||
this.error(DiagnosticCode.Operation_not_supported, expression.range);
|
this.error(DiagnosticCode.Operation_not_supported, expression.range);
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
|
@ -86,6 +86,7 @@ export enum DiagnosticCode {
|
|||||||
Expected_0_arguments_but_got_1 = 2554,
|
Expected_0_arguments_but_got_1 = 2554,
|
||||||
Expected_at_least_0_arguments_but_got_1 = 2555,
|
Expected_at_least_0_arguments_but_got_1 = 2555,
|
||||||
Expected_0_type_arguments_but_got_1 = 2558,
|
Expected_0_type_arguments_but_got_1 = 2558,
|
||||||
|
A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums = 2651,
|
||||||
Namespace_0_has_no_exported_member_1 = 2694,
|
Namespace_0_has_no_exported_member_1 = 2694,
|
||||||
File_0_not_found = 6054
|
File_0_not_found = 6054
|
||||||
}
|
}
|
||||||
@ -177,6 +178,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
|||||||
case 2554: return "Expected {0} arguments, but got {1}.";
|
case 2554: return "Expected {0} arguments, but got {1}.";
|
||||||
case 2555: return "Expected at least {0} arguments, but got {1}.";
|
case 2555: return "Expected at least {0} arguments, but got {1}.";
|
||||||
case 2558: return "Expected {0} type arguments, but got {1}.";
|
case 2558: return "Expected {0} type arguments, but got {1}.";
|
||||||
|
case 2651: return "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.";
|
||||||
case 2694: return "Namespace '{0}' has no exported member '{1}'.";
|
case 2694: return "Namespace '{0}' has no exported member '{1}'.";
|
||||||
case 6054: return "File '{0}' not found.";
|
case 6054: return "File '{0}' not found.";
|
||||||
default: return "";
|
default: return "";
|
||||||
|
@ -86,6 +86,7 @@
|
|||||||
"Expected {0} arguments, but got {1}.": 2554,
|
"Expected {0} arguments, but got {1}.": 2554,
|
||||||
"Expected at least {0} arguments, but got {1}.": 2555,
|
"Expected at least {0} arguments, but got {1}.": 2555,
|
||||||
"Expected {0} type arguments, but got {1}.": 2558,
|
"Expected {0} type arguments, but got {1}.": 2558,
|
||||||
|
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": 2651,
|
||||||
"Namespace '{0}' has no exported member '{1}'.": 2694,
|
"Namespace '{0}' has no exported member '{1}'.": 2694,
|
||||||
|
|
||||||
"File '{0}' not found.": 6054
|
"File '{0}' not found.": 6054
|
||||||
|
@ -992,18 +992,24 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Resolves an identifier to the element it refers to. */
|
/** Resolves an identifier to the element it refers to. */
|
||||||
resolveIdentifier(identifier: IdentifierExpression, contextualFunction: Function | null): ResolvedElement | null {
|
resolveIdentifier(identifier: IdentifierExpression, contextualFunction: Function | null, contextualEnum: Enum | null = null): ResolvedElement | null {
|
||||||
var name = identifier.name;
|
var name = identifier.name;
|
||||||
|
|
||||||
var element: Element | null;
|
var element: Element | null;
|
||||||
var namespace: Element | null;
|
var namespace: Element | null;
|
||||||
|
var reference: Element | null;
|
||||||
|
|
||||||
if (contextualFunction) {
|
// check siblings
|
||||||
|
if (contextualEnum) {
|
||||||
|
|
||||||
|
if (contextualEnum.members && (element = contextualEnum.members.get(name)) && element.kind == ElementKind.ENUMVALUE)
|
||||||
|
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(element);
|
||||||
|
|
||||||
|
} else if (contextualFunction) {
|
||||||
|
|
||||||
// check locals
|
// check locals
|
||||||
var local = contextualFunction.flow.getScopedLocal(name);
|
if (element = contextualFunction.flow.getScopedLocal(name))
|
||||||
if (local)
|
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(element);
|
||||||
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(local);
|
|
||||||
|
|
||||||
// search contextual parent namespaces if applicable
|
// search contextual parent namespaces if applicable
|
||||||
if (namespace = contextualFunction.prototype.namespace) {
|
if (namespace = contextualFunction.prototype.namespace) {
|
||||||
@ -1259,7 +1265,9 @@ export enum ElementFlags {
|
|||||||
/** Has already inherited base class static members. */
|
/** Has already inherited base class static members. */
|
||||||
HAS_STATIC_BASE_MEMBERS = 1 << 18,
|
HAS_STATIC_BASE_MEMBERS = 1 << 18,
|
||||||
/** Is scoped. */
|
/** Is scoped. */
|
||||||
SCOPED = 1 << 19
|
SCOPED = 1 << 19,
|
||||||
|
/** Is the start function. */
|
||||||
|
START = 1 << 20
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Base class of all program elements. */
|
/** Base class of all program elements. */
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
(global $enum/Mixed.FOUR i32 (i32.const 4))
|
(global $enum/Mixed.FOUR i32 (i32.const 4))
|
||||||
(global $enum/NonConstant.ZERO (mut i32) (i32.const 0))
|
(global $enum/NonConstant.ZERO (mut i32) (i32.const 0))
|
||||||
(global $enum/NonConstant.ONE (mut i32) (i32.const 0))
|
(global $enum/NonConstant.ONE (mut i32) (i32.const 0))
|
||||||
|
(global $enum/SelfReference.ZERO i32 (i32.const 0))
|
||||||
|
(global $enum/SelfReference.ONE i32 (i32.const 1))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||||
(export "enum/Implicit.ONE" (global $enum/Implicit.ONE))
|
(export "enum/Implicit.ONE" (global $enum/Implicit.ONE))
|
||||||
@ -27,6 +29,8 @@
|
|||||||
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
||||||
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
||||||
(export "enum/Mixed.FOUR" (global $enum/Mixed.FOUR))
|
(export "enum/Mixed.FOUR" (global $enum/Mixed.FOUR))
|
||||||
|
(export "enum/SelfReference.ZERO" (global $enum/SelfReference.ZERO))
|
||||||
|
(export "enum/SelfReference.ONE" (global $enum/SelfReference.ONE))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $start (; 0 ;) (type $v)
|
(func $start (; 0 ;) (type $v)
|
||||||
|
@ -27,3 +27,8 @@ export enum NonConstant {
|
|||||||
ZERO = getZero(), // cannot export a mutable global
|
ZERO = getZero(), // cannot export a mutable global
|
||||||
ONE // cannot export a mutable global (tsc doesn't allow this)
|
ONE // cannot export a mutable global (tsc doesn't allow this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SelfReference {
|
||||||
|
ZERO,
|
||||||
|
ONE = ZERO + 1
|
||||||
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
(global $enum/Mixed.FOUR i32 (i32.const 4))
|
(global $enum/Mixed.FOUR i32 (i32.const 4))
|
||||||
(global $enum/NonConstant.ZERO (mut i32) (i32.const 0))
|
(global $enum/NonConstant.ZERO (mut i32) (i32.const 0))
|
||||||
(global $enum/NonConstant.ONE (mut i32) (i32.const 0))
|
(global $enum/NonConstant.ONE (mut i32) (i32.const 0))
|
||||||
|
(global $enum/SelfReference.ZERO i32 (i32.const 0))
|
||||||
|
(global $enum/SelfReference.ONE i32 (i32.const 1))
|
||||||
(global $HEAP_BASE i32 (i32.const 4))
|
(global $HEAP_BASE i32 (i32.const 4))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||||
@ -29,6 +31,8 @@
|
|||||||
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
||||||
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
||||||
(export "enum/Mixed.FOUR" (global $enum/Mixed.FOUR))
|
(export "enum/Mixed.FOUR" (global $enum/Mixed.FOUR))
|
||||||
|
(export "enum/SelfReference.ZERO" (global $enum/SelfReference.ZERO))
|
||||||
|
(export "enum/SelfReference.ONE" (global $enum/SelfReference.ONE))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $enum/getZero (; 0 ;) (type $i) (result i32)
|
(func $enum/getZero (; 0 ;) (type $i) (result i32)
|
||||||
@ -97,9 +101,11 @@
|
|||||||
ENUM: enum/Mixed
|
ENUM: enum/Mixed
|
||||||
FUNCTION_PROTOTYPE: enum/getZero
|
FUNCTION_PROTOTYPE: enum/getZero
|
||||||
ENUM: enum/NonConstant
|
ENUM: enum/NonConstant
|
||||||
|
ENUM: enum/SelfReference
|
||||||
[program.exports]
|
[program.exports]
|
||||||
ENUM: enum/Implicit
|
ENUM: enum/Implicit
|
||||||
ENUM: enum/Explicit
|
ENUM: enum/Explicit
|
||||||
ENUM: enum/Mixed
|
ENUM: enum/Mixed
|
||||||
ENUM: enum/NonConstant
|
ENUM: enum/NonConstant
|
||||||
|
ENUM: enum/SelfReference
|
||||||
;)
|
;)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user