/*
* Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
package stdx.chir
import std.deriving.*
const ATTR_SIZE: UInt64 = 64
@Derive[Equatable]
internal enum Attribute <: ToString {
AttrBegin |
Static | ///< Mark whether a member is a static one.
Public | ///< Mark whether a member is a public one.
Private | ///< Mark whether a member is a private one.
Protected | ///< Mark whether a member is a protected one.
Abstract | ///< Mark whether a function is an abstract one.
Virtual | ///< Mark whether a declaration is in fact open (even if the user does not use `open` keyword).
Override | ///< Mark whether a declaration in fact overrides the inherited one
///(even if the user does not use `override` keyword).
Redef | ///< Mark whether a declaration in fact overrides the inherited one (even if the user does not use
///< `redef` keyword).
Sealed | ///< Mark whether a declaration is a sealed one.
Foreign | ///< Mark whether a declaration is a foreign one.
Mut | ///< Mark whether a declaration is a mutable one.
Final | ///< Mark a Func override a parent class's func, and this func self does not have VIRTUAL Attribute.
Operator | ///< Mark whether a declaration is a operator one.
ReadOnly | ///< 'let x = xxx', 'x' enable READONLY attribute
Const | ///< correspond `const` keyword in Cangjie source code.
Imported | ///< Mark whether variable、func、enum、struct、class is imported from other package.
GenericInstantiated | ///< Mark whether a `GlobalVar/Func/Type` is instantiated.
NoDebugInfo | ///< Mark a `Value` doesn't contain debug info, like line/column number.
Generic | ///< Mark a declaration is generic
Internal | ///< GlobalVar/Func/Enum/Class/Struct/Interface is visible in current and sub package.
CompilerAdd | ///< Mark a `Value` is added by compiler, like "copied default func from interface".
// compiler attribute
NoReflectInfo | ///< Mark a `Value` is't used by `reflect` feature.
NoInline | ///< Mark a Func can't be inlined.
NonRecompile | ///< only used in `ImportedValue` in incremental compilation, indicate this ImportedValue is
///< converted from a decl in current package that is not recompiled.
Unreachable | ///< Mark a Block is unreachable.
NoSideEffect | ///< Mark a Func does't have side effect.
Common | ///< Mark whether it's common declaration.
Platform | ///< Mark whether it's platform declaration.
SkipAnalysis | ///< Mark node that is not used for analysis.
///< e.g. Node can be skiped if it has no body when creating 'common part'
Deserialized | ///< Node deserialized from .chir file
Initializer | ///< Mark nodes that related to initialization process.
///< Marked functions are package initializer, file initializers, variable initializer or so.
///< On the block is used to search for it among other blocks of the function.
Unsafe | ///< Mark whether a function that was marked as `unsafe`
// Native FFI attributes
JavaMirror | ///< Mark whether it's @JavaMirror declaration (binding for a java type).
JavaImpl | ///< Mark whether it's @JavaImpl declaration.
ObjCMirror | ///< Mark whether it's @ObjCMirror declaration (binding for an Objective-C type).
HasInitedField | ///< Mark whether a node is a special flag, which marks the class instance as initialized.
JavaHasDefault | ///< Mark whether JAVA_MIRROR interface has default method.
PreviouslyDeserialized | ///< Mark that deserialization occurs not in the newly created node, but in an existing one.
PluginAdded | ///< Mark that the declaration is added by chir plugin.
AttrEnd
/**
* Converts this attribute flag to its stable keyword string used in CHIR text output.
* @return The attribute name string, or "UNKNOWN" for sentinel values.
*/
public func toString(): String {
match (this) {
case Static => "static"
case Public => "public"
case Private => "private"
case Protected => "protected"
case Abstract => "abstract"
case Virtual => "virtual"
case Override => "override"
case Redef => "redef"
case Sealed => "sealed"
case Foreign => "foreign"
case Mut => "mut"
case Operator => "operator"
case Const => "compileTimeVal"
case ReadOnly => "readOnly"
case Imported => "imported"
case NonRecompile => "nonRecompile"
case GenericInstantiated => "generic_instantiated"
case Internal => "internal"
case CompilerAdd => "compilerAdd"
case Generic => "generic"
case NoReflectInfo => "noReflectInfo"
case NoInline => "noInline"
case NoDebugInfo => "noDebugInfo"
case Unreachable => "unreachable"
case NoSideEffect => "noSideEffect"
case Final => "final"
case Common => "common"
case Platform => "platform"
case SkipAnalysis => "skip_analysis"
case Deserialized => "deserialized"
case Initializer => "initializer"
case Unsafe => "unsafe"
case JavaMirror => "javaMirror"
case JavaImpl => "javaImpl"
case ObjCMirror => "objCMirror"
case HasInitedField => "hasInitedField"
case JavaHasDefault => "javaHasDefault"
case PreviouslyDeserialized => "previouslyDeserialized"
case PluginAdded => "pluginAdded"
case AttrBegin | AttrEnd => "UNKNOWN"
}
}
internal func getNextAttribute(): Attribute {
match (this) {
case AttrBegin => Static
case Static => Public
case Public => Private
case Private => Protected
case Protected => Abstract
case Abstract => Virtual
case Virtual => Override
case Override => Redef
case Redef => Sealed
case Sealed => Foreign
case Foreign => Mut
case Mut => Final
case Final => Operator
case Operator => ReadOnly
case ReadOnly => Const
case Const => Imported
case Imported => GenericInstantiated
case GenericInstantiated => NoDebugInfo
case NoDebugInfo => Generic
case Generic => Internal
case Internal => CompilerAdd
case CompilerAdd => NoReflectInfo
case NoReflectInfo => NoInline
case NoInline => NonRecompile
case NonRecompile => Unreachable
case Unreachable => NoSideEffect
case NoSideEffect => Common
case Common => Platform
case Platform => SkipAnalysis
case SkipAnalysis => Deserialized
case Deserialized => Initializer
case Initializer => Unsafe
case Unsafe => JavaMirror
case JavaMirror => JavaImpl
case JavaImpl => ObjCMirror
case ObjCMirror => HasInitedField
case HasInitedField => JavaHasDefault
case JavaHasDefault => PreviouslyDeserialized
case PreviouslyDeserialized => PluginAdded
case PluginAdded => AttrEnd
case AttrEnd => AttrEnd
}
}
internal func toUInt64(): UInt64 {
match (this) {
case AttrBegin => 0 // just a placeholder
case Static => 0
case Public => 1
case Private => 2
case Protected => 3
case Abstract => 4
case Virtual => 5
case Override => 6
case Redef => 7
case Sealed => 8
case Foreign => 9
case Mut => 10
case Final => 11
case Operator => 12
case ReadOnly => 13
case Const => 14
case Imported => 15
case GenericInstantiated => 16
case NoDebugInfo => 17
case Generic => 18
case Internal => 19
case CompilerAdd => 20
case NoReflectInfo => 21
case NoInline => 22
case NonRecompile => 23
case Unreachable => 24
case NoSideEffect => 25
case Common => 26
case Platform => 27
case SkipAnalysis => 28
case Deserialized => 29
case Initializer => 30
case Unsafe => 31
case JavaMirror => 32
case JavaImpl => 33
case ObjCMirror => 34
case HasInitedField => 35
case JavaHasDefault => 36
case PreviouslyDeserialized => 37
case PluginAdded => 38
case AttrEnd => ATTR_SIZE // Invalid, return size to indicate error
}
}
}
/**
* AttributeInfo class for managing attribute flags
* Uses a bitset-like approach with UInt64 to store up to 64 attributes
*/
internal struct AttributeInfo <: ToString {
internal var _attributesInfo: UInt64 = 0
/**
* Builds a bracketed list of all set attribute names (e.g. "[public][static]").
* @return Concatenated attribute tags for debugging or pretty-printing.
*/
public func toString(): String {
let result = StringBuilder()
// Iterate through all attributes and build string
var current: Attribute = Attribute.AttrBegin.getNextAttribute()
while (true) {
if (testAttr(current)) {
result.append("[")
result.append(current.toString())
result.append("]")
}
// Move to next attribute (simplified iteration)
current = current.getNextAttribute()
if (current == Attribute.AttrEnd) {
break
}
}
return result.toString()
}
internal init() {
this._attributesInfo = 0
}
internal init(attrs: UInt64) {
this._attributesInfo = attrs
}
internal func clone(): AttributeInfo {
return AttributeInfo(_attributesInfo)
}
/**
* Set an attribute to enabled or disabled
*/
internal mut func setAttr(attr: Attribute, enable: Bool): Unit {
if (enable) {
let bitIndex = attr.toUInt64()
if (bitIndex < ATTR_SIZE) {
_attributesInfo |= UInt64(1) << bitIndex
} else {
throw CHIRException("set failed, Attribute index out of range")
}
} else {
let bitIndex = attr.toUInt64()
if (bitIndex < ATTR_SIZE) {
_attributesInfo &= !(UInt64(1) << bitIndex)
} else {
throw CHIRException("set failed, Attribute index out of range")
}
}
}
/**
* Test whether an attribute is set
*/
internal func testAttr(attr: Attribute): Bool {
let bitIndex = attr.toUInt64()
if (bitIndex >= ATTR_SIZE) {
return false
}
return (_attributesInfo & (UInt64(1) << bitIndex)) != 0
}
internal mut func appendAttrs(info : AttributeInfo): Unit {
_attributesInfo |= info._attributesInfo
}
internal func getRawAttrs(): UInt64 {
return _attributesInfo
}
internal mut func setInternal(): Unit {
setAttr(Attribute.Internal, true)
setAttr(Attribute.Public, false)
setAttr(Attribute.Private, false)
setAttr(Attribute.Protected, false)
}
internal mut func setPublic(): Unit {
setAttr(Attribute.Public, true)
setAttr(Attribute.Private, false)
setAttr(Attribute.Protected, false)
setAttr(Attribute.Internal, false)
}
internal mut func setPrivate(): Unit {
setAttr(Attribute.Private, true)
setAttr(Attribute.Public, false)
setAttr(Attribute.Protected, false)
setAttr(Attribute.Internal, false)
}
internal mut func setProtected(): Unit {
setAttr(Attribute.Protected, true)
setAttr(Attribute.Public, false)
setAttr(Attribute.Private, false)
setAttr(Attribute.Internal, false)
}
internal func isImported(): Bool {
return testAttr(Attribute.Imported)
}
}