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. */
|
||||
currentFunction: Function;
|
||||
/** Current enum in compilation. */
|
||||
currentEnum: Enum | null = null;
|
||||
/** Current type in compilation. */
|
||||
currentType: Type = Type.void;
|
||||
|
||||
@ -214,6 +216,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// set up start function
|
||||
var startFunctionTemplate = new FunctionPrototype(program, "start", "start", null);
|
||||
var startFunctionInstance = new Function(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
|
||||
startFunctionInstance.set(ElementFlags.START);
|
||||
this.currentFunction = this.startFunction = startFunctionInstance;
|
||||
}
|
||||
|
||||
@ -472,6 +475,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// members might reference each other, triggering another compile
|
||||
element.set(ElementFlags.COMPILED);
|
||||
|
||||
this.currentEnum = element;
|
||||
var previousValue: EnumValue | null = null;
|
||||
if (element.members)
|
||||
for (var member of element.members.values()) {
|
||||
@ -480,6 +484,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var initInStart = false;
|
||||
var val = <EnumValue>member;
|
||||
var valueDeclaration = val.declaration;
|
||||
val.set(ElementFlags.COMPILED);
|
||||
if (val.is(ElementFlags.INLINED)) {
|
||||
if (!element.declaration || element.declaration.isTopLevelExport)
|
||||
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.currentEnum = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2775,7 +2781,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
// otherwise resolve
|
||||
var resolved = this.program.resolveIdentifier(expression, this.currentFunction); // reports
|
||||
var resolved = this.program.resolveIdentifier(expression, this.currentFunction, this.currentEnum); // reports
|
||||
if (!resolved)
|
||||
return this.module.createUnreachable();
|
||||
|
||||
@ -2799,6 +2805,17 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.compileInlineConstant(<Global>element, contextualType);
|
||||
this.currentType = (<Global>element).type;
|
||||
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);
|
||||
return this.module.createUnreachable();
|
||||
|
@ -86,6 +86,7 @@ export enum DiagnosticCode {
|
||||
Expected_0_arguments_but_got_1 = 2554,
|
||||
Expected_at_least_0_arguments_but_got_1 = 2555,
|
||||
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,
|
||||
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 2555: return "Expected at least {0} 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 6054: return "File '{0}' not found.";
|
||||
default: return "";
|
||||
|
@ -86,6 +86,7 @@
|
||||
"Expected {0} arguments, but got {1}.": 2554,
|
||||
"Expected at least {0} arguments, but got {1}.": 2555,
|
||||
"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,
|
||||
|
||||
"File '{0}' not found.": 6054
|
||||
|
@ -992,18 +992,24 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
/** 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 element: 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
|
||||
var local = contextualFunction.flow.getScopedLocal(name);
|
||||
if (local)
|
||||
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(local);
|
||||
if (element = contextualFunction.flow.getScopedLocal(name))
|
||||
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(element);
|
||||
|
||||
// search contextual parent namespaces if applicable
|
||||
if (namespace = contextualFunction.prototype.namespace) {
|
||||
@ -1259,7 +1265,9 @@ export enum ElementFlags {
|
||||
/** Has already inherited base class static members. */
|
||||
HAS_STATIC_BASE_MEMBERS = 1 << 18,
|
||||
/** Is scoped. */
|
||||
SCOPED = 1 << 19
|
||||
SCOPED = 1 << 19,
|
||||
/** Is the start function. */
|
||||
START = 1 << 20
|
||||
}
|
||||
|
||||
/** Base class of all program elements. */
|
||||
|
@ -14,6 +14,8 @@
|
||||
(global $enum/Mixed.FOUR i32 (i32.const 4))
|
||||
(global $enum/NonConstant.ZERO (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)
|
||||
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||
(export "enum/Implicit.ONE" (global $enum/Implicit.ONE))
|
||||
@ -27,6 +29,8 @@
|
||||
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
||||
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
||||
(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))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -27,3 +27,8 @@ export enum NonConstant {
|
||||
ZERO = getZero(), // cannot export a mutable global
|
||||
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/NonConstant.ZERO (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))
|
||||
(memory $0 1)
|
||||
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||
@ -29,6 +31,8 @@
|
||||
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
||||
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
||||
(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))
|
||||
(start $start)
|
||||
(func $enum/getZero (; 0 ;) (type $i) (result i32)
|
||||
@ -97,9 +101,11 @@
|
||||
ENUM: enum/Mixed
|
||||
FUNCTION_PROTOTYPE: enum/getZero
|
||||
ENUM: enum/NonConstant
|
||||
ENUM: enum/SelfReference
|
||||
[program.exports]
|
||||
ENUM: enum/Implicit
|
||||
ENUM: enum/Explicit
|
||||
ENUM: enum/Mixed
|
||||
ENUM: enum/NonConstant
|
||||
ENUM: enum/SelfReference
|
||||
;)
|
||||
|
Loading…
x
Reference in New Issue
Block a user