...

Source file src/cuelang.org/go/internal/core/compile/predeclared.go

Documentation: cuelang.org/go/internal/core/compile

     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.NumKind}
    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.NumKind, parseFloat(a))
   140  	to := newBound(adt.LessEqualOp, adt.NumKind, 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  }
   170  

View as plain text