Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion experimental/ast/zero_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func testZero[Node source.Spanner](t *testing.T) {
r = m.Call(nil)[0]
}

assert.Zero(t, r.Interface(), "non-zero return #%d %#v of %T.%s", i, r, z, m.Name)
assert.Zero(t, r.Interface(), "non-zero return %#d %#v of %T.%s", i, r, z, m.Name)
}
}
})
Expand Down
3 changes: 3 additions & 0 deletions experimental/ir/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@ func GetImports(f *File) *Imports {
}

func (s Symbol) RawData() arena.Untyped {
if s.IsZero() {
return arena.Nil()
}
return s.Raw().data
}
78 changes: 66 additions & 12 deletions experimental/ir/ir_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ func (f *File) InternedPath() intern.ID {
// google/protobuf/descriptor.proto, which is given special treatment in
// the language.
func (f *File) IsDescriptorProto() bool {
if f == nil {
return false
}
return f.InternedPath() == f.session.builtins.DescriptorFile
}

Expand Down Expand Up @@ -176,15 +179,23 @@ func (f *File) InternedPackage() intern.ID {

// Imports returns an indexer over the imports declared in this file.
func (f *File) Imports() seq.Indexer[Import] {
return f.imports.Directs()
var imp imports
if f != nil {
imp = f.imports
}
return imp.Directs()
}

// TransitiveImports returns an indexer over the transitive imports for this
// file.
//
// This function does not report whether those imports are weak or not.
func (f *File) TransitiveImports() seq.Indexer[Import] {
return f.imports.Transitive()
var imp imports
if f != nil {
imp = f.imports
}
return imp.Transitive()
}

// ImportFor returns import metadata for a given file, if this file imports it.
Expand All @@ -199,8 +210,12 @@ func (f *File) ImportFor(that *File) Import {

// Types returns the top level types of this file.
func (f *File) Types() seq.Indexer[Type] {
var types []id.ID[Type]
if f != nil {
types = f.types[:f.topLevelTypesEnd]
}
return seq.NewFixedSlice(
f.types[:f.topLevelTypesEnd],
types,
func(_ int, p id.ID[Type]) Type {
return id.Wrap(f, p)
},
Expand All @@ -209,8 +224,12 @@ func (f *File) Types() seq.Indexer[Type] {

// AllTypes returns all types defined in this file.
func (f *File) AllTypes() seq.Indexer[Type] {
var types []id.ID[Type]
if f != nil {
types = f.types
}
return seq.NewFixedSlice(
f.types,
types,
func(_ int, p id.ID[Type]) Type {
return id.Wrap(f, p)
},
Expand All @@ -220,8 +239,12 @@ func (f *File) AllTypes() seq.Indexer[Type] {
// Extensions returns the top level extensions defined in this file (i.e.,
// the contents of any top-level `extends` blocks).
func (f *File) Extensions() seq.Indexer[Member] {
var slice []id.ID[Member]
if f != nil {
slice = f.extns[:f.topLevelExtnsEnd]
}
return seq.NewFixedSlice(
f.extns[:f.topLevelExtnsEnd],
slice,
func(_ int, p id.ID[Member]) Member {
return id.Wrap(f, p)
},
Expand All @@ -230,8 +253,12 @@ func (f *File) Extensions() seq.Indexer[Member] {

// AllExtensions returns all extensions defined in this file.
func (f *File) AllExtensions() seq.Indexer[Member] {
var extns []id.ID[Member]
if f != nil {
extns = f.extns
}
return seq.NewFixedSlice(
f.extns,
extns,
func(_ int, p id.ID[Member]) Member {
return id.Wrap(f, p)
},
Expand All @@ -240,8 +267,12 @@ func (f *File) AllExtensions() seq.Indexer[Member] {

// Extends returns the top level extend blocks in this file.
func (f *File) Extends() seq.Indexer[Extend] {
var slice []id.ID[Extend]
if f != nil {
slice = f.extends[:f.topLevelExtendsEnd]
}
return seq.NewFixedSlice(
f.extends[:f.topLevelExtendsEnd],
slice,
func(_ int, p id.ID[Extend]) Extend {
return id.Wrap(f, p)
},
Expand All @@ -250,8 +281,12 @@ func (f *File) Extends() seq.Indexer[Extend] {

// AllExtends returns all extend blocks in this file.
func (f *File) AllExtends() seq.Indexer[Extend] {
var extends []id.ID[Extend]
if f != nil {
extends = f.extends
}
return seq.NewFixedSlice(
f.extends,
extends,
func(_ int, p id.ID[Extend]) Extend {
return id.Wrap(f, p)
},
Expand All @@ -261,17 +296,25 @@ func (f *File) AllExtends() seq.Indexer[Extend] {
// AllMembers returns all fields defined in this file, including extensions
// and enum values.
func (f *File) AllMembers() iter.Seq[Member] {
var raw iter.Seq[*rawMember]
if f != nil {
raw = f.arenas.members.Values()
}
i := 0
return iterx.Map(f.arenas.members.Values(), func(raw *rawMember) Member {
return iterx.Map(raw, func(raw *rawMember) Member {
i++
return id.WrapRaw(f, id.ID[Member](i), raw)
})
}

// Services returns all services defined in this file.
func (f *File) Services() seq.Indexer[Service] {
var services []id.ID[Service]
if f != nil {
services = f.services
}
return seq.NewFixedSlice(
f.services,
services,
func(_ int, p id.ID[Service]) Service {
return id.Wrap(f, p)
},
Expand All @@ -280,11 +323,18 @@ func (f *File) Services() seq.Indexer[Service] {

// Options returns the top level options applied to this file.
func (f *File) Options() MessageValue {
return id.Wrap(f, f.options).AsMessage()
var options id.ID[Value]
if f != nil {
options = f.options
}
return id.Wrap(f, options).AsMessage()
}

// FeatureSet returns the Editions features associated with this file.
func (f *File) FeatureSet() FeatureSet {
if f == nil {
return FeatureSet{}
}
return id.Wrap(f, f.features)
}

Expand All @@ -308,8 +358,12 @@ func (f *File) Deprecated() Value {
// imported by the file. The symbols are returned in an arbitrary but fixed
// order.
func (f *File) Symbols() seq.Indexer[Symbol] {
var symbols []Ref[Symbol]
if f != nil {
symbols = f.imported
}
return seq.NewFixedSlice(
f.imported,
symbols,
func(_ int, r Ref[Symbol]) Symbol {
return GetRef(f, r)
},
Expand Down
15 changes: 13 additions & 2 deletions experimental/ir/ir_imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,21 @@ func (i *imports) MarkUsed(file *File) {

// DescriptorProto returns the file for descriptor.proto.
func (i *imports) DescriptorProto() *File {
if i == nil {
return nil
}
imported, _ := slicesx.Last(i.files)
return imported.file
}

// Directs returns an indexer over the Directs imports.
func (i *imports) Directs() seq.Indexer[Import] {
var slice []imported
if i != nil {
slice = i.files[:i.importEnd]
}
return seq.NewFixedSlice(
i.files[:i.importEnd],
slice,
func(j int, imported imported) Import {
n := uint32(j)
public := n < i.publicEnd
Expand All @@ -223,8 +230,12 @@ func (i *imports) Directs() seq.Indexer[Import] {
//
// This function does not report whether those imports are weak or used.
func (i *imports) Transitive() seq.Indexer[Import] {
var slice []imported
if i != nil {
slice = i.files[:max(0, len(i.files)-1)] // Exclude the implicit descriptor.proto
}
return seq.NewFixedSlice(
i.files[:max(0, len(i.files)-1)], // Exclude the implicit descriptor.proto.
slice,
func(j int, imported imported) Import {
n := uint32(j)
return Import{
Expand Down
20 changes: 14 additions & 6 deletions experimental/ir/ir_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ func (m Member) Oneof() Oneof {

// Options returns the options applied to this member.
func (m Member) Options() MessageValue {
if m.IsZero() {
return MessageValue{}
}

return id.Wrap(m.Context(), m.Raw().options).AsMessage()
}

Expand Down Expand Up @@ -587,12 +591,13 @@ func (o Oneof) Index() int {

// Members returns this oneof's member fields.
func (o Oneof) Members() seq.Indexer[Member] {
return seq.NewFixedSlice(
o.Raw().members,
func(_ int, p id.ID[Member]) Member {
return id.Wrap(o.Context(), p)
},
)
var members []id.ID[Member]
if !o.IsZero() {
members = o.Raw().members
}
return seq.NewFixedSlice(members, func(_ int, p id.ID[Member]) Member {
return id.Wrap(o.Context(), p)
})
}

// Parent returns the type that this oneof is declared within,.
Expand Down Expand Up @@ -715,6 +720,9 @@ type rawReservedName struct {

// AST returns the expression that this name was evaluated from, if known.
func (r ReservedName) AST() ast.ExprAny {
if r.IsZero() {
return ast.ExprAny{}
}
return r.raw.ast
}

Expand Down
38 changes: 31 additions & 7 deletions experimental/ir/ir_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ func (t Type) AllowsAlias() bool {
// IsAny returns whether this is the type google.protobuf.Any, which gets special
// treatment in the language.
func (t Type) IsAny() bool {
return t.InternedFullName() == t.Context().session.builtins.AnyPath
return !t.IsZero() && t.InternedFullName() == t.Context().session.builtins.AnyPath
}

// Predeclared returns the predeclared type that this Type corresponds to, if any.
Expand Down Expand Up @@ -417,7 +417,10 @@ func (t Type) Extensions() seq.Indexer[Member] {
//
// This does not include reserved field names; see [Type.ReservedNames].
func (t Type) AllRanges() seq.Indexer[ReservedRange] {
slice := t.Raw().ranges
var slice []id.ID[ReservedRange]
if !t.IsZero() {
slice = t.Raw().ranges
}
return seq.NewFixedSlice(slice, func(_ int, p id.ID[ReservedRange]) ReservedRange {
return id.Wrap(t.Context(), p)
})
Expand All @@ -427,24 +430,34 @@ func (t Type) AllRanges() seq.Indexer[ReservedRange] {
//
// This does not include reserved field names; see [Type.ReservedNames].
func (t Type) ReservedRanges() seq.Indexer[ReservedRange] {
slice := t.Raw().ranges[:t.Raw().rangesExtnStart]
var slice []id.ID[ReservedRange]
if !t.IsZero() {
slice = t.Raw().ranges[:t.Raw().rangesExtnStart]
}
return seq.NewFixedSlice(slice, func(_ int, p id.ID[ReservedRange]) ReservedRange {
return id.Wrap(t.Context(), p)
})
}

// ExtensionRanges returns the extension ranges declared in this type.
func (t Type) ExtensionRanges() seq.Indexer[ReservedRange] {
slice := t.Raw().ranges[t.Raw().rangesExtnStart:]
var slice []id.ID[ReservedRange]
if !t.IsZero() {
slice = t.Raw().ranges[t.Raw().rangesExtnStart:]
}
return seq.NewFixedSlice(slice, func(_ int, p id.ID[ReservedRange]) ReservedRange {
return id.Wrap(t.Context(), p)
})
}

// ReservedNames returns the reserved named declared in this type.
func (t Type) ReservedNames() seq.Indexer[ReservedName] {
var slice []rawReservedName
if !t.IsZero() {
slice = t.Raw().reservedNames
}
return seq.NewFixedSlice(
t.Raw().reservedNames,
slice,
func(i int, _ rawReservedName) ReservedName {
return ReservedName{id.WrapContext(t.Context()), &t.Raw().reservedNames[i]}
},
Expand All @@ -453,8 +466,12 @@ func (t Type) ReservedNames() seq.Indexer[ReservedName] {

// Oneofs returns the options applied to this type.
func (t Type) Oneofs() seq.Indexer[Oneof] {
var oneofs []id.ID[Oneof]
if !t.IsZero() {
oneofs = t.Raw().oneofs
}
return seq.NewFixedSlice(
t.Raw().oneofs,
oneofs,
func(_ int, p id.ID[Oneof]) Oneof {
return id.Wrap(t.Context(), p)
},
Expand All @@ -463,8 +480,12 @@ func (t Type) Oneofs() seq.Indexer[Oneof] {

// Extends returns the options applied to this type.
func (t Type) Extends() seq.Indexer[Extend] {
var extends []id.ID[Extend]
if !t.IsZero() {
extends = t.Raw().extends
}
return seq.NewFixedSlice(
t.Raw().extends,
extends,
func(_ int, p id.ID[Extend]) Extend {
return id.Wrap(t.Context(), p)
},
Expand All @@ -473,6 +494,9 @@ func (t Type) Extends() seq.Indexer[Extend] {

// Options returns the options applied to this type.
func (t Type) Options() MessageValue {
if t.IsZero() {
return MessageValue{}
}
return id.Wrap(t.Context(), t.Raw().options).AsMessage()
}

Expand Down
6 changes: 6 additions & 0 deletions experimental/ir/ir_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,13 @@ func (e Element) AST() ast.ExprAny {
// this element, e.g.
//
// key := e.Value().MessageKeys().At(e.ValueNodeIndex())
//
// If the element is empty, this returns -1.
func (e Element) ValueNodeIndex() int {
if e.IsZero() {
return -1
}

Comment on lines +575 to +580
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to make sure this behaviour is reasonable.

// We do O(log n) work here, because this function doesn't get called except
// for diagnostics.

Expand Down
Loading
Loading