This repository has been archived by the owner on Feb 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 108
/
terms.go
170 lines (142 loc) · 4.31 KB
/
terms.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright 2019 eBay Inc.
// Primary authors: Simon Fell, Diego Ongaro,
// Raymond Kroeker, and Sathish Kandasamy.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plandef
import (
"fmt"
"strconv"
"strings"
"github.com/ebay/akutan/rpc"
"github.com/ebay/akutan/util/cmp"
)
// A Term is an argument to an Operator, such as a Variable or an OID.
// Every type of Term is either a FreeTerm or a FixedTerm.
type Term interface {
String() string
cmp.Key
aTerm()
}
// A FreeTerm is a Term that has an unknown value when the operator executes. It
// represents a result from the operator.
type FreeTerm interface {
Term
aFreeTerm()
}
// ImplementFreeTerm is a list of types that implement FreeTerm. This serves as
// documentation and as a compile-time check.
var ImplementFreeTerm = []FreeTerm{
new(DontCare),
new(Variable),
}
// A FixedTerm is a Term that has a known value before the operator executes.
type FixedTerm interface {
Term
aFixedTerm()
}
// ImplementFixedTerm is a list of types that implement FixedTerm. This serves
// as documentation and as a compile-time check.
var ImplementFixedTerm = []FixedTerm{
new(Binding),
new(Literal),
new(OID),
}
// DontCare is a FreeTerm representing a placeholder for a result to be discarded.
type DontCare struct {
// The very bottom of the Go spec
// https://golang.org/ref/spec#Size_and_alignment_guarantees says pointers to
// two empty slices may be the same. This byte of padding ensures that pointers
// distinct DontCare values will by unequal (not ==).
_ byte
}
func (*DontCare) aTerm() {}
func (*DontCare) aFreeTerm() {}
// String returns "_".
func (d *DontCare) String() string {
return "_"
}
// Key implements cmp.Key.
func (d *DontCare) Key(b *strings.Builder) {
b.WriteByte('_')
}
// A Variable is a FreeTerm representing a placeholder for a named result.
type Variable struct {
Name string
}
func (*Variable) aTerm() {}
func (*Variable) aFreeTerm() {}
func (*Variable) anExpression() {}
// String returns a string like "?foo".
func (v *Variable) String() string {
return "?" + v.Name
}
// Key implements cmp.Key.
func (v *Variable) Key(b *strings.Builder) {
b.WriteByte('?')
b.WriteString(v.Name)
}
// A Binding is a variable that will be filled in by values from an outer nested
// loop join. Unlike a Variable, Binding is a FixedTerm.
type Binding struct {
Var *Variable
}
func (*Binding) aTerm() {}
func (*Binding) aFixedTerm() {}
// String returns a string like "$foo".
func (b *Binding) String() string {
return "$" + b.Var.Name
}
// Key implements cmp.Key.
func (b *Binding) Key(buf *strings.Builder) {
buf.WriteByte('$')
buf.WriteString(b.Var.Name)
}
// An OID is a FixedTerm containing an opaque resource identifier.
type OID struct {
Value uint64
// If not empty, this is a unique identifier for the same entity that's more
// human-friendly, like "<foo>" or "rdfs:label".
Hint string
}
func (*OID) aTerm() {}
func (*OID) aFixedTerm() {}
// String returns oid.Hint if that's set; otherwise, it returns a string like
// "#1052".
func (oid *OID) String() string {
if oid.Hint == "" {
return fmt.Sprintf("#%v", oid.Value)
}
return oid.Hint
}
// Key implements cmp.Key. The key is based on oid.Value alone; the Hint does
// not affect it.
func (oid *OID) Key(b *strings.Builder) {
b.WriteByte('#')
b.WriteString(strconv.FormatUint(oid.Value, 10))
}
// A Literal is a FixedTerm containing a literal value, like a particular
// float or string.
type Literal struct {
// Most KGObject types are allowed, but KID is not: that is represented as an
// OID instead.
Value rpc.KGObject
}
func (*Literal) aTerm() {}
func (*Literal) aFixedTerm() {}
func (literal *Literal) String() string {
return literal.Value.String()
}
// Key implements cmp.Key.
func (literal *Literal) Key(b *strings.Builder) {
literal.Value.Key(b)
}