Skip to content

Commit bf882b0

Browse files
committed
pkg/internal: copy cue builtin code to separate package
Mostly a copy and reorg. Contain minor modifications to make it compile. Adds Register function to facilitate registring. Change-Id: I1494f9f057130277e82cb62d04973488de916473 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6884 Reviewed-by: CUE cueckoo <[email protected]> Reviewed-by: Marcel van Lohuizen <[email protected]>
1 parent 9acd624 commit bf882b0

File tree

3 files changed

+609
-0
lines changed

3 files changed

+609
-0
lines changed

pkg/internal/builtin.go

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
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 internal
16+
17+
import (
18+
"encoding/json"
19+
"fmt"
20+
21+
"cuelang.org/go/cue/errors"
22+
"cuelang.org/go/cue/parser"
23+
"cuelang.org/go/cue/token"
24+
"cuelang.org/go/internal"
25+
"cuelang.org/go/internal/core/adt"
26+
"cuelang.org/go/internal/core/compile"
27+
"cuelang.org/go/internal/core/convert"
28+
)
29+
30+
// A Builtin is a Builtin function or constant.
31+
//
32+
// A function may return and a constant may be any of the following types:
33+
//
34+
// error (translates to bottom)
35+
// nil (translates to null)
36+
// bool
37+
// int*
38+
// uint*
39+
// float64
40+
// string
41+
// *big.Float
42+
// *big.Int
43+
//
44+
// For any of the above, including interface{} and these types recursively:
45+
// []T
46+
// map[string]T
47+
//
48+
type Builtin struct {
49+
Name string
50+
Pkg adt.Feature
51+
Params []adt.Kind
52+
Result adt.Kind
53+
Func func(c *CallCtxt)
54+
Const string
55+
}
56+
57+
type Package struct {
58+
Native []*Builtin
59+
CUE string
60+
}
61+
62+
func (p *Package) MustCompile(ctx *adt.OpContext, pkgName string) *adt.Vertex {
63+
obj := &adt.Vertex{}
64+
pkgLabel := ctx.StringLabel(pkgName)
65+
st := &adt.StructLit{}
66+
if len(p.Native) > 0 {
67+
obj.AddConjunct(adt.MakeConjunct(nil, st))
68+
}
69+
for _, b := range p.Native {
70+
b.Pkg = pkgLabel
71+
72+
f := ctx.StringLabel(b.Name) // never starts with _
73+
// n := &node{baseValue: newBase(imp.Path)}
74+
var v adt.Expr = toBuiltin(ctx, b)
75+
if b.Const != "" {
76+
v = mustParseConstBuiltin(ctx, b.Name, b.Const)
77+
}
78+
st.Decls = append(st.Decls, &adt.Field{
79+
Label: f,
80+
Value: v,
81+
})
82+
}
83+
84+
// Parse builtin CUE
85+
if p.CUE != "" {
86+
expr, err := parser.ParseExpr(pkgName, p.CUE)
87+
if err != nil {
88+
panic(fmt.Errorf("could not parse %v: %v", p.CUE, err))
89+
}
90+
c, err := compile.Expr(nil, ctx.Runtime, expr)
91+
if err != nil {
92+
panic(fmt.Errorf("could compile parse %v: %v", p.CUE, err))
93+
}
94+
obj.AddConjunct(c)
95+
}
96+
97+
// We could compile lazily, but this is easier for debugging.
98+
obj.Finalize(ctx)
99+
if err := obj.Err(ctx, adt.Finalized); err != nil {
100+
panic(err.Err)
101+
}
102+
103+
return obj
104+
}
105+
106+
func toBuiltin(ctx *adt.OpContext, b *Builtin) *adt.Builtin {
107+
x := &adt.Builtin{
108+
Params: b.Params,
109+
Result: b.Result,
110+
Package: b.Pkg,
111+
Name: b.Name,
112+
}
113+
x.Func = func(ctx *adt.OpContext, args []adt.Value) (ret adt.Expr) {
114+
// call, _ := ctx.Source().(*ast.CallExpr)
115+
c := &CallCtxt{
116+
// src: call,
117+
ctx: ctx,
118+
args: args,
119+
builtin: b,
120+
}
121+
defer func() {
122+
var errVal interface{} = c.Err
123+
if err := recover(); err != nil {
124+
errVal = err
125+
}
126+
ret = processErr(c, errVal, ret)
127+
}()
128+
b.Func(c)
129+
switch v := c.Ret.(type) {
130+
case adt.Value:
131+
return v
132+
case bottomer:
133+
return v.Bottom()
134+
}
135+
if c.Err != nil {
136+
return nil
137+
}
138+
return convert.GoValueToValue(ctx, c.Ret, true)
139+
}
140+
return x
141+
}
142+
143+
// newConstBuiltin parses and creates any CUE expression that does not have
144+
// fields.
145+
func mustParseConstBuiltin(ctx adt.Runtime, name, val string) adt.Expr {
146+
expr, err := parser.ParseExpr("<builtin:"+name+">", val)
147+
if err != nil {
148+
panic(err)
149+
}
150+
c, err := compile.Expr(nil, ctx, expr)
151+
if err != nil {
152+
panic(err)
153+
}
154+
return c.Expr()
155+
156+
}
157+
158+
func pos(n adt.Node) (p token.Pos) {
159+
if n == nil {
160+
return
161+
}
162+
src := n.Source()
163+
if src == nil {
164+
return
165+
}
166+
return src.Pos()
167+
}
168+
169+
func (x *Builtin) name(ctx *adt.OpContext) string {
170+
if x.Pkg == 0 {
171+
return x.Name
172+
}
173+
return fmt.Sprintf("%s.%s", x.Pkg.StringValue(ctx), x.Name)
174+
}
175+
176+
func (x *Builtin) isValidator() bool {
177+
return len(x.Params) == 1 && x.Result == adt.BoolKind
178+
}
179+
180+
func processErr(call *CallCtxt, errVal interface{}, ret adt.Expr) adt.Expr {
181+
ctx := call.ctx
182+
switch err := errVal.(type) {
183+
case nil:
184+
case *callError:
185+
ret = err.b
186+
case *json.MarshalerError:
187+
if err, ok := err.Err.(bottomer); ok {
188+
if b := err.Bottom(); b != nil {
189+
ret = b
190+
}
191+
}
192+
case bottomer:
193+
ret = wrapCallErr(call, err.Bottom())
194+
case errors.Error:
195+
ret = wrapCallErr(call, &adt.Bottom{Err: err})
196+
case error:
197+
if call.Err == internal.ErrIncomplete {
198+
err := ctx.NewErrf("incomplete value")
199+
err.Code = adt.IncompleteError
200+
ret = err
201+
} else {
202+
// TODO: store the underlying error explicitly
203+
ret = wrapCallErr(call, &adt.Bottom{Err: errors.Promote(err, "")})
204+
}
205+
default:
206+
// Likely a string passed to panic.
207+
ret = wrapCallErr(call, &adt.Bottom{
208+
Err: errors.Newf(call.Pos(), "%s", err),
209+
})
210+
}
211+
return ret
212+
}

0 commit comments

Comments
 (0)