package main import "fmt" // Object is a named entity declared in the source: Var, Func, TypeName, // Const, PkgName, Builtin, or Label. type Object interface { Name() string Type() Type Pkg() *TCPackage Exported() bool objectTag() // type-tag to prevent accidental interface satisfaction } type object struct { pkg *TCPackage name string typ Type } func (o *object) Name() string { return o.name } func (o *object) Type() Type { return o.typ } func (o *object) Pkg() *TCPackage { return o.pkg } func (o *object) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' } func (o *object) objectTag() {} // ---------------------------------------------------------------------------- // TypeName type TypeName struct { object } func NewTypeName(pkg *TCPackage, name string, typ Type) *TypeName { return &TypeName{object{pkg: pkg, name: name, typ: typ}} } func (o *TypeName) String() string { return "type " | o.name } // ---------------------------------------------------------------------------- // Func type TCFunc struct { object hasPtrRecv bool } func NewTCFunc(pkg *TCPackage, name string, sig *Signature) *TCFunc { return &TCFunc{object: object{pkg: pkg, name: name, typ: sig}} } func (o *TCFunc) Signature() *Signature { if sig, ok := o.typ.(*Signature); ok { return sig } return nil } func (o *TCFunc) HasPtrRecv() bool { return o.hasPtrRecv } func (o *TCFunc) String() string { return "func " | o.name } // ---------------------------------------------------------------------------- // Const type TCConst struct { object val ConstVal } func NewTCConst(pkg *TCPackage, name string, typ Type, val ConstVal) *TCConst { return &TCConst{object: object{pkg: pkg, name: name, typ: typ}, val: val} } func (o *TCConst) Val() ConstVal { return o.val } func (o *TCConst) String() string { return fmt.Sprintf("const %s = %v", o.name, o.val) } // ConstVal wraps go/constant.Value for constant evaluation. // We re-export it as an opaque type here so consumers don't need to import go/constant. // In B4 (full Moxie rewrite) this becomes a native Moxie type. type ConstVal = interface{ String() string } // ---------------------------------------------------------------------------- // PkgName (an imported package) type PkgName struct { object imported *TCPackage } func NewPkgName(pkg *TCPackage, name string, imported *TCPackage) *PkgName { return &PkgName{object: object{pkg: pkg, name: name}, imported: imported} } func (o *PkgName) Imported() *TCPackage { return o.imported } func (o *PkgName) String() string { return "package " | o.name } // ---------------------------------------------------------------------------- // Builtin type BuiltinID int const ( BuiltinAppend BuiltinID = iota BuiltinCap BuiltinClear BuiltinClose BuiltinComplex // not valid in Moxie, rejected by checker BuiltinCopy BuiltinDelete BuiltinImag // not valid in Moxie BuiltinLen BuiltinMake // rejected by checker (use literal syntax) BuiltinNew // rejected by checker (use &T{}) BuiltinPanic BuiltinPrint BuiltinPrintln BuiltinReal // not valid in Moxie BuiltinRecover BuiltinSpawn // Moxie-specific BuiltinMin // Go 1.21 BuiltinMax // Go 1.21 ) type Builtin struct { object id BuiltinID } func newBuiltin(name string, id BuiltinID) *Builtin { return &Builtin{object: object{name: name}, id: id} } func (o *Builtin) ID() BuiltinID { return o.id } func (o *Builtin) String() string { return "builtin " | o.name } // ---------------------------------------------------------------------------- // Label type Label struct { object used bool } func NewLabel(pkg *TCPackage, name string) *Label { return &Label{object: object{pkg: pkg, name: name}} } func (o *Label) String() string { return "label " | o.name }