<commit_before>util = require('./util')
err = require('./errors')

# Import some names to this namespace for convienience
ar = util.ar
varar = util.varar
aropt = util.aropt

# rethinkdb is both the main export object for the module
# and a function that shortcuts `r.expr`.
rethinkdb = (args...) -> rethinkdb.expr(args...)

# Utilities

funcWrap = (val) ->
    if val is undefined
        # Pass through the undefined value so it's caught by
        # the appropriate undefined checker
        return val

    val = rethinkdb.expr(val)

    ivarScan = (node) ->
        unless node instanceof TermBase then return false
        if node instanceof ImplicitVar then return true
        if (node.args.map ivarScan).some((a)->a) then return true
        if (v for own k,v of node.optargs).map(ivarScan).some((a)->a) then return true
        return false

    if ivarScan(val)
        return new Func {}, (x) -> val

    return val

# AST classes

class TermBase
    constructor: ->
        self = (ar (field) -> self.getField(field))
        self.__proto__ = @.__proto__
        return self

    run: (connOrOptions, cb) ->
        useOutdated = undefined

        # Parse out run options from connOrOptions object
        if connOrOptions? and connOrOptions.constructor is Object
            for own key of connOrOptions
                unless key in ['connection', 'useOutdated', 'noreply', 'timeFormat']
                    throw new err.RqlDriverError "First argument to `run` must be an open connection or { connection: <connection>, useOutdated: <bool>, noreply: <bool>, timeFormat: <string>}."
            conn = connOrOptions.connection
            opts = connOrOptions
        else
            conn = connOrOptions
            opts = {}

        # This only checks that the argument is of the right type, connection
        # closed errors will be handled elsewhere
        unless conn? and conn._start?
            throw new err.RqlDriverError "First argument to `run` must be an open connection or { connection: <connection>, useOutdated: <bool>, noreply: <bool>, timeFormat: <string>}."

        # We only require a callback if noreply isn't set
        if not opts.noreply and typeof(cb) isnt 'function'
            throw new err.RqlDriverError "Second argument to `run` must be a callback to invoke "+
                                         "with either an error or the result of the query."

        try
            conn._start @, cb, opts
        catch e
            # It was decided that, if we can, we prefer to invoke the callback
            # with any errors rather than throw them as normal exceptions.
            # Thus we catch errors here and invoke the callback instead of
            # letting the error bubble up.
            if typeof(cb) is 'function'
                cb(e)
            else
                throw e

    toString: -> err.printQuery(@)

class RDBVal extends TermBase
    eq: varar(1, null, (others...) -> new Eq {}, @, others...)
    ne: varar(1, null, (others...) -> new Ne {}, @, others...)
    lt: varar(1, null, (others...) -> new Lt {}, @, others...)
    le: varar(1, null, (others...) -> new Le {}, @, others...)
    gt: varar(1, null, (others...) -> new Gt {}, @, others...)
    ge: varar(1, null, (others...) -> new Ge {}, @, others...)

    not: ar () -> new Not {}, @

    add: varar(1, null, (others...) -> new Add {}, @, others...)
    sub: varar(1, null, (others...) -> new Sub {}, @, others...)
    mul: varar(1, null, (others...) -> new Mul {}, @, others...)
    div: varar(1, null, (others...) -> new Div {}, @, others...)
    mod: ar (other) -> new Mod {}, @, other

    append: ar (val) -> new Append {}, @, val
    prepend: ar (val) -> new Prepend {}, @, val
    difference: ar (val) -> new Difference {}, @, val
    setInsert: ar (val) -> new SetInsert {}, @, val
    setUnion: ar (val) -> new SetUnion {}, @, val
    setIntersection: ar (val) -> new SetIntersection {}, @, val
    setDifference: ar (val) -> new SetDifference {}, @, val
    slice: aropt (left, right, opts) -> new Slice opts, @, left, right
    skip: ar (index) -> new Skip {}, @, index
    limit: ar (index) -> new Limit {}, @, index
    getField: ar (field) -> new GetField {}, @, field
    contains: varar(1, null, (fields...) -> new Contains {}, @, fields...)
    insertAt: ar (index, value) -> new InsertAt {}, @, index, value
    spliceAt: ar (index, value) -> new SpliceAt {}, @, index, value
    deleteAt: varar(1, 2, (others...) -> new DeleteAt {}, @, others...)
    changeAt: ar (index, value) -> new ChangeAt {}, @, index, value
    indexesOf: ar (which) -> new IndexesOf {}, @, funcWrap(which)
    hasFields: varar(0, null, (fields...) -> new HasFields {}, @, fields...)
    withFields: varar(0, null, (fields...) -> new WithFields {}, @, fields...)
    keys: ar(-> new Keys {}, @)

    # pluck and without on zero fields are allowed
    pluck: (fields...) -> new Pluck {}, @, fields...
    without: (fields...) -> new Without {}, @, fields...

    merge: ar (other) -> new Merge {}, @, other
    between: aropt (left, right, opts) -> new Between opts, @, left, right
    reduce: varar(1, 2, (func, base) -> new Reduce {base:base}, @, funcWrap(func))
    map: ar (func) -> new Map {}, @, funcWrap(func)
    filter: aropt (predicate, opts) -> new Filter opts, @, funcWrap(predicate)
    concatMap: ar (func) -> new ConcatMap {}, @, funcWrap(func)
    distinct: ar () -> new Distinct {}, @
    count: varar(0, 1, (fun...) -> new Count {}, @, fun...)
    union: varar(1, null, (others...) -> new Union {}, @, others...)
    nth: ar (index) -> new Nth {}, @, index
    match: ar (pattern) -> new Match {}, @, pattern
    isEmpty: ar () -> new IsEmpty {}, @
    groupedMapReduce: varar(3, 4, (group, map, reduce, base) -> new GroupedMapReduce {base:base}, @, funcWrap(group), funcWrap(map), funcWrap(reduce))
    innerJoin: ar (other, predicate) -> new InnerJoin {}, @, other, predicate
    outerJoin: ar (other, predicate) -> new OuterJoin {}, @, other, predicate
    eqJoin: aropt (left_attr, right, opts) -> new EqJoin opts, @, left_attr, right
    zip: ar () -> new Zip {}, @
    coerceTo: ar (type) -> new CoerceTo {}, @, type
    typeOf: ar () -> new TypeOf {}, @
    update: aropt (func, opts) -> new Update opts, @, funcWrap(func)
    delete: aropt (opts) -> new Delete opts, @
    replace: aropt (func, opts) -> new Replace opts, @, funcWrap(func)
    do: ar (func) -> new FunCall {}, funcWrap(func), @
    default: ar (x) -> new Default {}, @, x

    or: varar(1, null, (others...) -> new Any {}, @, others...)
    and: varar(1, null, (others...) -> new All {}, @, others...)

    forEach: ar (func) -> new ForEach {}, @, funcWrap(func)
<commit_msg>contains, count, indexes_of wrapped for JS<commit_after>util = require('./util')
err = require('./errors')

# Import some names to this namespace for convienience
ar = util.ar
varar = util.varar
aropt = util.aropt

# rethinkdb is both the main export object for the module
# and a function that shortcuts `r.expr`.
rethinkdb = (args...) -> rethinkdb.expr(args...)

# Utilities

funcWrap = (val) ->
    if val is undefined
        # Pass through the undefined value so it's caught by
        # the appropriate undefined checker
        return val

    val = rethinkdb.expr(val)

    ivarScan = (node) ->
        unless node instanceof TermBase then return false
        if node instanceof ImplicitVar then return true
        if (node.args.map ivarScan).some((a)->a) then return true
        if (v for own k,v of node.optargs).map(ivarScan).some((a)->a) then return true
        return false

    if ivarScan(val)
        return new Func {}, (x) -> val

    return val

# AST classes

class TermBase
    constructor: ->
        self = (ar (field) -> self.getField(field))
        self.__proto__ = @.__proto__
        return self

    run: (connOrOptions, cb) ->
        useOutdated = undefined

        # Parse out run options from connOrOptions object
        if connOrOptions? and connOrOptions.constructor is Object
            for own key of connOrOptions
                unless key in ['connection', 'useOutdated', 'noreply', 'timeFormat']
                    throw new err.RqlDriverError "First argument to `run` must be an open connection or { connection: <connection>, useOutdated: <bool>, noreply: <bool>, timeFormat: <string>}."
            conn = connOrOptions.connection
            opts = connOrOptions
        else
            conn = connOrOptions
            opts = {}

        # This only checks that the argument is of the right type, connection
        # closed errors will be handled elsewhere
        unless conn? and conn._start?
            throw new err.RqlDriverError "First argument to `run` must be an open connection or { connection: <connection>, useOutdated: <bool>, noreply: <bool>, timeFormat: <string>}."

        # We only require a callback if noreply isn't set
        if not opts.noreply and typeof(cb) isnt 'function'
            throw new err.RqlDriverError "Second argument to `run` must be a callback to invoke "+
                                         "with either an error or the result of the query."

        try
            conn._start @, cb, opts
        catch e
            # It was decided that, if we can, we prefer to invoke the callback
            # with any errors rather than throw them as normal exceptions.
            # Thus we catch errors here and invoke the callback instead of
            # letting the error bubble up.
            if typeof(cb) is 'function'
                cb(e)
            else
                throw e

    toString: -> err.printQuery(@)

class RDBVal extends TermBase
    eq: varar(1, null, (others...) -> new Eq {}, @, others...)
    ne: varar(1, null, (others...) -> new Ne {}, @, others...)
    lt: varar(1, null, (others...) -> new Lt {}, @, others...)
    le: varar(1, null, (others...) -> new Le {}, @, others...)
    gt: varar(1, null, (others...) -> new Gt {}, @, others...)
    ge: varar(1, null, (others...) -> new Ge {}, @, others...)

    not: ar () -> new Not {}, @

    add: varar(1, null, (others...) -> new Add {}, @, others...)
    sub: varar(1, null, (others...) -> new Sub {}, @, others...)
    mul: varar(1, null, (others...) -> new Mul {}, @, others...)
    div: varar(1, null, (others...) -> new Div {}, @, others...)
    mod: ar (other) -> new Mod {}, @, other

    append: ar (val) -> new Append {}, @, val
    prepend: ar (val) -> new Prepend {}, @, val
    difference: ar (val) -> new Difference {}, @, val
    setInsert: ar (val) -> new SetInsert {}, @, val
    setUnion: ar (val) -> new SetUnion {}, @, val
    setIntersection: ar (val) -> new SetIntersection {}, @, val
    setDifference: ar (val) -> new SetDifference {}, @, val
    slice: aropt (left, right, opts) -> new Slice opts, @, left, right
    skip: ar (index) -> new Skip {}, @, index
    limit: ar (index) -> new Limit {}, @, index
    getField: ar (field) -> new GetField {}, @, field
    contains: varar(1, null, (fields...) -> new Contains {}, @, fields.map(funcWrap)...)
    insertAt: ar (index, value) -> new InsertAt {}, @, index, value
    spliceAt: ar (index, value) -> new SpliceAt {}, @, index, value
    deleteAt: varar(1, 2, (others...) -> new DeleteAt {}, @, others...)
    changeAt: ar (index, value) -> new ChangeAt {}, @, index, value
    indexesOf: ar (which) -> new IndexesOf {}, @, funcWrap(which)
    hasFields: varar(0, null, (fields...) -> new HasFields {}, @, fields...)
    withFields: varar(0, null, (fields...) -> new WithFields {}, @, fields...)
    keys: ar(-> new Keys {}, @)

    # pluck and without on zero fields are allowed
    pluck: (fields...) -> new Pluck {}, @, fields...
    without: (fields...) -> new Without {}, @, fields...

    merge: ar (other) -> new Merge {}, @, other
    between: aropt (left, right, opts) -> new Between opts, @, left, right
    reduce: varar(1, 2, (func, base) -> new Reduce {base:base}, @, funcWrap(func))
    map: ar (func) -> new Map {}, @, funcWrap(func)
    filter: aropt (predicate, opts) -> new Filter opts, @, funcWrap(predicate)
    concatMap: ar (func) -> new ConcatMap {}, @, funcWrap(func)
    distinct: ar () -> new Distinct {}, @
    count: varar(0, 1, (fun...) -> new Count {}, @, fun.map(funcWrap)...)
    union: varar(1, null, (others...) -> new Union {}, @, others...)
    nth: ar (index) -> new Nth {}, @, index
    match: ar (pattern) -> new Match {}, @, pattern
    isEmpty: ar () -> new IsEmpty {}, @
    groupedMapReduce: varar(3, 4, (group, map, reduce, base) -> new GroupedMapReduce {base:base}, @, funcWrap(group), funcWrap(map), funcWrap(reduce))
    innerJoin: ar (other, predicate) -> new InnerJoin {}, @, other, predicate
    outerJoin: ar (other, predicate) -> new OuterJoin {}, @, other, predicate
    eqJoin: aropt (left_attr, right, opts) -> new EqJoin opts, @, left_attr, right
    zip: ar () -> new Zip {}, @
    coerceTo: ar (type) -> new CoerceTo {}, @, type
    typeOf: ar () -> new TypeOf {}, @
    update: aropt (func, opts) -> new Update opts, @, funcWrap(func)
    delete: aropt (opts) -> new Delete opts, @
    replace: aropt (func, opts) -> new Replace opts, @, funcWrap(func)
    do: ar (func) -> new FunCall {}, funcWrap(func), @
    default: ar (x) -> new Default {}, @, x

    or: varar(1, null, (others...) -> new Any {}, @, others...)
    and: varar(1, null, (others...) -> new All {}, @, others...)

    forEach: ar (func) -> new ForEach {}, @, funcWrap(func)

{'fraction_non_alphanumeric': 0.16130231175202556, 'fraction_numerical': 0.003567977402809782, 'mean_word_length': 2.4374041900868675, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 161, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2241809', 'n_tokens_mistral': 4115, 'n_tokens_neox': 4015, 'n_words': 1471}