1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package compile
16
17 import (
18 "cuelang.org/go/cue/errors"
19 "cuelang.org/go/internal/core/adt"
20 )
21
22
23
24 const supportedByLen = adt.StructKind | adt.BytesKind | adt.StringKind | adt.ListKind
25
26 var (
27 stringParam = adt.Param{Value: &adt.BasicType{K: adt.StringKind}}
28 structParam = adt.Param{Value: &adt.BasicType{K: adt.StructKind}}
29 listParam = adt.Param{Value: &adt.BasicType{K: adt.ListKind}}
30 intParam = adt.Param{Value: &adt.BasicType{K: adt.IntKind}}
31 )
32
33 var lenBuiltin = &adt.Builtin{
34 Name: "len",
35 Params: []adt.Param{{Value: &adt.BasicType{K: supportedByLen}}},
36 Result: adt.IntKind,
37 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
38 v := args[0]
39 if x, ok := v.(*adt.Vertex); ok {
40 x.LockArcs = true
41 switch x.BaseValue.(type) {
42 case nil:
43
44 return c.NewErrf("unevaluated vertex")
45 case *adt.ListMarker:
46 return c.NewInt64(int64(len(x.Elems())), v)
47
48 case *adt.StructMarker:
49 n := 0
50 v, _ := v.(*adt.Vertex)
51 for _, a := range v.Arcs {
52 if a.Label.IsRegular() && a.IsDefined(c) {
53 n++
54 }
55 }
56 return c.NewInt64(int64(n), v)
57
58 default:
59 v = x.Value()
60 }
61 }
62
63 switch x := v.(type) {
64 case *adt.Bytes:
65 return c.NewInt64(int64(len(x.B)), v)
66 case *adt.String:
67 return c.NewInt64(int64(len(x.Str)), v)
68 default:
69 k := x.Kind()
70 if k&supportedByLen == adt.BottomKind {
71 return c.NewErrf("invalid argument type %v", k)
72 }
73 b := c.NewErrf("incomplete argument %s (type %v)", v, k)
74 b.Code = adt.IncompleteError
75 return b
76 }
77 },
78 }
79
80 var closeBuiltin = &adt.Builtin{
81 Name: "close",
82 Params: []adt.Param{structParam},
83 Result: adt.StructKind,
84 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
85 s, ok := args[0].(*adt.Vertex)
86 if !ok {
87 return c.NewErrf("struct argument must be concrete")
88 }
89 if m, ok := s.BaseValue.(*adt.StructMarker); ok && m.NeedClose {
90 return s
91 }
92 v := s.Clone()
93
94
95 v.BaseValue = &adt.StructMarker{NeedClose: true}
96 return v
97 },
98 }
99
100 var andBuiltin = &adt.Builtin{
101 Name: "and",
102 Params: []adt.Param{listParam},
103 Result: adt.IntKind,
104 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
105 list := c.RawElems(args[0])
106 if len(list) == 0 {
107 return &adt.Top{}
108 }
109 a := []adt.Value{}
110 for _, c := range list {
111 a = append(a, c)
112 }
113 return &adt.Conjunction{Values: a}
114 },
115 }
116
117 var orBuiltin = &adt.Builtin{
118 Name: "or",
119 Params: []adt.Param{listParam},
120 Result: adt.IntKind,
121 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
122 d := []adt.Disjunct{}
123 for _, c := range c.RawElems(args[0]) {
124 d = append(d, adt.Disjunct{Val: c, Default: false})
125 }
126 if len(d) == 0 {
127
128
129
130
131
132
133
134 return &adt.Bottom{
135 Code: adt.IncompleteError,
136 Err: errors.Newf(c.Pos(), "empty list in call to or"),
137 }
138 }
139 v := &adt.Vertex{}
140
141 closeInfo := c.CloseInfo()
142 v.AddConjunct(adt.MakeConjunct(nil,
143 &adt.DisjunctionExpr{Values: d, HasDefaults: false},
144 closeInfo,
145 ))
146 v.CompleteArcs(c)
147 return v
148 },
149 }
150
151 var divBuiltin = &adt.Builtin{
152 Name: "div",
153 Params: []adt.Param{intParam, intParam},
154 Result: adt.IntKind,
155 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
156 const name = "argument to div builtin"
157
158 return intDivOp(c, (*adt.OpContext).IntDiv, name, args)
159 },
160 }
161
162 var modBuiltin = &adt.Builtin{
163 Name: "mod",
164 Params: []adt.Param{intParam, intParam},
165 Result: adt.IntKind,
166 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
167 const name = "argument to mod builtin"
168
169 return intDivOp(c, (*adt.OpContext).IntMod, name, args)
170 },
171 }
172
173 var quoBuiltin = &adt.Builtin{
174 Name: "quo",
175 Params: []adt.Param{intParam, intParam},
176 Result: adt.IntKind,
177 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
178 const name = "argument to quo builtin"
179
180 return intDivOp(c, (*adt.OpContext).IntQuo, name, args)
181 },
182 }
183
184 var remBuiltin = &adt.Builtin{
185 Name: "rem",
186 Params: []adt.Param{intParam, intParam},
187 Result: adt.IntKind,
188 Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
189 const name = "argument to rem builtin"
190
191 return intDivOp(c, (*adt.OpContext).IntRem, name, args)
192 },
193 }
194
195 type intFunc func(c *adt.OpContext, x, y *adt.Num) adt.Value
196
197 func intDivOp(c *adt.OpContext, fn intFunc, name string, args []adt.Value) adt.Value {
198 a := c.Num(args[0], name)
199 b := c.Num(args[1], name)
200
201 if c.HasErr() {
202 return nil
203 }
204
205 return fn(c, a, b)
206 }
207
View as plain text