Skip to content

XGo AST Design: Static Members

xushiwei edited this page Jun 22, 2026 · 5 revisions

This document describes the AST representation of static constants, static variables, and static methods/functions in XGo, covering both normal XGo files and classfiles.


Overview

XGo introduces static members — static constants, static variables, and static methods — as type-scoped declarations. The AST must distinguish these from global declarations and instance members. Two existing node types carry this information:

  • FuncDecl — for functions and methods (static or not)
  • ValueSpec — for const and var declarations (static or not)

FuncDecl: Static Method Representation

type FuncDecl struct {
    Doc      *CommentGroup // associated documentation; or nil
    Recv     *FieldList    // receiver (methods); or nil (functions)
    Name     *Ident        // function/method name
    Type     *FuncType     // function signature: parameters, results, and position of "func" keyword
    Body     *BlockStmt    // function body; or nil for external (non-Go) function
    Operator bool          // is operator or not
    Shadow   bool          // is a shadow entry
    IsClass  bool          // recv set by class
    Static   bool          // recv is static (class method)
}

Key Fields for Static Methods

  • Static bool: set to true when the declaration is a static method (either T.Method or .Method form).
  • Recv *FieldList: carries the receiver type T for the T.Method form; non-nil but with len(Recv.List) == 0 for the .Method shorthand form in classfiles.
  • Name *Ident: always holds the bare method name (without the T. or . prefix).

Field Values by Declaration Form

Context Syntax Static Recv Name
Normal XGo func name(...) false nil "name"
Normal XGo func T.Method(...) true FieldList{List: [T]} "Method"
Classfile func name(...) false non-nil, set by class (IsClass=true) "name"
Classfile func T.Method(...) true FieldList{List: [T]} "Method"
Classfile func .Method(...) true FieldList{List: nil} (empty list) "Method"

Notes

  • For normal XGo, a bare func name(...) is a global function: Static=false, Recv=nil.
  • For classfiles, a bare func name(...) is an instance method: Static=false, Recv is non-nil and set by the class mechanism (IsClass=true).
  • func T.Method(...) is unambiguously a static method in both contexts. Recv holds T as a regular field entry.
  • func .Method(...) is the classfile shorthand for a static method on the owning class. Recv is non-nil but len(Recv.List) == 0, indicating "static on the implicit class type."

ValueSpec: Static Constant and Variable Representation

type ValueSpec struct {
    Doc       *CommentGroup // associated documentation; or nil
    Names     []*Ident      // value names (len >= 1)
    Type      Expr          // value type; or nil
    Tag       *BasicLit     // classfile field tag; or nil
    Values    []Expr        // initial values; or nil
    Comment   *CommentGroup // line comments; or nil
    HasStatic bool          // true if any name is in ".name" or "T.name" form
}

Key Fields for Static Constants and Variables

  • HasStatic bool: set to true when at least one name in Names uses the T.name or .name static form. When false, all names are bare identifiers (global or instance members).
  • Names []*Ident: each Ident in the slice carries its parsed name. For a static name in T.name form the identifier encodes the qualifier; for .name form the identifier encodes the shorthand.

Note: A single ValueSpec may mix static and non-static names (e.g., const T.A, B = 1, 2). HasStatic signals that at least one name requires special handling; consumers must inspect each Ident individually to determine which names are static.

Field Values by Declaration Form

const Declarations

Context Syntax HasStatic Names entries Semantics
Normal XGo const name = ... false ["name"] Global constant
Normal XGo const T.name = ... true ["T.name"] Static constant
Classfile const name = ... false ["name"] Global constant
Classfile const T.name = ... true ["T.name"] Static constant
Classfile const .name = ... true [".name"] Static constant

var Declarations

Context Syntax HasStatic Names entries Semantics
Normal XGo var name V = ... false ["name"] Global variable
Normal XGo var T.name V = ... true ["T.name"] Static variable
Classfile var name V = ... false ["name"] Class (instance) member †
Classfile var T.name V = ... true ["T.name"] Static variable
Classfile var .name V = ... true [".name"] Static variable

† In classfiles, bare var name declares a class (instance) member. At most one top-level var block with bare names is permitted per classfile; a second such block is a compile-time error.


Summary: Static vs. Non-Static at a Glance

Kind Context Form Static / HasStatic Semantics
func Normal XGo name Static=false Global function
func Normal XGo T.Method Static=true Static method
func Classfile name Static=false Instance method
func Classfile T.Method Static=true Static method
func Classfile .Method Static=true Static method (shorthand)
const Normal XGo name HasStatic=false Global constant
const Normal XGo T.name HasStatic=true Static constant
const Classfile name HasStatic=false Global constant
const Classfile T.name HasStatic=true Static constant
const Classfile .name HasStatic=true Static constant (shorthand)
var Normal XGo name HasStatic=false Global variable
var Normal XGo T.name HasStatic=true Static variable
var Classfile name HasStatic=false Class (instance) member
var Classfile T.name HasStatic=true Static variable
var Classfile .name HasStatic=true Static variable (shorthand)

Disambiguation Rules for Consumers

When walking the AST, consumers can classify any declaration using the following rules:

For FuncDecl

if Static == false && Recv == nil         → global function (normal XGo)
if Static == false && Recv != nil         → instance method (classfile, IsClass=true)
if Static == true  && len(Recv.List) > 0  → static method with explicit type T
if Static == true  && len(Recv.List) == 0 → static method via classfile shorthand (.Method)

For ValueSpec (in a const declaration)

if HasStatic == false → all names are global constants (both contexts)
if HasStatic == true  → at least one name is a static constant;
                        inspect each Ident for "T.name" or ".name" form

For ValueSpec (in a var declaration)

if HasStatic == false, in normal XGo  → all names are global variables
if HasStatic == false, in classfile   → all names are class (instance) members
if HasStatic == true                  → at least one name is a static variable;
                                        inspect each Ident for "T.name" or ".name" form

Constraints and Compile-Time Errors

  • Classfile var block limit: A classfile may contain at most one top-level var block whose names are bare (non-static) identifiers. Parsing a second such block is a compile-time error.
  • type declarations: type declarations are always global in both contexts. There is no T.Name or .Name syntax for types, and no static flag is needed on type nodes.
  • Mixed ValueSpec: A single ValueSpec may contain both static and non-static names. HasStatic=true does not imply that all names are static — only that at least one is. Semantic analysis must inspect individual Ident nodes.

Clone this wiki locally