// Copyright (c) Huawei Technologies Co., Ltd. 2025. 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.
// The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.
// This is actually a package format
namespace PackageFormat;
// Module
file_identifier "CJOF";
// We expect the loader to redo the symbol table
// but not type inference / check within a loaded module
// Using 'uint32' as type of 'SemaTy/Decl/Expr' 's table index.
// 0 is invalid index, valid index start from 1, which is the offset of table plus 1.
// Because of the size of AST node and 'Ty', length of uint32 is enough that oom will occurred before out-of-range.
enum DeclKind : uint16 {
InvalidDecl,
ClassDecl,
InterfaceDecl,
FuncDecl,
PropDecl,
VarDecl,
VarWithPatternDecl,
FuncParam,
StructDecl,
EnumDecl,
ExtendDecl,
TypeAliasDecl,
GenericParamDecl,
BuiltInDecl,
}
// Position member's max length same as 'struct Position''s definition.
struct Position {
file:uint32;
pkgId:uint32; // Package's index that file beglongs to. 0 indicates current package
line:int32;
column:int32;
ignore:bool;
}
table FullId {
pkgId:int32; // package that the decl belongs to
decl:string; // exportId of refed node in other package
index:uint32; // index of referenced decl in same package
}
table Constraint {
begin:Position;
end:Position;
type:uint32; // type of corresponding typeParameter
uppers:[uint32]; // UpperBounds
}
table Generic{
typeParameters:[uint32]; // GenericParamDecls
constraints:[Constraint];
}
table FuncParamList {
params:[uint32];
desugars:[uint32];
}
table FuncBody {
paramLists:[FuncParamList];
retType:uint32;
body:uint32; // index of body expr
always:bool;
captureKind:uint8;
}
struct DeclHash {
instVar:uint64;
virt:uint64;
sig:uint64;
srcUse:uint64;
bodyHash:uint64;
}
union ConstValue {
Int8Value,
UInt8Value,
Int16Value,
UInt16Value,
Int32Value,
UInt32Value,
Int64Value,
UInt64Value,
Float32Value,
Float64Value,
ArrayValue,
StringValue:string,
CompositeValue:CompositeValueIndex,
}
struct Int8Value { val:int8; }
struct UInt8Value { val:uint8; }
struct Int16Value { val:int16; } // alse represents Float16
struct UInt16Value { val:uint16; }
struct Int32Value { val:int32; }
struct UInt32Value { val:uint32; }
struct Int64Value { val:int64; }
struct UInt64Value { val:uint64; }
struct Float32Value { val:float32; }
struct Float64Value { val:float64; }
table ArrayValue { val:[ConstValue]; }
struct CompositeValueIndex { idx:uint32; }
table MemberValue {
field:string;
type:uint32;
value:ConstValue;
}
table CompositeValue { // represents class, struct, tuple, enum
type:uint32;
fields:[MemberValue];
}
table AutoDiffInfo {
isDiff:bool;
isAdj:bool;
primal:string;
excepts:[string];
includes:[string];
stage:uint64;
}
table ClassInfo {
inheritedTypes:[uint32];
body:[uint32];
adInfo:AutoDiffInfo;
isAnno:bool = false; // indicates if current class is custom annotation
annoTargets:uint8; // available if current class is custom annotation
runtimeVisible:bool;
annoTargets2:uint8;
}
table InterfaceInfo {
inheritedTypes:[uint32];
body:[uint32];
}
table StructInfo {
inheritedTypes:[uint32];
body:[uint32];
adInfo:AutoDiffInfo;
}
table EnumInfo {
inheritedTypes:[uint32];
body:[uint32];
adInfo:AutoDiffInfo;
hasArguments:bool;
nonExhaustive:bool;
ellipsisPos:Position;
}
table ExtendInfo {
inheritedTypes:[uint32];
body:[uint32];
}
table VarInfo {
isVar:bool;
isConst:bool;
isMemberParam:bool;
initializer:uint32; // Index of expression
value:ConstValue; // Has value if it is constant
}
table VarWithPatternInfo {
isVar:bool;
isConst:bool;
irrefutablePattern:Pattern; // Only existed in expression child node.
initializer:uint32; // Index of expression
}
enum OverflowPolicy : uint8 {
NA,
Checked,
Wrapping,
Throwing,
Saturating,
}
enum OperatorKind : uint8 {
NA,
// Overloadable
Index, // []
Call, // ()
Not, // !
Power, // **
Multiply, // *
Divide, // /
Remainder, // %
Add, // +
Subtract, // -
BitLeftShift, // <<
BitRightShift, // >>
LT, // <
LE, // <=
GT, // >
GE, // >=
Equal, // ==
NotEqual, // !=
BitAnd, // &
BitXor, // ^
BitOr, // |
// Others
PostInc, // ++
PostDec, // --
Is, // is
As, // as
LogicAnd, // &&
LogicOr, // ||
Coalescing, // ??
Pipeline, // |>
Composition, // ~>
Assign, // =
PowerAssign, // **=
MultiplyAssign, // *=
DivideAssign, // /=
RemainderAssign, // %=
AddAssign, // +=
SubtractAssign, // -=
LeftShiftAssign, // <<=
RightShiftAssign, // >>=
BitAndAssign, // &=
BitXorAssign, // ^=
BitOrAssign, // |=
LogicAndAssign, // &&=
LogicOrAssign, // ||=
}
table FuncInfo {
funcBody:FuncBody;
overflowPolicy:OverflowPolicy;
op:OperatorKind = NA;
adInfo:AutoDiffInfo;
isConst:bool;
isInline:bool;
isFastNative:bool;
}
table ParamInfo {
isNamedParam:bool;
isMemberParam:bool;
defaultVal:uint32; // Index of expression
}
table PropInfo {
isConst:bool;
isMutable:bool;
setters:[uint32];
getters:[uint32];
}
enum BuiltInType : uint8 {
Array,
VArray,
CPointer,
CString,
CFunc,
}
table BuiltInInfo {
builtInType:BuiltInType;
}
table AliasInfo {
aliasedTy:uint32; // Index of semantic type
}
union DeclInfo {
ClassInfo,
InterfaceInfo,
StructInfo,
EnumInfo,
ExtendInfo,
PropInfo,
VarInfo,
VarWithPatternInfo,
ParamInfo,
FuncInfo,
BuiltInInfo,
AliasInfo,
}
table Decl {
kind:DeclKind = InvalidDecl;
isTopLevel:bool = false; // whether the decl is toplevel
fullPkgName:string;
genericDecl:FullId;
generic:Generic;
begin:Position;
end:Position;
identifier:string;
identifierPos:Position;
attributes:[uint64];
annotations:[Anno];
// Semantic & CodeGen info
type: uint32;
mangledName: string; // mangledName for CodeGen
exportId: string; // exportId for import
// info used in ast diff
mangledBeforeSema:string;
hash:DeclHash;
// Specific information for each specific kind of declaration
info:DeclInfo;
}
enum AnnoKind : uint16 {
Deprecated,
TestRegistration,
Frozen,
Custom
}
// Current annotation representation is a balance between needs of @Deprecated
// and potential generalization for other annotations
table Anno { // Short name "Anno" because of the clash with "Annotation" from "PackageFormat.fbs"
kind:AnnoKind;
identifier:string;
args:[AnnoArg];
}
table AnnoArg {
name:string;
expr:uint32; // index of Expr (LitConstExpr)
}
enum ExprKind : uint16 {
InvalidExpr,
WildcardExpr,
PrimitiveTypeExpr,
ReturnExpr,
JumpExpr,
MemberAccess,
RefExpr,
CallExpr,
UnaryExpr,
IncOrDecExpr,
LitConstExpr,
BinaryExpr,
SubscriptExpr,
AssignExpr,
ArrayExpr,
PointerExpr,
TypeConvExpr,
ThrowExpr,
SpawnExpr,
ArrayLit,
TupleLit,
MatchExpr,
LetPatternDestructor,
IfExpr,
TryExpr,
WhileExpr,
DoWhileExpr,
LambdaExpr,
Block,
MatchCase,
MatchCaseOther,
AdjointExpr,
GradExpr,
ValWithGradExpr,
VJPExpr,
ForInExpr,
IfAvailableExpr,
PerformExpr,
ResumeExpr,
}
enum CallKind : uint8 {
NA,
CallDeclaredFunction,
CallObjectCreation,
CallStructCreation,
CallSuperFunction,
CallVariadicFunction,
CallFunctionPtr,
CallAnnotation,
CallBuiltinFunction,
CallIntrinsicFunction,
}
enum LitConstKind : uint8 {
Integer,
RuneByte,
Float,
Rune,
String,
JString,
Bool,
Unit,
}
enum StringKind : uint8 {
Normal,
JString,
MultiLine,
MultiLineRaw,
}
enum ForInKind : uint8 {
NA,
Range,
String,
Iterator,
}
union ExprInfo {
CallInfo,
UnaryInfo,
BinaryInfo,
IncOrDecInfo,
LitConstInfo,
ReferenceInfo,
LambdaInfo,
AssignInfo,
ArrayInfo,
JumpInfo,
FuncArgInfo,
SubscriptInfo,
MatchInfo,
BlockInfo,
TryInfo,
LetPatternDestructorInfo,
ForInInfo,
MatchCaseInfo,
SpawnInfo,
}
table CallInfo {
hasSideEffect:bool;
callKind:CallKind = NA;
}
table UnaryInfo {
op:OperatorKind;
}
table BinaryInfo {
op:OperatorKind;
}
table IncOrDecInfo {
op:OperatorKind;
}
table LitConstInfo {
strValue:string;
constKind:LitConstKind;
strKind:StringKind;
}
table ReferenceInfo {
// For RefExpr/MemberAccess
reference:string; // also for LitConstExpr string value
target:FullId;
instTys:[uint32]; // Instantiated type index vectors.
matchedParentTy:uint32; // For instantiation re-arrange.
}
table LambdaInfo {
funcBody:FuncBody (required); // LambdaExpr
supportMock:bool;
}
table AssignInfo {
isCompound:bool;
op:OperatorKind;
}
table ArrayInfo {
initFunc:FullId;
isValueArray:bool;
}
table JumpInfo {
isBreak:bool;
}
table FuncArgInfo {
withInout:bool;
isDefaultVal:bool;
}
table SubscriptInfo {
isTupleAccess:bool;
}
table MatchInfo {
matchMode:bool;
}
table BlockInfo {
isExpr:[bool];
}
table TryInfo {
resources:[FullId]; // for try-with-resource
patterns:[Pattern];
}
table LetPatternDestructorInfo {
patterns:[Pattern];
}
table ForInInfo {
pattern:Pattern;
forInKind:ForInKind = NA;
}
table MatchCaseInfo {
patterns:[Pattern];
}
table SpawnInfo {
future:FullId;
}
table Expr {
kind:ExprKind = InvalidExpr;
begin:Position;
end:Position;
mapExpr:uint32; // index of expr to deal with side effect.
operands:[uint32]; // index of sub expressions
type:uint32;
overflowPolicy:OverflowPolicy;
info:ExprInfo;
}
enum PatternKind:int8 {
InvalidPattern,
ConstPattern,
WildcardPattern,
VarPattern,
TuplePattern,
TypePattern,
EnumPattern,
ExceptTypePattern,
CommandTypePattern,
}
table Pattern {
kind:PatternKind = InvalidPattern;
begin:Position;
end:Position;
patterns:[Pattern];
types:[uint32]; // SemaTy indexes.
exprs:[uint32];
values:[ConstValue];
matchBeforeRuntime:bool;
needRuntimeTypeCheck:bool;
}
// For compatibility any new type kind MUST only be added at last.
enum TypeKind : uint16 {
Invalid, // invalid
// primitive type
Unit, // unit
// integer
Int8,
Int16,
Int32,
Int64,
IntNative,
// unsigned integer
UInt8,
UInt16,
UInt32,
UInt64,
UIntNative,
// float
Float16,
Float32,
Float64,
Rune, // char
Nothing,
Bool, // bool
// composite type
Tuple, // Tuple
Enum, // enum
Func, // function
Struct, // struct
// reference type
Array, // Array
VArray, // VArray
CPointer,
CString,
Class,
Interface,
Type, // typealias
Generic, // genericTy
}
union SemaTyInfo {
FuncTyInfo,
CompositeTyInfo,
GenericTyInfo,
ArrayTyInfo,
}
table FuncTyInfo {
retType:uint32; // Func return type
isC:bool; // CFunc or @C func type.
hasVariableLenArg:bool;
}
table CompositeTyInfo {
declPtr:FullId;
isThisTy:bool=false;
}
table GenericTyInfo {
declPtr:FullId;
upperBounds:[uint32];
}
table ArrayTyInfo {
dimsOrSize:int64;
}
table SemaTy {
kind:TypeKind=Unit;
// TypeArguments, also for funcTy's paramTypes
typeArgs:[uint32];
info:SemaTyInfo;
}
enum AccessModifier : uint8 {
Private,
Internal,
Protected,
Public,
}
table ImportSpec {
begin:Position;
end:Position;
prefixPaths:[string];
identifier:string;
asIdentifier:string;
reExport:AccessModifier = Private;
}
table Imports {
importSpecs:[ImportSpec];
}
enum PackageKind : uint8 {
Normal, // normal package.
Macro, // macro package.
Foreign, // foreign language package.
Mock, // package with mocking support.
}
enum AccessLevel : uint8 {
Public,
Protected,
Internal,
}
struct CjoVersion {
major_num:uint8;
minor_num:uint8;
patch_num:uint8;
}
// all SemaTys, decls are saved here, and indexed by other nodes.
table Package {
version:string; // cjc version.
cjoVersion:CjoVersion; // cjo format version.
fullPkgName:string; // full package name.
pkgDepInfo:string; // package dependency info.
imports:[string]; // all imported packages.
allFiles:[string]; // all files in package.
allFileImports:[Imports]; // all file imports in package.
allTypes:[SemaTy]; // all saved SemaTys.
allDecls:[Decl]; // all saved decls.
allExprs:[Expr]; // all saved expressions.
allValues:[CompositeValue];// all saved constant composite values.
kind:PackageKind = Normal; // package kind.
access:AccessLevel = Public;
moduleName:string;
}
root_type Package;