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)
+			}
+		})
+	}
+}