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