github.com/solo-io/cue@v0.4.7/internal/core/compile/predeclared.go (about) 1 // Copyright 2020 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package compile 16 17 import ( 18 "strconv" 19 20 "github.com/solo-io/cue/cue/ast" 21 "github.com/solo-io/cue/cue/token" 22 "github.com/solo-io/cue/internal/core/adt" 23 ) 24 25 func predeclared(n *ast.Ident) adt.Expr { 26 // TODO: consider supporting GraphQL-style names: 27 // String, Bytes, Boolean, Integer, Number. 28 // These names will not conflict with idiomatic camel-case JSON. 29 switch n.Name { 30 case "_": 31 return &adt.Top{Src: n} 32 case "string", "__string": 33 return &adt.BasicType{Src: n, K: adt.StringKind} 34 case "bytes", "__bytes": 35 return &adt.BasicType{Src: n, K: adt.BytesKind} 36 case "bool", "__bool": 37 return &adt.BasicType{Src: n, K: adt.BoolKind} 38 case "int", "__int": 39 return &adt.BasicType{Src: n, K: adt.IntKind} 40 case "float", "__float": 41 return &adt.BasicType{Src: n, K: adt.FloatKind} 42 case "number", "__number": 43 return &adt.BasicType{Src: n, K: adt.NumKind} 44 45 case "len", "__len": 46 return lenBuiltin 47 case "close", "__close": 48 return closeBuiltin 49 case "and", "__and": 50 return andBuiltin 51 case "or", "__or": 52 return orBuiltin 53 case "div", "__div": 54 return divBuiltin 55 case "mod", "__mod": 56 return modBuiltin 57 case "quo", "__quo": 58 return quoBuiltin 59 case "rem", "__rem": 60 return remBuiltin 61 } 62 63 if r, ok := predefinedRanges[n.Name]; ok { 64 return r 65 } 66 67 return nil 68 } 69 70 // LookupRange returns a CUE expressions for the given predeclared identifier 71 // representing a range, such as uint8, int128, and float64. 72 func LookupRange(name string) adt.Expr { 73 return predefinedRanges[name] 74 } 75 76 var predefinedRanges = map[string]adt.Expr{ 77 "rune": mkIntRange("0", strconv.Itoa(0x10FFFF)), 78 "int8": mkIntRange("-128", "127"), 79 "int16": mkIntRange("-32768", "32767"), 80 "int32": mkIntRange("-2147483648", "2147483647"), 81 "int64": mkIntRange("-9223372036854775808", "9223372036854775807"), 82 "int128": mkIntRange( 83 "-170141183460469231731687303715884105728", 84 "170141183460469231731687303715884105727"), 85 86 // Do not include an alias for "byte", as it would be too easily confused 87 // with the builtin "bytes". 88 "uint": mkUint(), 89 "uint8": mkIntRange("0", "255"), 90 "uint16": mkIntRange("0", "65535"), 91 "uint32": mkIntRange("0", "4294967295"), 92 "uint64": mkIntRange("0", "18446744073709551615"), 93 "uint128": mkIntRange("0", "340282366920938463463374607431768211455"), 94 95 // 2**127 * (2**24 - 1) / 2**23 96 "float32": mkFloatRange( 97 "-3.40282346638528859811704183484516925440e+38", 98 "3.40282346638528859811704183484516925440e+38", 99 ), 100 // 2**1023 * (2**53 - 1) / 2**52 101 "float64": mkFloatRange( 102 "-1.797693134862315708145274237317043567981e+308", 103 "1.797693134862315708145274237317043567981e+308", 104 ), 105 } 106 107 func init() { 108 for k, v := range predefinedRanges { 109 predefinedRanges["__"+k] = v 110 } 111 } 112 113 // TODO: use an adt.BoundValue here. and conjunctions here. 114 115 func mkUint() adt.Expr { 116 from := newBound(adt.GreaterEqualOp, adt.IntKind, parseInt("0")) 117 ident := ast.NewIdent("__int") 118 src := ast.NewBinExpr(token.AND, ident, from.Src) 119 return &adt.Conjunction{ 120 Src: src, 121 Values: []adt.Value{ 122 &adt.BasicType{Src: ident, K: adt.IntKind}, from, 123 }, 124 } 125 } 126 127 func mkIntRange(a, b string) adt.Expr { 128 from := newBound(adt.GreaterEqualOp, adt.IntKind, parseInt(a)) 129 to := newBound(adt.LessEqualOp, adt.IntKind, parseInt(b)) 130 ident := ast.NewIdent("__int") 131 src := ast.NewBinExpr(token.AND, ident, from.Src, to.Src) 132 return &adt.Conjunction{ 133 Src: src, 134 Values: []adt.Value{ 135 &adt.BasicType{Src: ident, K: adt.IntKind}, from, to, 136 }, 137 } 138 } 139 140 func mkFloatRange(a, b string) adt.Expr { 141 from := newBound(adt.GreaterEqualOp, adt.NumKind, parseFloat(a)) 142 to := newBound(adt.LessEqualOp, adt.NumKind, parseFloat(b)) 143 src := ast.NewBinExpr(token.AND, from.Src, to.Src) 144 return &adt.Conjunction{Src: src, Values: []adt.Value{from, to}} 145 } 146 147 func newBound(op adt.Op, k adt.Kind, v adt.Value) *adt.BoundValue { 148 src := &ast.UnaryExpr{Op: op.Token(), X: v.Source().(ast.Expr)} 149 return &adt.BoundValue{Src: src, Op: op, Value: v} 150 } 151 152 func parseInt(s string) *adt.Num { 153 n := parseNum(adt.IntKind, s) 154 n.Src = &ast.BasicLit{Kind: token.INT, Value: s} 155 return n 156 } 157 158 func parseFloat(s string) *adt.Num { 159 n := parseNum(adt.FloatKind, s) 160 n.Src = &ast.BasicLit{Kind: token.FLOAT, Value: s} 161 return n 162 } 163 164 func parseNum(k adt.Kind, s string) *adt.Num { 165 num := &adt.Num{K: k} 166 _, _, err := num.X.SetString(s) 167 if err != nil { 168 panic(err) 169 } 170 return num 171 }