	}

	if id, ok := builtin.Index[node.Name]; ok {
		switch node.Name {
		case "get":
			return v.checkBuiltinGet(node)
		}
		return v.checkFunction(builtin.Builtins[id], node, node.Arguments)
	}

	return v.error(node, "unknown builtin %v", node.Name)
}

func (v *Checker) begin(collectionNature Nature, vars ...varScope) {
	v.predicateScopes = append(v.predicateScopes, predicateScope{
		collection: collectionNature,
		vars:       vars,
	})
}

func (v *Checker) end() {
	v.predicateScopes = v.predicateScopes[:len(v.predicateScopes)-1]
}

func (v *Checker) checkBuiltinGet(node *ast.BuiltinNode) Nature {
	if len(node.Arguments) != 2 {
		return v.error(node, "invalid number of arguments (expected 2, got %d)", len(node.Arguments))
	}

	base := v.visit(node.Arguments[0])
	prop := v.visit(node.Arguments[1])
46:		return "string"
47-	case reflect.Array, reflect.Slice:
48-		return "array"
49-	case reflect.Map:
50-		return "map"
51-	case reflect.Func:
22:		panic(fmt.Sprintf("invalid argument for len (type %T)", x))
32:		return fmt.Sprintf("%s.%s", v.Type().PkgPath(), v.Type().Name())
115:	panic(fmt.Sprintf("invalid argument for abs (type %T)", x))
127:	panic(fmt.Sprintf("invalid argument for ceil (type %T)", x))
139:	panic(fmt.Sprintf("invalid argument for floor (type %T)", x))
151:	panic(fmt.Sprintf("invalid argument for round (type %T)", x))
183:			panic(fmt.Sprintf("invalid operation: int(%s)", x))
191:		panic(fmt.Sprintf("invalid operation: int(%T)", x))
224:			panic(fmt.Sprintf("invalid operation: float(%s)", x))
228:		panic(fmt.Sprintf("invalid operation: float(%T)", x))
