cuelang.org/go@v0.13.0/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 "cuelang.org/go/cue/ast" 21 "cuelang.org/go/cue/token" 22 "cuelang.org/go/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 "string", "__string": 31 return &adt.BasicType{Src: n, K: adt.StringKind} 32 case "bytes", "__bytes": 33 return &adt.BasicType{Src: n, K: adt.BytesKind} 34 case "bool", "__bool": 35 return &adt.BasicType{Src: n, K: adt.BoolKind} 36 case "int", "__int": 37 return &adt.BasicType{Src: n, K: adt.IntKind} 38 case "float", "__float": 39 return &adt.BasicType{Src: n, K: adt.FloatKind} 40 case "number", "__number": 41 return &adt.BasicType{Src: n, K: adt.NumberKind} 42 43 case "len", "__len": 44 return lenBuiltin 45 case "close", "__close": 46 return closeBuiltin 47 case "matchIf", "__matchIf": 48 return matchIfBuiltin 49 case "matchN", "__matchN": 50 return matchNBuiltin 51 case "and", "__and": 52 return andBuiltin 53 case "or", "__or": 54 return orBuiltin 55 case "div", "__div": 56 return divBuiltin 57 case "mod", "__mod": 58 return modBuiltin 59 case "quo", "__quo": 60 return quoBuiltin 61 case "rem", "__rem": 62 return remBuiltin 63 64 case "__no_sharing": 65 return adt.NoShareSentinel 66 } 67 68 if r, ok := predefinedRanges[n.Name]; ok { 69 return r 70 } 71 72 return nil 73 } 74 75 // LookupRange returns a CUE expressions for the given predeclared identifier 76 // representing a range, such as uint8, int128, and float64. 77 func LookupRange(name string) adt.Expr { 78 return predefinedRanges[name] 79 } 80 81 var predefinedRanges = map[string]adt.Expr{ 82 "rune": mkIntRange("0", strconv.Itoa(0x10FFFF)), 83 "int8": mkIntRange("-128", "127"), 84 "int16": mkIntRange("-32768", "32767"), 85 "int32": mkIntRange("-2147483648", "2147483647"), 86 "int64": mkIntRange("-9223372036854775808", "9223372036854775807"), 87 "int128": mkIntRange( 88 "-170141183460469231731687303715884105728", 89 "170141183460469231731687303715884105727"), 90 91 // Do not include an alias for "byte", as it would be too easily confused 92 // with the builtin "bytes". 93 "uint": mkUint(), 94 "uint8": mkIntRange("0", "255"), 95 "uint16": mkIntRange("0", "65535"), 96 "uint32": mkIntRange("0", "4294967295"), 97 "uint64": mkIntRange("0", "18446744073709551615"), 98 "uint128": mkIntRange("0", "340282366920938463463374607431768211455"), 99 100 // 2**127 * (2**24 - 1) / 2**23 101 "float32": mkFloatRange( 102 "-3.40282346638528859811704183484516925440e+38", 103 "3.40282346638528859811704183484516925440e+38", 104 ), 105 // 2**1023 * (2**53 - 1) / 2**52 106 "float64": mkFloatRange( 107 "-1.797693134862315708145274237317043567981e+308", 108 "1.797693134862315708145274237317043567981e+308", 109 ), 110 } 111 112 func init() { 113 for k, v := range predefinedRanges { 114 predefinedRanges["__"+k] = v 115 } 116 } 117 118 // TODO: use an adt.BoundValue here. and conjunctions here. 119 120 func mkUint() adt.Expr { 121 from := newBound(adt.GreaterEqualOp, adt.IntKind, parseInt("0")) 122 ident := ast.NewIdent("__int") 123 src := ast.NewBinExpr(token.AND, ident, from.Src) 124 return &adt.Conjunction{ 125 Src: src, 126 Values: []adt.Value{ 127 &adt.BasicType{Src: ident, K: adt.IntKind}, from, 128 }, 129 } 130 } 131 132 func mkIntRange(a, b string) adt.Expr { 133 from := newBound(adt.GreaterEqualOp, adt.IntKind, parseInt(a)) 134 to := newBound(adt.LessEqualOp, adt.IntKind, parseInt(b)) 135 ident := ast.NewIdent("__int") 136 src := ast.NewBinExpr(token.AND, ident, from.Src, to.Src) 137 return &adt.Conjunction{ 138 Src: src, 139 Values: []adt.Value{ 140 &adt.BasicType{Src: ident, K: adt.IntKind}, from, to, 141 }, 142 } 143 } 144 145 func mkFloatRange(a, b string) adt.Expr { 146 from := newBound(adt.GreaterEqualOp, adt.NumberKind, parseFloat(a)) 147 to := newBound(adt.LessEqualOp, adt.NumberKind, parseFloat(b)) 148 src := ast.NewBinExpr(token.AND, from.Src, to.Src) 149 return &adt.Conjunction{Src: src, Values: []adt.Value{from, to}} 150 } 151 152 func newBound(op adt.Op, k adt.Kind, v adt.Value) *adt.BoundValue { 153 src := &ast.UnaryExpr{Op: op.Token(), X: v.Source().(ast.Expr)} 154 return &adt.BoundValue{Src: src, Op: op, Value: v} 155 } 156 157 func parseInt(s string) *adt.Num { 158 n := parseNum(adt.IntKind, s) 159 n.Src = &ast.BasicLit{Kind: token.INT, Value: s} 160 return n 161 } 162 163 func parseFloat(s string) *adt.Num { 164 n := parseNum(adt.FloatKind, s) 165 n.Src = &ast.BasicLit{Kind: token.FLOAT, Value: s} 166 return n 167 } 168 169 func parseNum(k adt.Kind, s string) *adt.Num { 170 num := &adt.Num{K: k} 171 _, _, err := num.X.SetString(s) 172 if err != nil { 173 panic(err) 174 } 175 return num 176 }