cue: allow builtins defined in CUE
For now, just the time.Time type is added, which
is an often-used type in the type of Go structs that
one may want to map to CUE.
Updates #24
Change-Id: Ied688f7dd355006e4515520f22dd40b646703c6f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/1722
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cue/build.go b/cue/build.go
index a6d8601..ba247f4 100644
--- a/cue/build.go
+++ b/cue/build.go
@@ -46,7 +46,7 @@
return loaded
}
-// FromExpr creates anb instance from an expression.
+// FromExpr creates an instance from an expression.
// Any references must be resolved beforehand.
func FromExpr(fset *token.FileSet, expr ast.Expr) (*Instance, error) {
i := newIndex(fset).NewInstance(nil)
diff --git a/cue/builtin.go b/cue/builtin.go
index 550a4c5..72f466d 100644
--- a/cue/builtin.go
+++ b/cue/builtin.go
@@ -59,9 +59,14 @@
Const string
}
-func mustCompileBuiltins(ctx *context, b []*builtin) *structLit {
+type builtinPkg struct {
+ native []*builtin
+ cue string
+}
+
+func mustCompileBuiltins(ctx *context, p *builtinPkg) *structLit {
obj := &structLit{}
- for _, b := range b {
+ for _, b := range p.native {
f := ctx.label(b.Name, false) // never starts with _
// n := &node{baseValue: newBase(imp.Path)}
var v evaluated = b
@@ -71,6 +76,22 @@
obj.arcs = append(obj.arcs, arc{feature: f, v: v})
}
sort.Sort(obj)
+
+ // Parse builtin CUE
+ if p.cue != "" {
+ expr, err := parser.ParseExpr(ctx.index.fset, "<builtinPkg>", p.cue)
+ if err != nil {
+ fmt.Println(p.cue)
+ panic(err)
+ }
+ pkg := evalExpr(ctx.index, obj, expr).(*structLit)
+ for _, a := range pkg.arcs {
+ // Discard option status and attributes at top level.
+ // TODO: filter on capitalized fields?
+ obj.insertValue(ctx, a.feature, false, a.v, nil)
+ }
+ }
+
return obj
}
@@ -173,7 +194,7 @@
var builtins = map[string]*structLit{}
-func initBuiltins(pkgs map[string][]*builtin) {
+func initBuiltins(pkgs map[string]*builtinPkg) {
ctx := sharedIndex.newContext()
for k, b := range pkgs {
e := mustCompileBuiltins(ctx, b)
diff --git a/cue/builtins.go b/cue/builtins.go
index 1955814..93e8c9e 100644
--- a/cue/builtins.go
+++ b/cue/builtins.go
@@ -50,1790 +50,1836 @@
var pathDir = path.Dir
-var builtinPackages = map[string][]*builtin{
- "": []*builtin{{}},
- "crypto/md5": []*builtin{{
- Name: "Size",
- Const: "16",
- }, {
- Name: "BlockSize",
- Const: "64",
- }, {
- Name: "Sum",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return md5.Sum(data)
- }()
- },
- }},
- "crypto/sha1": []*builtin{{
- Name: "Size",
- Const: "20",
- }, {
- Name: "BlockSize",
- Const: "64",
- }, {
- Name: "Sum",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return sha1.Sum(data)
- }()
- },
- }},
- "crypto/sha256": []*builtin{{
- Name: "Size",
- Const: "32",
- }, {
- Name: "Size224",
- Const: "28",
- }, {
- Name: "BlockSize",
- Const: "64",
- }, {
- Name: "Sum256",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return sha256.Sum256(data)
- }()
- },
- }, {
- Name: "Sum224",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return sha256.Sum224(data)
- }()
- },
- }},
- "crypto/sha512": []*builtin{{
- Name: "Size",
- Const: "64",
- }, {
- Name: "Size224",
- Const: "28",
- }, {
- Name: "Size256",
- Const: "32",
- }, {
- Name: "Size384",
- Const: "48",
- }, {
- Name: "BlockSize",
- Const: "128",
- }, {
- Name: "Sum512",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return sha512.Sum512(data)
- }()
- },
- }, {
- Name: "Sum384",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return sha512.Sum384(data)
- }()
- },
- }, {
- Name: "Sum512_224",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return sha512.Sum512_224(data)
- }()
- },
- }, {
- Name: "Sum512_256",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return sha512.Sum512_256(data)
- }()
- },
- }},
- "encoding/csv": []*builtin{{
- Name: "Encode",
- Params: []kind{topKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- x := c.value(0)
- c.ret, c.err = func() (interface{}, error) {
- buf := &bytes.Buffer{}
- w := csv.NewWriter(buf)
- iter, err := x.List()
- if err != nil {
- return "", err
- }
- for iter.Next() {
- row, err := iter.Value().List()
- if err != nil {
- return "", err
- }
- a := []string{}
- for row.Next() {
- col := row.Value()
- if str, err := col.String(); err == nil {
- a = append(a, str)
- } else {
- b, err := col.MarshalJSON()
- if err != nil {
- return "", err
- }
- a = append(a, string(b))
- }
- }
- w.Write(a)
- }
- w.Flush()
- return buf.String(), nil
- }()
- },
- }, {
- Name: "Decode",
- Params: []kind{stringKind},
- Result: listKind,
- Func: func(c *callCtxt) {
- r := c.reader(0)
- c.ret, c.err = func() (interface{}, error) {
- return csv.NewReader(r).ReadAll()
- }()
- },
- }},
- "encoding/hex": []*builtin{{
- Name: "EncodedLen",
- Params: []kind{intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- n := c.int(0)
- c.ret = func() interface{} {
- return hex.EncodedLen(n)
- }()
- },
- }, {
- Name: "DecodedLen",
- Params: []kind{intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x := c.int(0)
- c.ret = func() interface{} {
- return hex.DecodedLen(x)
- }()
- },
- }, {
- Name: "Decode",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret, c.err = func() (interface{}, error) {
- return hex.DecodeString(s)
- }()
- },
- }, {
- Name: "Dump",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return hex.Dump(data)
- }()
- },
- }, {
- Name: "Encode",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- src := c.bytes(0)
- c.ret = func() interface{} {
- return hex.EncodeToString(src)
- }()
- },
- }},
- "encoding/json": []*builtin{{
- Name: "Valid",
- Params: []kind{stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret = func() interface{} {
- return json.Valid(data)
- }()
- },
- }, {
- Name: "Compact",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- src := c.bytes(0)
- c.ret, c.err = func() (interface{}, error) {
- dst := bytes.Buffer{}
- if err := json.Compact(&dst, src); err != nil {
- return "", err
- }
- return dst.String(), nil
- }()
- },
- }, {
- Name: "Indent",
- Params: []kind{stringKind, stringKind, stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- src, prefix, indent := c.bytes(0), c.string(1), c.string(2)
- c.ret, c.err = func() (interface{}, error) {
- dst := bytes.Buffer{}
- if err := json.Indent(&dst, src, prefix, indent); err != nil {
- return "", err
- }
- return dst.String(), nil
- }()
- },
- }, {
- Name: "HTMLEscape",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- src := c.bytes(0)
- c.ret = func() interface{} {
- dst := &bytes.Buffer{}
- json.HTMLEscape(dst, src)
- return dst.String()
- }()
- },
- }, {
- Name: "Marshal",
- Params: []kind{topKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- v := c.value(0)
- c.ret, c.err = func() (interface{}, error) {
- b, err := json.Marshal(v)
- return string(b), err
- }()
- },
- }, {
- Name: "MarshalStream",
- Params: []kind{topKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- v := c.value(0)
- c.ret, c.err = func() (interface{}, error) {
-
- iter, err := v.List()
- if err != nil {
- return "", err
- }
- buf := &bytes.Buffer{}
- for iter.Next() {
- b, err := json.Marshal(iter.Value())
- if err != nil {
- return "", err
- }
- buf.Write(b)
- buf.WriteByte('\n')
- }
- return buf.String(), nil
- }()
- },
- }, {
- Name: "Unmarshal",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- b := c.bytes(0)
- c.ret, c.err = func() (interface{}, error) {
- if !json.Valid(b) {
- return nil, fmt.Errorf("json: invalid JSON")
- }
- fset := token.NewFileSet()
- expr, err := parser.ParseExpr(fset, "json", b)
- if err != nil {
-
- return nil, fmt.Errorf("json: could not parse JSON: %v", err)
- }
- return expr, nil
- }()
- },
- }},
- "encoding/yaml": []*builtin{{
- Name: "Marshal",
- Params: []kind{topKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- v := c.value(0)
- c.ret, c.err = func() (interface{}, error) {
- b, err := goyaml.Marshal(v)
- return string(b), err
- }()
- },
- }, {
- Name: "MarshalStream",
- Params: []kind{topKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- v := c.value(0)
- c.ret, c.err = func() (interface{}, error) {
-
- iter, err := v.List()
- if err != nil {
- return "", err
- }
- buf := &bytes.Buffer{}
- for i := 0; iter.Next(); i++ {
- if i > 0 {
- buf.WriteString("---\n")
- }
- b, err := goyaml.Marshal(iter.Value())
- if err != nil {
- return "", err
- }
- buf.Write(b)
- }
- return buf.String(), nil
- }()
- },
- }, {
- Name: "Unmarshal",
- Params: []kind{stringKind},
- Result: topKind,
- Func: func(c *callCtxt) {
- data := c.bytes(0)
- c.ret, c.err = func() (interface{}, error) {
- fset := token.NewFileSet()
- return yaml.Unmarshal(fset, "", data)
- }()
- },
- }},
- "html": []*builtin{{
- Name: "Escape",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return html.EscapeString(s)
- }()
- },
- }, {
- Name: "Unescape",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return html.UnescapeString(s)
- }()
- },
- }},
- "list": []*builtin{{}},
- "math": []*builtin{{
- Name: "MaxExp",
- Const: "2147483647",
- }, {
- Name: "MinExp",
- Const: "-2147483648",
- }, {
- Name: "MaxPrec",
- Const: "4294967295",
- }, {
- Name: "ToNearestEven",
- Const: "0",
- }, {
- Name: "ToNearestAway",
- Const: "1",
- }, {
- Name: "ToZero",
- Const: "2",
- }, {
- Name: "AwayFromZero",
- Const: "3",
- }, {
- Name: "ToNegativeInf",
- Const: "4",
- }, {
- Name: "ToPositiveInf",
- Const: "5",
- }, {
- Name: "Below",
- Const: "-1",
- }, {
- Name: "Exact",
- Const: "0",
- }, {
- Name: "Above",
- Const: "1",
- }, {
- Name: "Jacobi",
- Params: []kind{intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x, y := c.bigInt(0), c.bigInt(1)
- c.ret = func() interface{} {
- return big.Jacobi(x, y)
- }()
- },
- }, {
- Name: "MaxBase",
- Const: "62",
- }, {
- Name: "Floor",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Floor(x)
- }()
- },
- }, {
- Name: "Ceil",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Ceil(x)
- }()
- },
- }, {
- Name: "Trunc",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Trunc(x)
- }()
- },
- }, {
- Name: "Round",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Round(x)
- }()
- },
- }, {
- Name: "RoundToEven",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.RoundToEven(x)
- }()
- },
- }, {
- Name: "Abs",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Abs(x)
- }()
- },
- }, {
- Name: "Acosh",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Acosh(x)
- }()
- },
- }, {
- Name: "Asin",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Asin(x)
- }()
- },
- }, {
- Name: "Acos",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Acos(x)
- }()
- },
- }, {
- Name: "Asinh",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Asinh(x)
- }()
- },
- }, {
- Name: "Atan",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Atan(x)
- }()
- },
- }, {
- Name: "Atan2",
- Params: []kind{numKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- y, x := c.float64(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Atan2(y, x)
- }()
- },
- }, {
- Name: "Atanh",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Atanh(x)
- }()
- },
- }, {
- Name: "Cbrt",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Cbrt(x)
- }()
- },
- }, {
- Name: "E",
- Const: "2.71828182845904523536028747135266249775724709369995957496696763",
- }, {
- Name: "Pi",
- Const: "3.14159265358979323846264338327950288419716939937510582097494459",
- }, {
- Name: "Phi",
- Const: "1.61803398874989484820458683436563811772030917980576286213544861",
- }, {
- Name: "Sqrt2",
- Const: "1.41421356237309504880168872420969807856967187537694807317667974",
- }, {
- Name: "SqrtE",
- Const: "1.64872127070012814684865078781416357165377610071014801157507931",
- }, {
- Name: "SqrtPi",
- Const: "1.77245385090551602729816748334114518279754945612238712821380779",
- }, {
- Name: "SqrtPhi",
- Const: "1.27201964951406896425242246173749149171560804184009624861664038",
- }, {
- Name: "Ln2",
- Const: "0.693147180559945309417232121458176568075500134360255254120680009",
- }, {
- Name: "Log2E",
- Const: "1.442695040888963407359924681001892137426645954152985934135449408",
- }, {
- Name: "Ln10",
- Const: "2.3025850929940456840179914546843642076011014886287729760333278",
- }, {
- Name: "Log10E",
- Const: "0.43429448190325182765112891891660508229439700580366656611445378",
- }, {
- Name: "Copysign",
- Params: []kind{numKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x, y := c.float64(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Copysign(x, y)
- }()
- },
- }, {
- Name: "Dim",
- Params: []kind{numKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x, y := c.float64(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Dim(x, y)
- }()
- },
- }, {
- Name: "Erf",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Erf(x)
- }()
- },
- }, {
- Name: "Erfc",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Erfc(x)
- }()
- },
- }, {
- Name: "Erfinv",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Erfinv(x)
- }()
- },
- }, {
- Name: "Erfcinv",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Erfcinv(x)
- }()
- },
- }, {
- Name: "Exp",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Exp(x)
- }()
- },
- }, {
- Name: "Exp2",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Exp2(x)
- }()
- },
- }, {
- Name: "Expm1",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Expm1(x)
- }()
- },
- }, {
- Name: "Gamma",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Gamma(x)
- }()
- },
- }, {
- Name: "Hypot",
- Params: []kind{numKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- p, q := c.float64(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Hypot(p, q)
- }()
- },
- }, {
- Name: "J0",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.J0(x)
- }()
- },
- }, {
- Name: "Y0",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Y0(x)
- }()
- },
- }, {
- Name: "J1",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.J1(x)
- }()
- },
- }, {
- Name: "Y1",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Y1(x)
- }()
- },
- }, {
- Name: "Jn",
- Params: []kind{intKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- n, x := c.int(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Jn(n, x)
- }()
- },
- }, {
- Name: "Yn",
- Params: []kind{intKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- n, x := c.int(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Yn(n, x)
- }()
- },
- }, {
- Name: "Ldexp",
- Params: []kind{numKind, intKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- frac, exp := c.float64(0), c.int(1)
- c.ret = func() interface{} {
- return math.Ldexp(frac, exp)
- }()
- },
- }, {
- Name: "Log",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Log(x)
- }()
- },
- }, {
- Name: "Log10",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Log10(x)
- }()
- },
- }, {
- Name: "Log2",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Log2(x)
- }()
- },
- }, {
- Name: "Log1p",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Log1p(x)
- }()
- },
- }, {
- Name: "Logb",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Logb(x)
- }()
- },
- }, {
- Name: "Ilogb",
- Params: []kind{numKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Ilogb(x)
- }()
- },
- }, {
- Name: "Mod",
- Params: []kind{numKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x, y := c.float64(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Mod(x, y)
- }()
- },
- }, {
- Name: "Pow",
- Params: []kind{numKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x, y := c.float64(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Pow(x, y)
- }()
- },
- }, {
- Name: "Pow10",
- Params: []kind{intKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- n := c.int(0)
- c.ret = func() interface{} {
- return math.Pow10(n)
- }()
- },
- }, {
- Name: "Remainder",
- Params: []kind{numKind, numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x, y := c.float64(0), c.float64(1)
- c.ret = func() interface{} {
- return math.Remainder(x, y)
- }()
- },
- }, {
- Name: "Signbit",
- Params: []kind{numKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Signbit(x)
- }()
- },
- }, {
- Name: "Cos",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Cos(x)
- }()
- },
- }, {
- Name: "Sin",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Sin(x)
- }()
- },
- }, {
- Name: "Sinh",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Sinh(x)
- }()
- },
- }, {
- Name: "Cosh",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Cosh(x)
- }()
- },
- }, {
- Name: "Sqrt",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Sqrt(x)
- }()
- },
- }, {
- Name: "Tan",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Tan(x)
- }()
- },
- }, {
- Name: "Tanh",
- Params: []kind{numKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- x := c.float64(0)
- c.ret = func() interface{} {
- return math.Tanh(x)
- }()
- },
- }},
- "math/bits": []*builtin{{
- Name: "And",
- Params: []kind{intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- a, b := c.bigInt(0), c.bigInt(1)
- c.ret = func() interface{} {
- wa := a.Bits()
- wb := b.Bits()
- n := len(wa)
- if len(wb) < n {
- n = len(wb)
- }
- w := make([]big.Word, n)
- for i := range w {
- w[i] = wa[i] & wb[i]
- }
- i := &big.Int{}
- i.SetBits(w)
- return i
- }()
- },
- }, {
- Name: "Or",
- Params: []kind{intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- a, b := c.bigInt(0), c.bigInt(1)
- c.ret = func() interface{} {
- wa := a.Bits()
- wb := b.Bits()
- var w []big.Word
- n := len(wa)
- if len(wa) > len(wb) {
- w = append(w, wa...)
- n = len(wb)
- } else {
- w = append(w, wb...)
- }
- for i := 0; i < n; i++ {
- w[i] = wa[i] | wb[i]
- }
- i := &big.Int{}
- i.SetBits(w)
- return i
- }()
- },
- }, {
- Name: "Xor",
- Params: []kind{intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- a, b := c.bigInt(0), c.bigInt(1)
- c.ret = func() interface{} {
- wa := a.Bits()
- wb := b.Bits()
- var w []big.Word
- n := len(wa)
- if len(wa) > len(wb) {
- w = append(w, wa...)
- n = len(wb)
- } else {
- w = append(w, wb...)
- }
- for i := 0; i < n; i++ {
- w[i] = wa[i] ^ wb[i]
- }
- i := &big.Int{}
- i.SetBits(w)
- return i
- }()
- },
- }, {
- Name: "Clear",
- Params: []kind{intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- a, b := c.bigInt(0), c.bigInt(1)
- c.ret = func() interface{} {
- wa := a.Bits()
- wb := b.Bits()
- w := append([]big.Word(nil), wa...)
- for i, m := range wb {
- if i >= len(w) {
- break
- }
- w[i] = wa[i] &^ m
- }
- i := &big.Int{}
- i.SetBits(w)
- return i
- }()
- },
- }, {
- Name: "OnesCount",
- Params: []kind{intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x := c.uint64(0)
- c.ret = func() interface{} {
- return bits.OnesCount64(x)
- }()
- },
- }, {
- Name: "RotateLeft",
- Params: []kind{intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x, k := c.uint64(0), c.int(1)
- c.ret = func() interface{} {
- return bits.RotateLeft64(x, k)
- }()
- },
- }, {
- Name: "Reverse",
- Params: []kind{intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x := c.uint64(0)
- c.ret = func() interface{} {
- return bits.Reverse64(x)
- }()
- },
- }, {
- Name: "ReverseBytes",
- Params: []kind{intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x := c.uint64(0)
- c.ret = func() interface{} {
- return bits.ReverseBytes64(x)
- }()
- },
- }, {
- Name: "Len",
- Params: []kind{intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- x := c.uint64(0)
- c.ret = func() interface{} {
- return bits.Len64(x)
- }()
- },
- }},
- "path": []*builtin{{
- Name: "Split",
- Params: []kind{stringKind},
- Result: listKind,
- Func: func(c *callCtxt) {
- path := c.string(0)
- c.ret = func() interface{} {
- file, dir := split(path)
- return []string{file, dir}
- }()
- },
- }, {
- Name: "Match",
- Params: []kind{stringKind, stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- pattern, name := c.string(0), c.string(1)
- c.ret, c.err = func() (interface{}, error) {
- return path.Match(pattern, name)
- }()
- },
- }, {
- Name: "Clean",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- path := c.string(0)
- c.ret = func() interface{} {
- return pathClean(path)
- }()
- },
- }, {
- Name: "Ext",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- path := c.string(0)
- c.ret = func() interface{} {
- return pathExt(path)
- }()
- },
- }, {
- Name: "Base",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- path := c.string(0)
- c.ret = func() interface{} {
- return pathBase(path)
- }()
- },
- }, {
- Name: "IsAbs",
- Params: []kind{stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- path := c.string(0)
- c.ret = func() interface{} {
- return pathIsAbs(path)
- }()
- },
- }, {
- Name: "Dir",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- path := c.string(0)
- c.ret = func() interface{} {
- return pathDir(path)
- }()
- },
- }},
- "regexp": []*builtin{{
- Name: "Match",
- Params: []kind{stringKind, stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- pattern, s := c.string(0), c.string(1)
- c.ret, c.err = func() (interface{}, error) {
- return regexp.MatchString(pattern, s)
- }()
- },
- }, {
- Name: "QuoteMeta",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return regexp.QuoteMeta(s)
- }()
- },
- }},
- "runtime": []*builtin{{
- Name: "Path",
- Params: []kind{},
- Result: stringKind,
- Func: func(c *callCtxt) {
- c.ret = func() interface{} {
- return ""
- }()
- },
- }},
- "strconv": []*builtin{{
- Name: "Unquote",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret, c.err = func() (interface{}, error) {
- return literal.Unquote(s)
- }()
- },
- }, {
- Name: "ParseBool",
- Params: []kind{stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- str := c.string(0)
- c.ret, c.err = func() (interface{}, error) {
- return strconv.ParseBool(str)
- }()
- },
- }, {
- Name: "FormatBool",
- Params: []kind{boolKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- b := c.bool(0)
- c.ret = func() interface{} {
- return strconv.FormatBool(b)
- }()
- },
- }, {
- Name: "ParseFloat",
- Params: []kind{stringKind, intKind},
- Result: numKind,
- Func: func(c *callCtxt) {
- s, bitSize := c.string(0), c.int(1)
- c.ret, c.err = func() (interface{}, error) {
- return strconv.ParseFloat(s, bitSize)
- }()
- },
- }, {
- Name: "IntSize",
- Const: "64",
- }, {
- Name: "ParseUint",
- Params: []kind{stringKind, intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s, base, bitSize := c.string(0), c.int(1), c.int(2)
- c.ret, c.err = func() (interface{}, error) {
- return strconv.ParseUint(s, base, bitSize)
- }()
- },
- }, {
- Name: "ParseInt",
- Params: []kind{stringKind, intKind, intKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s, base, bitSize := c.string(0), c.int(1), c.int(2)
- c.ret, c.err = func() (interface{}, error) {
- return strconv.ParseInt(s, base, bitSize)
- }()
- },
- }, {
- Name: "Atoi",
- Params: []kind{stringKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret, c.err = func() (interface{}, error) {
- return strconv.Atoi(s)
- }()
- },
- }, {
- Name: "FormatFloat",
- Params: []kind{numKind, intKind, intKind, intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- f, fmt, prec, bitSize := c.float64(0), c.byte(1), c.int(2), c.int(3)
- c.ret = func() interface{} {
- return strconv.FormatFloat(f, fmt, prec, bitSize)
- }()
- },
- }, {
- Name: "FormatUint",
- Params: []kind{intKind, intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- i, base := c.uint64(0), c.int(1)
- c.ret = func() interface{} {
- return strconv.FormatUint(i, base)
- }()
- },
- }, {
- Name: "FormatInt",
- Params: []kind{intKind, intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- i, base := c.int64(0), c.int(1)
- c.ret = func() interface{} {
- return strconv.FormatInt(i, base)
- }()
- },
- }, {
- Name: "Quote",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strconv.Quote(s)
- }()
- },
- }, {
- Name: "QuoteToASCII",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strconv.QuoteToASCII(s)
- }()
- },
- }, {
- Name: "QuoteToGraphic",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strconv.QuoteToGraphic(s)
- }()
- },
- }, {
- Name: "QuoteRune",
- Params: []kind{intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- r := c.rune(0)
- c.ret = func() interface{} {
- return strconv.QuoteRune(r)
- }()
- },
- }, {
- Name: "QuoteRuneToASCII",
- Params: []kind{intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- r := c.rune(0)
- c.ret = func() interface{} {
- return strconv.QuoteRuneToASCII(r)
- }()
- },
- }, {
- Name: "QuoteRuneToGraphic",
- Params: []kind{intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- r := c.rune(0)
- c.ret = func() interface{} {
- return strconv.QuoteRuneToGraphic(r)
- }()
- },
- }, {
- Name: "CanBackquote",
- Params: []kind{stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strconv.CanBackquote(s)
- }()
- },
- }, {
- Name: "IsPrint",
- Params: []kind{intKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- r := c.rune(0)
- c.ret = func() interface{} {
- return strconv.IsPrint(r)
- }()
- },
- }, {
- Name: "IsGraphic",
- Params: []kind{intKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- r := c.rune(0)
- c.ret = func() interface{} {
- return strconv.IsGraphic(r)
- }()
- },
- }},
- "strings": []*builtin{{
- Name: "ToTitle",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
-
- prev := ' '
- return strings.Map(
- func(r rune) rune {
- if unicode.IsSpace(prev) {
- prev = r
- return unicode.ToTitle(r)
- }
- prev = r
- return r
- },
- s)
- }()
- },
- }, {
- Name: "ToCamel",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
-
- prev := ' '
- return strings.Map(
- func(r rune) rune {
- if unicode.IsSpace(prev) {
- prev = r
- return unicode.ToLower(r)
- }
- prev = r
- return r
- },
- s)
- }()
- },
- }, {
- Name: "Compare",
- Params: []kind{stringKind, stringKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- a, b := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.Compare(a, b)
- }()
- },
- }, {
- Name: "Count",
- Params: []kind{stringKind, stringKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s, substr := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.Count(s, substr)
- }()
- },
- }, {
- Name: "Contains",
- Params: []kind{stringKind, stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- s, substr := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.Contains(s, substr)
- }()
- },
- }, {
- Name: "ContainsAny",
- Params: []kind{stringKind, stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- s, chars := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.ContainsAny(s, chars)
- }()
- },
- }, {
- Name: "LastIndex",
- Params: []kind{stringKind, stringKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s, substr := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.LastIndex(s, substr)
- }()
- },
- }, {
- Name: "IndexAny",
- Params: []kind{stringKind, stringKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s, chars := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.IndexAny(s, chars)
- }()
- },
- }, {
- Name: "LastIndexAny",
- Params: []kind{stringKind, stringKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s, chars := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.LastIndexAny(s, chars)
- }()
- },
- }, {
- Name: "SplitN",
- Params: []kind{stringKind, stringKind, intKind},
- Result: listKind,
- Func: func(c *callCtxt) {
- s, sep, n := c.string(0), c.string(1), c.int(2)
- c.ret = func() interface{} {
- return strings.SplitN(s, sep, n)
- }()
- },
- }, {
- Name: "SplitAfterN",
- Params: []kind{stringKind, stringKind, intKind},
- Result: listKind,
- Func: func(c *callCtxt) {
- s, sep, n := c.string(0), c.string(1), c.int(2)
- c.ret = func() interface{} {
- return strings.SplitAfterN(s, sep, n)
- }()
- },
- }, {
- Name: "Split",
- Params: []kind{stringKind, stringKind},
- Result: listKind,
- Func: func(c *callCtxt) {
- s, sep := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.Split(s, sep)
- }()
- },
- }, {
- Name: "SplitAfter",
- Params: []kind{stringKind, stringKind},
- Result: listKind,
- Func: func(c *callCtxt) {
- s, sep := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.SplitAfter(s, sep)
- }()
- },
- }, {
- Name: "Fields",
- Params: []kind{stringKind},
- Result: listKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strings.Fields(s)
- }()
- },
- }, {
- Name: "Join",
- Params: []kind{listKind, stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- a, sep := c.strList(0), c.string(1)
- if c.do() {
+var builtinPackages = map[string]*builtinPkg{
+ "": &builtinPkg{
+ native: []*builtin{{}},
+ },
+ "crypto/md5": &builtinPkg{
+ native: []*builtin{{
+ Name: "Size",
+ Const: "16",
+ }, {
+ Name: "BlockSize",
+ Const: "64",
+ }, {
+ Name: "Sum",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
c.ret = func() interface{} {
- return strings.Join(a, sep)
+ return md5.Sum(data)
}()
- }
- },
- }, {
- Name: "HasPrefix",
- Params: []kind{stringKind, stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- s, prefix := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.HasPrefix(s, prefix)
- }()
- },
- }, {
- Name: "HasSuffix",
- Params: []kind{stringKind, stringKind},
- Result: boolKind,
- Func: func(c *callCtxt) {
- s, suffix := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.HasSuffix(s, suffix)
- }()
- },
- }, {
- Name: "Repeat",
- Params: []kind{stringKind, intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s, count := c.string(0), c.int(1)
- c.ret = func() interface{} {
- return strings.Repeat(s, count)
- }()
- },
- }, {
- Name: "ToUpper",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strings.ToUpper(s)
- }()
- },
- }, {
- Name: "ToLower",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strings.ToLower(s)
- }()
- },
- }, {
- Name: "Trim",
- Params: []kind{stringKind, stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s, cutset := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.Trim(s, cutset)
- }()
- },
- }, {
- Name: "TrimLeft",
- Params: []kind{stringKind, stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s, cutset := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.TrimLeft(s, cutset)
- }()
- },
- }, {
- Name: "TrimRight",
- Params: []kind{stringKind, stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s, cutset := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.TrimRight(s, cutset)
- }()
- },
- }, {
- Name: "TrimSpace",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return strings.TrimSpace(s)
- }()
- },
- }, {
- Name: "TrimPrefix",
- Params: []kind{stringKind, stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s, prefix := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.TrimPrefix(s, prefix)
- }()
- },
- }, {
- Name: "TrimSuffix",
- Params: []kind{stringKind, stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s, suffix := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.TrimSuffix(s, suffix)
- }()
- },
- }, {
- Name: "Replace",
- Params: []kind{stringKind, stringKind, stringKind, intKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s, old, new, n := c.string(0), c.string(1), c.string(2), c.int(3)
- c.ret = func() interface{} {
- return strings.Replace(s, old, new, n)
- }()
- },
- }, {
- Name: "Index",
- Params: []kind{stringKind, stringKind},
- Result: intKind,
- Func: func(c *callCtxt) {
- s, substr := c.string(0), c.string(1)
- c.ret = func() interface{} {
- return strings.Index(s, substr)
- }()
- },
- }},
- "text/tabwriter": []*builtin{{
- Name: "Write",
- Params: []kind{topKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- data := c.value(0)
- c.ret, c.err = func() (interface{}, error) {
- buf := &bytes.Buffer{}
- tw := tabwriter.NewWriter(buf, 0, 4, 1, ' ', 0)
- b, err := data.Bytes()
- if err != nil {
- return "", err
+ },
+ }},
+ },
+ "crypto/sha1": &builtinPkg{
+ native: []*builtin{{
+ Name: "Size",
+ Const: "20",
+ }, {
+ Name: "BlockSize",
+ Const: "64",
+ }, {
+ Name: "Sum",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return sha1.Sum(data)
+ }()
+ },
+ }},
+ },
+ "crypto/sha256": &builtinPkg{
+ native: []*builtin{{
+ Name: "Size",
+ Const: "32",
+ }, {
+ Name: "Size224",
+ Const: "28",
+ }, {
+ Name: "BlockSize",
+ Const: "64",
+ }, {
+ Name: "Sum256",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return sha256.Sum256(data)
+ }()
+ },
+ }, {
+ Name: "Sum224",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return sha256.Sum224(data)
+ }()
+ },
+ }},
+ },
+ "crypto/sha512": &builtinPkg{
+ native: []*builtin{{
+ Name: "Size",
+ Const: "64",
+ }, {
+ Name: "Size224",
+ Const: "28",
+ }, {
+ Name: "Size256",
+ Const: "32",
+ }, {
+ Name: "Size384",
+ Const: "48",
+ }, {
+ Name: "BlockSize",
+ Const: "128",
+ }, {
+ Name: "Sum512",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return sha512.Sum512(data)
+ }()
+ },
+ }, {
+ Name: "Sum384",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return sha512.Sum384(data)
+ }()
+ },
+ }, {
+ Name: "Sum512_224",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return sha512.Sum512_224(data)
+ }()
+ },
+ }, {
+ Name: "Sum512_256",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return sha512.Sum512_256(data)
+ }()
+ },
+ }},
+ },
+ "encoding/csv": &builtinPkg{
+ native: []*builtin{{
+ Name: "Encode",
+ Params: []kind{topKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ x := c.value(0)
+ c.ret, c.err = func() (interface{}, error) {
+ buf := &bytes.Buffer{}
+ w := csv.NewWriter(buf)
+ iter, err := x.List()
+ if err != nil {
+ return "", err
+ }
+ for iter.Next() {
+ row, err := iter.Value().List()
+ if err != nil {
+ return "", err
+ }
+ a := []string{}
+ for row.Next() {
+ col := row.Value()
+ if str, err := col.String(); err == nil {
+ a = append(a, str)
+ } else {
+ b, err := col.MarshalJSON()
+ if err != nil {
+ return "", err
+ }
+ a = append(a, string(b))
+ }
+ }
+ w.Write(a)
+ }
+ w.Flush()
+ return buf.String(), nil
+ }()
+ },
+ }, {
+ Name: "Decode",
+ Params: []kind{stringKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ r := c.reader(0)
+ c.ret, c.err = func() (interface{}, error) {
+ return csv.NewReader(r).ReadAll()
+ }()
+ },
+ }},
+ },
+ "encoding/hex": &builtinPkg{
+ native: []*builtin{{
+ Name: "EncodedLen",
+ Params: []kind{intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ n := c.int(0)
+ c.ret = func() interface{} {
+ return hex.EncodedLen(n)
+ }()
+ },
+ }, {
+ Name: "DecodedLen",
+ Params: []kind{intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x := c.int(0)
+ c.ret = func() interface{} {
+ return hex.DecodedLen(x)
+ }()
+ },
+ }, {
+ Name: "Decode",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret, c.err = func() (interface{}, error) {
+ return hex.DecodeString(s)
+ }()
+ },
+ }, {
+ Name: "Dump",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return hex.Dump(data)
+ }()
+ },
+ }, {
+ Name: "Encode",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ src := c.bytes(0)
+ c.ret = func() interface{} {
+ return hex.EncodeToString(src)
+ }()
+ },
+ }},
+ },
+ "encoding/json": &builtinPkg{
+ native: []*builtin{{
+ Name: "Valid",
+ Params: []kind{stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret = func() interface{} {
+ return json.Valid(data)
+ }()
+ },
+ }, {
+ Name: "Compact",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ src := c.bytes(0)
+ c.ret, c.err = func() (interface{}, error) {
+ dst := bytes.Buffer{}
+ if err := json.Compact(&dst, src); err != nil {
+ return "", err
+ }
+ return dst.String(), nil
+ }()
+ },
+ }, {
+ Name: "Indent",
+ Params: []kind{stringKind, stringKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ src, prefix, indent := c.bytes(0), c.string(1), c.string(2)
+ c.ret, c.err = func() (interface{}, error) {
+ dst := bytes.Buffer{}
+ if err := json.Indent(&dst, src, prefix, indent); err != nil {
+ return "", err
+ }
+ return dst.String(), nil
+ }()
+ },
+ }, {
+ Name: "HTMLEscape",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ src := c.bytes(0)
+ c.ret = func() interface{} {
+ dst := &bytes.Buffer{}
+ json.HTMLEscape(dst, src)
+ return dst.String()
+ }()
+ },
+ }, {
+ Name: "Marshal",
+ Params: []kind{topKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ v := c.value(0)
+ c.ret, c.err = func() (interface{}, error) {
+ b, err := json.Marshal(v)
+ return string(b), err
+ }()
+ },
+ }, {
+ Name: "MarshalStream",
+ Params: []kind{topKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ v := c.value(0)
+ c.ret, c.err = func() (interface{}, error) {
+
+ iter, err := v.List()
+ if err != nil {
+ return "", err
+ }
+ buf := &bytes.Buffer{}
+ for iter.Next() {
+ b, err := json.Marshal(iter.Value())
+ if err != nil {
+ return "", err
+ }
+ buf.Write(b)
+ buf.WriteByte('\n')
+ }
+ return buf.String(), nil
+ }()
+ },
+ }, {
+ Name: "Unmarshal",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ b := c.bytes(0)
+ c.ret, c.err = func() (interface{}, error) {
+ if !json.Valid(b) {
+ return nil, fmt.Errorf("json: invalid JSON")
+ }
+ fset := token.NewFileSet()
+ expr, err := parser.ParseExpr(fset, "json", b)
+ if err != nil {
+
+ return nil, fmt.Errorf("json: could not parse JSON: %v", err)
+ }
+ return expr, nil
+ }()
+ },
+ }},
+ },
+ "encoding/yaml": &builtinPkg{
+ native: []*builtin{{
+ Name: "Marshal",
+ Params: []kind{topKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ v := c.value(0)
+ c.ret, c.err = func() (interface{}, error) {
+ b, err := goyaml.Marshal(v)
+ return string(b), err
+ }()
+ },
+ }, {
+ Name: "MarshalStream",
+ Params: []kind{topKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ v := c.value(0)
+ c.ret, c.err = func() (interface{}, error) {
+
+ iter, err := v.List()
+ if err != nil {
+ return "", err
+ }
+ buf := &bytes.Buffer{}
+ for i := 0; iter.Next(); i++ {
+ if i > 0 {
+ buf.WriteString("---\n")
+ }
+ b, err := goyaml.Marshal(iter.Value())
+ if err != nil {
+ return "", err
+ }
+ buf.Write(b)
+ }
+ return buf.String(), nil
+ }()
+ },
+ }, {
+ Name: "Unmarshal",
+ Params: []kind{stringKind},
+ Result: topKind,
+ Func: func(c *callCtxt) {
+ data := c.bytes(0)
+ c.ret, c.err = func() (interface{}, error) {
+ fset := token.NewFileSet()
+ return yaml.Unmarshal(fset, "", data)
+ }()
+ },
+ }},
+ },
+ "html": &builtinPkg{
+ native: []*builtin{{
+ Name: "Escape",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return html.EscapeString(s)
+ }()
+ },
+ }, {
+ Name: "Unescape",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return html.UnescapeString(s)
+ }()
+ },
+ }},
+ },
+ "list": &builtinPkg{
+ native: []*builtin{{}},
+ },
+ "math": &builtinPkg{
+ native: []*builtin{{
+ Name: "MaxExp",
+ Const: "2147483647",
+ }, {
+ Name: "MinExp",
+ Const: "-2147483648",
+ }, {
+ Name: "MaxPrec",
+ Const: "4294967295",
+ }, {
+ Name: "ToNearestEven",
+ Const: "0",
+ }, {
+ Name: "ToNearestAway",
+ Const: "1",
+ }, {
+ Name: "ToZero",
+ Const: "2",
+ }, {
+ Name: "AwayFromZero",
+ Const: "3",
+ }, {
+ Name: "ToNegativeInf",
+ Const: "4",
+ }, {
+ Name: "ToPositiveInf",
+ Const: "5",
+ }, {
+ Name: "Below",
+ Const: "-1",
+ }, {
+ Name: "Exact",
+ Const: "0",
+ }, {
+ Name: "Above",
+ Const: "1",
+ }, {
+ Name: "Jacobi",
+ Params: []kind{intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x, y := c.bigInt(0), c.bigInt(1)
+ c.ret = func() interface{} {
+ return big.Jacobi(x, y)
+ }()
+ },
+ }, {
+ Name: "MaxBase",
+ Const: "62",
+ }, {
+ Name: "Floor",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Floor(x)
+ }()
+ },
+ }, {
+ Name: "Ceil",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Ceil(x)
+ }()
+ },
+ }, {
+ Name: "Trunc",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Trunc(x)
+ }()
+ },
+ }, {
+ Name: "Round",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Round(x)
+ }()
+ },
+ }, {
+ Name: "RoundToEven",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.RoundToEven(x)
+ }()
+ },
+ }, {
+ Name: "Abs",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Abs(x)
+ }()
+ },
+ }, {
+ Name: "Acosh",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Acosh(x)
+ }()
+ },
+ }, {
+ Name: "Asin",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Asin(x)
+ }()
+ },
+ }, {
+ Name: "Acos",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Acos(x)
+ }()
+ },
+ }, {
+ Name: "Asinh",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Asinh(x)
+ }()
+ },
+ }, {
+ Name: "Atan",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Atan(x)
+ }()
+ },
+ }, {
+ Name: "Atan2",
+ Params: []kind{numKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ y, x := c.float64(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Atan2(y, x)
+ }()
+ },
+ }, {
+ Name: "Atanh",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Atanh(x)
+ }()
+ },
+ }, {
+ Name: "Cbrt",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Cbrt(x)
+ }()
+ },
+ }, {
+ Name: "E",
+ Const: "2.71828182845904523536028747135266249775724709369995957496696763",
+ }, {
+ Name: "Pi",
+ Const: "3.14159265358979323846264338327950288419716939937510582097494459",
+ }, {
+ Name: "Phi",
+ Const: "1.61803398874989484820458683436563811772030917980576286213544861",
+ }, {
+ Name: "Sqrt2",
+ Const: "1.41421356237309504880168872420969807856967187537694807317667974",
+ }, {
+ Name: "SqrtE",
+ Const: "1.64872127070012814684865078781416357165377610071014801157507931",
+ }, {
+ Name: "SqrtPi",
+ Const: "1.77245385090551602729816748334114518279754945612238712821380779",
+ }, {
+ Name: "SqrtPhi",
+ Const: "1.27201964951406896425242246173749149171560804184009624861664038",
+ }, {
+ Name: "Ln2",
+ Const: "0.693147180559945309417232121458176568075500134360255254120680009",
+ }, {
+ Name: "Log2E",
+ Const: "1.442695040888963407359924681001892137426645954152985934135449408",
+ }, {
+ Name: "Ln10",
+ Const: "2.3025850929940456840179914546843642076011014886287729760333278",
+ }, {
+ Name: "Log10E",
+ Const: "0.43429448190325182765112891891660508229439700580366656611445378",
+ }, {
+ Name: "Copysign",
+ Params: []kind{numKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x, y := c.float64(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Copysign(x, y)
+ }()
+ },
+ }, {
+ Name: "Dim",
+ Params: []kind{numKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x, y := c.float64(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Dim(x, y)
+ }()
+ },
+ }, {
+ Name: "Erf",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Erf(x)
+ }()
+ },
+ }, {
+ Name: "Erfc",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Erfc(x)
+ }()
+ },
+ }, {
+ Name: "Erfinv",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Erfinv(x)
+ }()
+ },
+ }, {
+ Name: "Erfcinv",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Erfcinv(x)
+ }()
+ },
+ }, {
+ Name: "Exp",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Exp(x)
+ }()
+ },
+ }, {
+ Name: "Exp2",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Exp2(x)
+ }()
+ },
+ }, {
+ Name: "Expm1",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Expm1(x)
+ }()
+ },
+ }, {
+ Name: "Gamma",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Gamma(x)
+ }()
+ },
+ }, {
+ Name: "Hypot",
+ Params: []kind{numKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ p, q := c.float64(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Hypot(p, q)
+ }()
+ },
+ }, {
+ Name: "J0",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.J0(x)
+ }()
+ },
+ }, {
+ Name: "Y0",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Y0(x)
+ }()
+ },
+ }, {
+ Name: "J1",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.J1(x)
+ }()
+ },
+ }, {
+ Name: "Y1",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Y1(x)
+ }()
+ },
+ }, {
+ Name: "Jn",
+ Params: []kind{intKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ n, x := c.int(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Jn(n, x)
+ }()
+ },
+ }, {
+ Name: "Yn",
+ Params: []kind{intKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ n, x := c.int(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Yn(n, x)
+ }()
+ },
+ }, {
+ Name: "Ldexp",
+ Params: []kind{numKind, intKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ frac, exp := c.float64(0), c.int(1)
+ c.ret = func() interface{} {
+ return math.Ldexp(frac, exp)
+ }()
+ },
+ }, {
+ Name: "Log",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Log(x)
+ }()
+ },
+ }, {
+ Name: "Log10",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Log10(x)
+ }()
+ },
+ }, {
+ Name: "Log2",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Log2(x)
+ }()
+ },
+ }, {
+ Name: "Log1p",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Log1p(x)
+ }()
+ },
+ }, {
+ Name: "Logb",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Logb(x)
+ }()
+ },
+ }, {
+ Name: "Ilogb",
+ Params: []kind{numKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Ilogb(x)
+ }()
+ },
+ }, {
+ Name: "Mod",
+ Params: []kind{numKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x, y := c.float64(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Mod(x, y)
+ }()
+ },
+ }, {
+ Name: "Pow",
+ Params: []kind{numKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x, y := c.float64(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Pow(x, y)
+ }()
+ },
+ }, {
+ Name: "Pow10",
+ Params: []kind{intKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ n := c.int(0)
+ c.ret = func() interface{} {
+ return math.Pow10(n)
+ }()
+ },
+ }, {
+ Name: "Remainder",
+ Params: []kind{numKind, numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x, y := c.float64(0), c.float64(1)
+ c.ret = func() interface{} {
+ return math.Remainder(x, y)
+ }()
+ },
+ }, {
+ Name: "Signbit",
+ Params: []kind{numKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Signbit(x)
+ }()
+ },
+ }, {
+ Name: "Cos",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Cos(x)
+ }()
+ },
+ }, {
+ Name: "Sin",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Sin(x)
+ }()
+ },
+ }, {
+ Name: "Sinh",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Sinh(x)
+ }()
+ },
+ }, {
+ Name: "Cosh",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Cosh(x)
+ }()
+ },
+ }, {
+ Name: "Sqrt",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Sqrt(x)
+ }()
+ },
+ }, {
+ Name: "Tan",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Tan(x)
+ }()
+ },
+ }, {
+ Name: "Tanh",
+ Params: []kind{numKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ x := c.float64(0)
+ c.ret = func() interface{} {
+ return math.Tanh(x)
+ }()
+ },
+ }},
+ },
+ "math/bits": &builtinPkg{
+ native: []*builtin{{
+ Name: "And",
+ Params: []kind{intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ a, b := c.bigInt(0), c.bigInt(1)
+ c.ret = func() interface{} {
+ wa := a.Bits()
+ wb := b.Bits()
+ n := len(wa)
+ if len(wb) < n {
+ n = len(wb)
+ }
+ w := make([]big.Word, n)
+ for i := range w {
+ w[i] = wa[i] & wb[i]
+ }
+ i := &big.Int{}
+ i.SetBits(w)
+ return i
+ }()
+ },
+ }, {
+ Name: "Or",
+ Params: []kind{intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ a, b := c.bigInt(0), c.bigInt(1)
+ c.ret = func() interface{} {
+ wa := a.Bits()
+ wb := b.Bits()
+ var w []big.Word
+ n := len(wa)
+ if len(wa) > len(wb) {
+ w = append(w, wa...)
+ n = len(wb)
+ } else {
+ w = append(w, wb...)
+ }
+ for i := 0; i < n; i++ {
+ w[i] = wa[i] | wb[i]
+ }
+ i := &big.Int{}
+ i.SetBits(w)
+ return i
+ }()
+ },
+ }, {
+ Name: "Xor",
+ Params: []kind{intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ a, b := c.bigInt(0), c.bigInt(1)
+ c.ret = func() interface{} {
+ wa := a.Bits()
+ wb := b.Bits()
+ var w []big.Word
+ n := len(wa)
+ if len(wa) > len(wb) {
+ w = append(w, wa...)
+ n = len(wb)
+ } else {
+ w = append(w, wb...)
+ }
+ for i := 0; i < n; i++ {
+ w[i] = wa[i] ^ wb[i]
+ }
+ i := &big.Int{}
+ i.SetBits(w)
+ return i
+ }()
+ },
+ }, {
+ Name: "Clear",
+ Params: []kind{intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ a, b := c.bigInt(0), c.bigInt(1)
+ c.ret = func() interface{} {
+ wa := a.Bits()
+ wb := b.Bits()
+ w := append([]big.Word(nil), wa...)
+ for i, m := range wb {
+ if i >= len(w) {
+ break
+ }
+ w[i] = wa[i] &^ m
+ }
+ i := &big.Int{}
+ i.SetBits(w)
+ return i
+ }()
+ },
+ }, {
+ Name: "OnesCount",
+ Params: []kind{intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x := c.uint64(0)
+ c.ret = func() interface{} {
+ return bits.OnesCount64(x)
+ }()
+ },
+ }, {
+ Name: "RotateLeft",
+ Params: []kind{intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x, k := c.uint64(0), c.int(1)
+ c.ret = func() interface{} {
+ return bits.RotateLeft64(x, k)
+ }()
+ },
+ }, {
+ Name: "Reverse",
+ Params: []kind{intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x := c.uint64(0)
+ c.ret = func() interface{} {
+ return bits.Reverse64(x)
+ }()
+ },
+ }, {
+ Name: "ReverseBytes",
+ Params: []kind{intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x := c.uint64(0)
+ c.ret = func() interface{} {
+ return bits.ReverseBytes64(x)
+ }()
+ },
+ }, {
+ Name: "Len",
+ Params: []kind{intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ x := c.uint64(0)
+ c.ret = func() interface{} {
+ return bits.Len64(x)
+ }()
+ },
+ }},
+ },
+ "path": &builtinPkg{
+ native: []*builtin{{
+ Name: "Split",
+ Params: []kind{stringKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ path := c.string(0)
+ c.ret = func() interface{} {
+ file, dir := split(path)
+ return []string{file, dir}
+ }()
+ },
+ }, {
+ Name: "Match",
+ Params: []kind{stringKind, stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ pattern, name := c.string(0), c.string(1)
+ c.ret, c.err = func() (interface{}, error) {
+ return path.Match(pattern, name)
+ }()
+ },
+ }, {
+ Name: "Clean",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ path := c.string(0)
+ c.ret = func() interface{} {
+ return pathClean(path)
+ }()
+ },
+ }, {
+ Name: "Ext",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ path := c.string(0)
+ c.ret = func() interface{} {
+ return pathExt(path)
+ }()
+ },
+ }, {
+ Name: "Base",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ path := c.string(0)
+ c.ret = func() interface{} {
+ return pathBase(path)
+ }()
+ },
+ }, {
+ Name: "IsAbs",
+ Params: []kind{stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ path := c.string(0)
+ c.ret = func() interface{} {
+ return pathIsAbs(path)
+ }()
+ },
+ }, {
+ Name: "Dir",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ path := c.string(0)
+ c.ret = func() interface{} {
+ return pathDir(path)
+ }()
+ },
+ }},
+ },
+ "regexp": &builtinPkg{
+ native: []*builtin{{
+ Name: "Match",
+ Params: []kind{stringKind, stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ pattern, s := c.string(0), c.string(1)
+ c.ret, c.err = func() (interface{}, error) {
+ return regexp.MatchString(pattern, s)
+ }()
+ },
+ }, {
+ Name: "QuoteMeta",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return regexp.QuoteMeta(s)
+ }()
+ },
+ }},
+ },
+ "runtime": &builtinPkg{
+ native: []*builtin{{
+ Name: "Path",
+ Params: []kind{},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ c.ret = func() interface{} {
+ return ""
+ }()
+ },
+ }},
+ },
+ "strconv": &builtinPkg{
+ native: []*builtin{{
+ Name: "Unquote",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret, c.err = func() (interface{}, error) {
+ return literal.Unquote(s)
+ }()
+ },
+ }, {
+ Name: "ParseBool",
+ Params: []kind{stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ str := c.string(0)
+ c.ret, c.err = func() (interface{}, error) {
+ return strconv.ParseBool(str)
+ }()
+ },
+ }, {
+ Name: "FormatBool",
+ Params: []kind{boolKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ b := c.bool(0)
+ c.ret = func() interface{} {
+ return strconv.FormatBool(b)
+ }()
+ },
+ }, {
+ Name: "ParseFloat",
+ Params: []kind{stringKind, intKind},
+ Result: numKind,
+ Func: func(c *callCtxt) {
+ s, bitSize := c.string(0), c.int(1)
+ c.ret, c.err = func() (interface{}, error) {
+ return strconv.ParseFloat(s, bitSize)
+ }()
+ },
+ }, {
+ Name: "IntSize",
+ Const: "64",
+ }, {
+ Name: "ParseUint",
+ Params: []kind{stringKind, intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s, base, bitSize := c.string(0), c.int(1), c.int(2)
+ c.ret, c.err = func() (interface{}, error) {
+ return strconv.ParseUint(s, base, bitSize)
+ }()
+ },
+ }, {
+ Name: "ParseInt",
+ Params: []kind{stringKind, intKind, intKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s, base, bitSize := c.string(0), c.int(1), c.int(2)
+ c.ret, c.err = func() (interface{}, error) {
+ return strconv.ParseInt(s, base, bitSize)
+ }()
+ },
+ }, {
+ Name: "Atoi",
+ Params: []kind{stringKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret, c.err = func() (interface{}, error) {
+ return strconv.Atoi(s)
+ }()
+ },
+ }, {
+ Name: "FormatFloat",
+ Params: []kind{numKind, intKind, intKind, intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ f, fmt, prec, bitSize := c.float64(0), c.byte(1), c.int(2), c.int(3)
+ c.ret = func() interface{} {
+ return strconv.FormatFloat(f, fmt, prec, bitSize)
+ }()
+ },
+ }, {
+ Name: "FormatUint",
+ Params: []kind{intKind, intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ i, base := c.uint64(0), c.int(1)
+ c.ret = func() interface{} {
+ return strconv.FormatUint(i, base)
+ }()
+ },
+ }, {
+ Name: "FormatInt",
+ Params: []kind{intKind, intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ i, base := c.int64(0), c.int(1)
+ c.ret = func() interface{} {
+ return strconv.FormatInt(i, base)
+ }()
+ },
+ }, {
+ Name: "Quote",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strconv.Quote(s)
+ }()
+ },
+ }, {
+ Name: "QuoteToASCII",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strconv.QuoteToASCII(s)
+ }()
+ },
+ }, {
+ Name: "QuoteToGraphic",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strconv.QuoteToGraphic(s)
+ }()
+ },
+ }, {
+ Name: "QuoteRune",
+ Params: []kind{intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ r := c.rune(0)
+ c.ret = func() interface{} {
+ return strconv.QuoteRune(r)
+ }()
+ },
+ }, {
+ Name: "QuoteRuneToASCII",
+ Params: []kind{intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ r := c.rune(0)
+ c.ret = func() interface{} {
+ return strconv.QuoteRuneToASCII(r)
+ }()
+ },
+ }, {
+ Name: "QuoteRuneToGraphic",
+ Params: []kind{intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ r := c.rune(0)
+ c.ret = func() interface{} {
+ return strconv.QuoteRuneToGraphic(r)
+ }()
+ },
+ }, {
+ Name: "CanBackquote",
+ Params: []kind{stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strconv.CanBackquote(s)
+ }()
+ },
+ }, {
+ Name: "IsPrint",
+ Params: []kind{intKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ r := c.rune(0)
+ c.ret = func() interface{} {
+ return strconv.IsPrint(r)
+ }()
+ },
+ }, {
+ Name: "IsGraphic",
+ Params: []kind{intKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ r := c.rune(0)
+ c.ret = func() interface{} {
+ return strconv.IsGraphic(r)
+ }()
+ },
+ }},
+ },
+ "strings": &builtinPkg{
+ native: []*builtin{{
+ Name: "ToTitle",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+
+ prev := ' '
+ return strings.Map(
+ func(r rune) rune {
+ if unicode.IsSpace(prev) {
+ prev = r
+ return unicode.ToTitle(r)
+ }
+ prev = r
+ return r
+ },
+ s)
+ }()
+ },
+ }, {
+ Name: "ToCamel",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+
+ prev := ' '
+ return strings.Map(
+ func(r rune) rune {
+ if unicode.IsSpace(prev) {
+ prev = r
+ return unicode.ToLower(r)
+ }
+ prev = r
+ return r
+ },
+ s)
+ }()
+ },
+ }, {
+ Name: "Compare",
+ Params: []kind{stringKind, stringKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ a, b := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.Compare(a, b)
+ }()
+ },
+ }, {
+ Name: "Count",
+ Params: []kind{stringKind, stringKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s, substr := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.Count(s, substr)
+ }()
+ },
+ }, {
+ Name: "Contains",
+ Params: []kind{stringKind, stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ s, substr := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.Contains(s, substr)
+ }()
+ },
+ }, {
+ Name: "ContainsAny",
+ Params: []kind{stringKind, stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ s, chars := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.ContainsAny(s, chars)
+ }()
+ },
+ }, {
+ Name: "LastIndex",
+ Params: []kind{stringKind, stringKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s, substr := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.LastIndex(s, substr)
+ }()
+ },
+ }, {
+ Name: "IndexAny",
+ Params: []kind{stringKind, stringKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s, chars := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.IndexAny(s, chars)
+ }()
+ },
+ }, {
+ Name: "LastIndexAny",
+ Params: []kind{stringKind, stringKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s, chars := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.LastIndexAny(s, chars)
+ }()
+ },
+ }, {
+ Name: "SplitN",
+ Params: []kind{stringKind, stringKind, intKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ s, sep, n := c.string(0), c.string(1), c.int(2)
+ c.ret = func() interface{} {
+ return strings.SplitN(s, sep, n)
+ }()
+ },
+ }, {
+ Name: "SplitAfterN",
+ Params: []kind{stringKind, stringKind, intKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ s, sep, n := c.string(0), c.string(1), c.int(2)
+ c.ret = func() interface{} {
+ return strings.SplitAfterN(s, sep, n)
+ }()
+ },
+ }, {
+ Name: "Split",
+ Params: []kind{stringKind, stringKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ s, sep := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.Split(s, sep)
+ }()
+ },
+ }, {
+ Name: "SplitAfter",
+ Params: []kind{stringKind, stringKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ s, sep := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.SplitAfter(s, sep)
+ }()
+ },
+ }, {
+ Name: "Fields",
+ Params: []kind{stringKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strings.Fields(s)
+ }()
+ },
+ }, {
+ Name: "Join",
+ Params: []kind{listKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ a, sep := c.strList(0), c.string(1)
+ if c.do() {
+ c.ret = func() interface{} {
+ return strings.Join(a, sep)
+ }()
}
- _, err = tw.Write(b)
- if err != nil {
- return "", err
- }
- return buf.String(), err
- }()
- },
- }},
- "text/template": []*builtin{{
- Name: "Execute",
- Params: []kind{stringKind, topKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- templ, data := c.string(0), c.value(1)
- c.ret, c.err = func() (interface{}, error) {
- t, err := template.New("").Parse(templ)
- if err != nil {
- return "", err
- }
- buf := &bytes.Buffer{}
- if err := t.Execute(buf, data); err != nil {
- return "", err
- }
- return buf.String(), nil
- }()
- },
- }, {
- Name: "HTMLEscape",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return template.HTMLEscapeString(s)
- }()
- },
- }, {
- Name: "JSEscape",
- Params: []kind{stringKind},
- Result: stringKind,
- Func: func(c *callCtxt) {
- s := c.string(0)
- c.ret = func() interface{} {
- return template.JSEscapeString(s)
- }()
- },
- }},
+ },
+ }, {
+ Name: "HasPrefix",
+ Params: []kind{stringKind, stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ s, prefix := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.HasPrefix(s, prefix)
+ }()
+ },
+ }, {
+ Name: "HasSuffix",
+ Params: []kind{stringKind, stringKind},
+ Result: boolKind,
+ Func: func(c *callCtxt) {
+ s, suffix := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.HasSuffix(s, suffix)
+ }()
+ },
+ }, {
+ Name: "Repeat",
+ Params: []kind{stringKind, intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s, count := c.string(0), c.int(1)
+ c.ret = func() interface{} {
+ return strings.Repeat(s, count)
+ }()
+ },
+ }, {
+ Name: "ToUpper",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strings.ToUpper(s)
+ }()
+ },
+ }, {
+ Name: "ToLower",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strings.ToLower(s)
+ }()
+ },
+ }, {
+ Name: "Trim",
+ Params: []kind{stringKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s, cutset := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.Trim(s, cutset)
+ }()
+ },
+ }, {
+ Name: "TrimLeft",
+ Params: []kind{stringKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s, cutset := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.TrimLeft(s, cutset)
+ }()
+ },
+ }, {
+ Name: "TrimRight",
+ Params: []kind{stringKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s, cutset := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.TrimRight(s, cutset)
+ }()
+ },
+ }, {
+ Name: "TrimSpace",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return strings.TrimSpace(s)
+ }()
+ },
+ }, {
+ Name: "TrimPrefix",
+ Params: []kind{stringKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s, prefix := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.TrimPrefix(s, prefix)
+ }()
+ },
+ }, {
+ Name: "TrimSuffix",
+ Params: []kind{stringKind, stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s, suffix := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.TrimSuffix(s, suffix)
+ }()
+ },
+ }, {
+ Name: "Replace",
+ Params: []kind{stringKind, stringKind, stringKind, intKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s, old, new, n := c.string(0), c.string(1), c.string(2), c.int(3)
+ c.ret = func() interface{} {
+ return strings.Replace(s, old, new, n)
+ }()
+ },
+ }, {
+ Name: "Index",
+ Params: []kind{stringKind, stringKind},
+ Result: intKind,
+ Func: func(c *callCtxt) {
+ s, substr := c.string(0), c.string(1)
+ c.ret = func() interface{} {
+ return strings.Index(s, substr)
+ }()
+ },
+ }},
+ },
+ "text/tabwriter": &builtinPkg{
+ native: []*builtin{{
+ Name: "Write",
+ Params: []kind{topKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ data := c.value(0)
+ c.ret, c.err = func() (interface{}, error) {
+ buf := &bytes.Buffer{}
+ tw := tabwriter.NewWriter(buf, 0, 4, 1, ' ', 0)
+ b, err := data.Bytes()
+ if err != nil {
+ return "", err
+ }
+ _, err = tw.Write(b)
+ if err != nil {
+ return "", err
+ }
+ return buf.String(), err
+ }()
+ },
+ }},
+ },
+ "text/template": &builtinPkg{
+ native: []*builtin{{
+ Name: "Execute",
+ Params: []kind{stringKind, topKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ templ, data := c.string(0), c.value(1)
+ c.ret, c.err = func() (interface{}, error) {
+ t, err := template.New("").Parse(templ)
+ if err != nil {
+ return "", err
+ }
+ buf := &bytes.Buffer{}
+ if err := t.Execute(buf, data); err != nil {
+ return "", err
+ }
+ return buf.String(), nil
+ }()
+ },
+ }, {
+ Name: "HTMLEscape",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return template.HTMLEscapeString(s)
+ }()
+ },
+ }, {
+ Name: "JSEscape",
+ Params: []kind{stringKind},
+ Result: stringKind,
+ Func: func(c *callCtxt) {
+ s := c.string(0)
+ c.ret = func() interface{} {
+ return template.JSEscapeString(s)
+ }()
+ },
+ }},
+ },
+ "time": &builtinPkg{
+ native: []*builtin{{}},
+ cue: `{
+ Time: null | =~"^\("\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\\d|3[0-1])")T\("([0-1]\\d|2[0-3]):[0-5]\\d:[0-5]\\d")\("(.\\d{1,10})?")\("(Z|(-|\\+)\\d\\d:\\d\\d)")$"
+}`,
+ },
}
diff --git a/cue/gen.go b/cue/gen.go
index 3dd656a..683ea44 100644
--- a/cue/gen.go
+++ b/cue/gen.go
@@ -36,6 +36,11 @@
"sort"
"strconv"
"strings"
+
+ "cuelang.org/go/cue"
+ cueformat "cuelang.org/go/cue/format"
+ "cuelang.org/go/cue/load"
+ cuetoken "cuelang.org/go/cue/token"
)
const prefix = "../pkg/"
@@ -63,9 +68,10 @@
w: &bytes.Buffer{},
decls: &bytes.Buffer{},
fset: token.NewFileSet(),
+ cfset: cuetoken.NewFileSet(),
}
- fmt.Fprintln(g.w, "var builtinPackages = map[string][]*builtin{")
+ fmt.Fprintln(g.w, "var builtinPackages = map[string]*builtinPkg{")
filepath.Walk(prefix, func(dir string, info os.FileInfo, err error) error {
if err != nil {
log.Fatal(err)
@@ -131,6 +137,7 @@
w *bytes.Buffer
decls *bytes.Buffer
fset *token.FileSet
+ cfset *cuetoken.FileSet
defaultPkg string
first bool
iota int
@@ -139,20 +146,29 @@
}
func (g *generator) processDir(dir string) {
- args, err := filepath.Glob(filepath.Join(dir, "*.go"))
+ goFiles, err := filepath.Glob(filepath.Join(dir, "*.go"))
if err != nil {
log.Fatal(err)
}
- if len(args) == 0 {
+
+ cueFiles, err := filepath.Glob(filepath.Join(dir, "*.cue"))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if len(goFiles)+len(cueFiles) == 0 {
return
}
+
pkg := dir[len(prefix):]
- fmt.Fprintf(g.w, "%q: []*builtin{{\n", pkg)
- defer fmt.Fprintf(g.w, "}},\n")
+ fmt.Fprintf(g.w, "%q: &builtinPkg{\nnative: []*builtin{{\n", pkg)
g.first = true
- for _, filename := range args {
- g.process(filename)
+ for _, filename := range goFiles {
+ g.processGo(filename)
}
+ fmt.Fprintf(g.w, "}},\n")
+ g.processCUE(dir)
+ fmt.Fprintf(g.w, "},\n")
}
func (g *generator) sep() {
@@ -174,7 +190,34 @@
return path.Base(pkg)
}
-func (g *generator) process(filename string) {
+// processCUE mixes in CUE definitions defined in the package directory.
+func (g *generator) processCUE(dir string) {
+ instances := cue.Build(load.Instances([]string{dir}, &load.Config{
+ StdRoot: "../pkg",
+ }))
+
+ if err := instances[0].Err; err != nil {
+ if !strings.Contains(err.Error(), "no CUE files") {
+ log.Fatal(err)
+ }
+ return
+ }
+
+ var buf bytes.Buffer
+ if err := cueformat.Node(&buf, instances[0].Value().Syntax()); err != nil {
+ log.Fatal(err)
+ }
+ body := buf.String()
+ body = strings.ReplaceAll(body, "\n\n", "\n")
+ // body = strings.ReplaceAll(body, "\t", "")
+ // TODO: escape backtick
+ fmt.Fprintf(g.w, "cue: `%s`,\n", body)
+}
+
+func (g *generator) processGo(filename string) {
+ if strings.HasSuffix(filename, "_test.go") {
+ return
+ }
f, err := parser.ParseFile(g.fset, filename, nil, parser.ParseComments)
if err != nil {
log.Fatal(err)
@@ -351,6 +394,8 @@
return "bytes"
case "io.Reader":
return "reader"
+ case "time.Time":
+ return "string"
default:
return str
}
diff --git a/cue/load/config.go b/cue/load/config.go
index bf5f398..78444a3 100644
--- a/cue/load/config.go
+++ b/cue/load/config.go
@@ -108,6 +108,10 @@
// to CUE.
DataFiles bool
+ // StdRoot specifies an alternative directory for standard libaries.
+ // This is mostly used for bootstrapping.
+ StdRoot string
+
fileSystem
}
diff --git a/cue/load/import.go b/cue/load/import.go
index 7ad72ee..fc8f6fd 100644
--- a/cue/load/import.go
+++ b/cue/load/import.go
@@ -166,6 +166,9 @@
if !isLocalImport(path) {
// is it a builtin?
if strings.IndexByte(strings.Split(path, "/")[0], '.') == -1 {
+ if l.cfg.StdRoot != "" {
+ return l.importPkg(path, l.cfg.StdRoot)
+ }
return nil
}
if cfg.modRoot == "" {
@@ -207,13 +210,12 @@
p.Dir = ctxt.joinPath(srcDir, path)
}
return nil
- } else {
- dir := ctxt.joinPath(srcDir, path)
- info, err := os.Stat(filepath.Join(srcDir, path))
- if err == nil && info.IsDir() {
- p.Dir = dir
- return nil
- }
+ }
+ dir := ctxt.joinPath(srcDir, path)
+ info, err := os.Stat(filepath.Join(srcDir, path))
+ if err == nil && info.IsDir() {
+ p.Dir = dir
+ return nil
}
// package was not found
diff --git a/pkg/time/time.cue b/pkg/time/time.cue
new file mode 100644
index 0000000..0c69123
--- /dev/null
+++ b/pkg/time/time.cue
@@ -0,0 +1,33 @@
+// Copyright 2019 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package time provides functionality for representing and displaying time.
+//
+// The calendrical calculations always assume a Gregorian calendar, with no leap seconds.
+package time
+
+// A Time represents an instant in time with nanosecond precision as
+// an RFC 3339 string.
+//
+// A time represented in this format can be marshaled into and from
+// a Go time.Time. This means it does not allow the representation of leap
+// seconds.
+Time: null | =~"^\(date)T\(time)\(nano)\(zone)$"
+
+date = #"\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\d|3[0-1])"#
+time = #"([0-1]\d|2[0-3]):[0-5]\d:[0-5]\d"#
+nano = #"(.\d{1,10})?"# // Go parses up to 10 digits.
+zone = #"(Z|(-|\+)\d\d:\d\d)"#
+
+// TODO: correctly constrain days and then leap years/centuries.
diff --git a/pkg/time/time_test.go b/pkg/time/time_test.go
new file mode 100644
index 0000000..11570a0
--- /dev/null
+++ b/pkg/time/time_test.go
@@ -0,0 +1,101 @@
+// Copyright 2019 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package time
+
+import (
+ "encoding/json"
+ "testing"
+ "time"
+
+ "cuelang.org/go/cue"
+ "cuelang.org/go/cue/load"
+ "cuelang.org/go/cue/parser"
+ "cuelang.org/go/cue/token"
+)
+
+func TestTime(t *testing.T) {
+ inst := cue.Build(load.Instances([]string{"."}, nil))[0]
+ if inst.Err != nil {
+ t.Fatal(inst.Err)
+ }
+
+ parseCUE := func(t *testing.T, time string) error {
+ expr, err := parser.ParseExpr(token.NewFileSet(), "test", "Time&"+time)
+ if err != nil {
+ t.Fatal(err)
+ }
+ v := inst.Eval(expr)
+ return v.Err()
+ }
+
+ // Valid go times (for JSON marshaling) are represented as is
+ validTimes := []string{
+ // valid Go times
+ "null",
+ `"2019-01-02T15:04:05Z"`,
+ `"2019-01-02T15:04:05-08:00"`,
+ `"2019-01-02T15:04:05.0-08:00"`,
+ `"2019-01-02T15:04:05.01-08:00"`,
+ `"2019-01-02T15:04:05.0123456789-08:00"`, // Is this a Go bug?
+ `"2019-02-28T15:04:59Z"`,
+
+ // TODO: allow leap seconds? This is allowed by the RFC 3339 spec.
+ // `"2019-06-30T23:59:60Z"`, // leap seconds
+ }
+
+ for _, tc := range validTimes {
+ t.Run(tc, func(t *testing.T) {
+ // Test JSON unmarshaling
+ var tm time.Time
+
+ if err := json.Unmarshal([]byte(tc), &tm); err != nil {
+ t.Errorf("unmarshal JSON failed unexpectedly: %v", err)
+ }
+
+ if err := parseCUE(t, tc); err != nil {
+ t.Errorf("CUE eval failed unexpectedly: %v", err)
+ }
+ })
+ }
+
+ invalidTimes := []string{
+ `"2019-01-02T15:04:05"`, // missing time zone
+ `"2019-01-02T15:04:61Z"`, // seconds out of range
+ `"2019-01-02T15:60:00Z"`, // minute out of range
+ `"2019-01-02T24:00:00Z"`, // hour out of range
+ `"2019-01-32T23:00:00Z"`, // day out of range
+ `"2019-01-00T23:00:00Z"`, // day out of range
+ `"2019-00-15T23:00:00Z"`, // month out of range
+ `"2019-13-15T23:00:00Z"`, // month out of range
+ `"2019-01-02T15:04:05Z+08:00"`, // double time zone
+ `"2019-01-02T15:04:05+08"`, // partial time zone
+ `"2019-01-02T15:04:05.01234567890-08:00"`,
+ }
+
+ for _, tc := range invalidTimes {
+ t.Run(tc, func(t *testing.T) {
+ // Test JSON unmarshaling
+ var tm time.Time
+
+ if err := json.Unmarshal([]byte(tc), &tm); err == nil {
+ t.Errorf("unmarshal JSON succeeded unexpectedly: %v", err)
+ }
+
+ if err := parseCUE(t, tc); err == nil {
+ t.Errorf("CUE eval succeeded unexpectedly: %v", err)
+ }
+ })
+ }
+}