123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- function lazy_bool (arg, desc, name) {
- ensure(is(arg, Types.Bool), 'arg_require_bool', name)
- return arg
- }
- function apply_operator (name, a, b) {
- assert(is(name, Types.String))
- if (is(a, Types.Struct)) {
- let s = get_common_schema(a, b)
- return call(s.get_operator(name), [a, b])
- } else {
- assert(is(a, Types.Instance))
- let f = get_common_operator(a, b, name)
- return call(f, [a, b])
- }
- }
- function apply_unary (name, a) {
- assert(is(name, Types.String))
- if (is(a, Types.Struct)) {
- return call(a.schema.get_operator(name), [a])
- } else {
- assert(is(a, Types.Instance))
- return call(a.class_.get_operator(name), [a])
- }
- }
- let operators = {
- 'is': f (
- 'operator.is',
- 'function operator.is (x: Any, T: Type) -> Bool',
- (x, A) => {
- // if T is a custom type, its checker must be f: [Any] --> Bool
- // this constraint should be enforced by custom type creator
- return call(A[Checker], [x])
- }
- ),
- 'as': f (
- 'operator.as',
- `function operator.as (x: Operand<'as'>, T: Type) -> Object`,
- (x, T) => {
- let y = null
- if (is(x, Types.Struct)) {
- y = call(x.schema.get_operator('as'), [x, T])
- } else {
- assert(is(x, Types.Instance))
- y = call(x.class_.get_operator('as'), [x, T])
- }
- ensure(is(y, T), 'invalid_cast')
- return y
- }
- ),
- 'str': f (
- 'operator.str',
- `function operator.str (o: Operand<'str'>) -> String`,
- o => apply_unary('str', o),
- 'function operator.str (p: Bool) -> String',
- p => p? 'true': 'false',
- 'function operator.str (x: Number) -> String',
- x => Number.prototype.toString.call(x),
- 'function operator.str (s: String) -> String',
- s => s
- ),
- 'len': f (
- 'operator.len',
- `function operator.len (o: Operand<'len'>) -> Size`,
- o => apply_unary('len', o),
- 'function operator.len (l: List) -> Size',
- l => l.length
- ),
- 'copy': f (
- 'copy',
- `function copy (o: Operand<'copy'>) -> Object`,
- o => {
- assert(is(o, Types.Instance))
- let copied = apply_unary('copy', o)
- ensure(is(copied, Types.Instance), 'invalid_copy')
- ensure(copied.class_ === o.class_, 'invalid_copy')
- ensure(copied !== o, 'did_not_copy')
- return copied
- },
- 'function copy (s: Struct) -> Struct',
- s => new_struct(s.schema, copy(s.data)),
- 'function copy (l: List) -> List',
- l => copy(l),
- 'function copy (h: Hash) -> Hash',
- h => copy(h)
- ),
- 'prms': f (
- 'operator.prms',
- `function operator.prms (o: Operand<'prms'>) -> Promise`,
- o => apply_unary('prms', o),
- 'function operator.prms (p: Promise) -> Promise',
- p => p
- ),
- 'iter': f (
- 'operator.iter',
- `function operator.iter (o: Operand<'iter'>) -> Iterator`,
- o => apply_unary('iter', o),
- 'function operator.iter (e: Enum) -> Iterator',
- e => e.iterate_items(),
- 'function operator.iter (i: ES_Iterable) -> Iterator',
- i => i[Symbol.iterator]()
- ),
- 'obsv': f (
- 'operator.obsv',
- `function operator.obsv (o: Operand<'obsv'>) -> Observer`,
- o => apply_unary('obsv', o),
- 'function operator.obsv (o: Observer) -> Observer',
- o => o
- ),
- 'async_iter': f (
- 'operator.async_iter',
- `function operator.async_iter (o: Operand<'async_iter'>) -> AsyncIterator`,
- o => apply_unary('async_iter', o),
- 'function operator.async_iter (ai: ES_AsyncIterable) -> AsyncIterator',
- ai => ai[Symbol.asyncIterator]()
- ),
- 'enum': f (
- 'operator.enum',
- `function operator.enum (o: Operand<'enum'>) -> EntryList`,
- o => apply_unary('enum', o),
- 'function operator.enum (e: Enum) -> EntryList',
- e => {
- let keys = e.keys()
- return new_struct(Types.EntryList, {
- keys, values: keys.map(k => e.get(k))
- })
- },
- 'function operator.enum (h: Hash) -> EntryList',
- h => {
- let keys = Object.keys(h)
- return new Struct(Types.EntryList, {
- keys, values: keys.map(k => h[k])
- })
- }
- ),
- 'negate': f (
- 'operator.negate',
- `function operator.negate (o: Operand<'negate'>) -> Object`,
- o => apply_unary('negate', o),
- 'function operator.negate (x: Number) -> Number',
- x => 0 - x
- ),
- /* Pull, Push, Derive, Otherwise */
- '<<': f (
- 'operator.pull',
- `function operator.pull (a: Operand<'<<'>, b: Operand<'<<'>) -> Any`,
- (a, b) => apply_operator('<<', a, b),
- 'function operator.pull (f: Callable, x: Any) -> Any',
- (f, x) => call(f, [x]),
- 'function operator.pull (l: Hash, r: Hash) -> Hash',
- (l, r) => Object.assign(l, r),
- 'function operator.pull (s: String, x: Any) -> String',
- (s, x) => call(string_format, [s, x])
- ),
- '>>': f (
- 'operator.push',
- `function operator.push (a: Operand<'>>'>, b: Operand<'>>'>) -> Any`,
- (a, b) => apply_operator('>>', a, b)
- ),
- '=>': f (
- 'operator.derive',
- 'function operator.derive (p: Bool, ok: Callable) -> Any',
- (p, ok) => p? ok(): Nil
- ),
- 'or': f (
- 'operator.otherwise',
- 'function operator.otherwise (x: Any, fallback: Callable) -> Any',
- (x, fallback) => (x !== Nil)? x: fallback()
- ),
- /* Comparsion */
- '<': f (
- 'operator.less_than',
- `function operator.less_than (a: Operand<'<'>, b: Operand<'<'>) -> Bool`,
- (a, b) => apply_operator('<', a, b),
- 'function operator.less_than (a: String, b: String) -> Bool',
- (a, b) => a < b,
- 'function operator.less_than (x: Number, y: Number) -> Bool',
- (x, y) => x < y
- ),
- '>': f (
- 'operator.greater_than',
- 'function operator.greater_than (l: Any, r: Any) -> Bool',
- (l, r) => operators['<'](r, l)
- ),
- '<=': f (
- 'operator.less_than_or_equal',
- 'function operator.less_than_or_equal (l: Any, r: Any) -> Bool',
- (l, r) => !operators['<'](r, l)
- ),
- '>=': f (
- 'operator.greater_than_or_equal',
- 'function operator.greater_than_or_equal (l: Any, r: Any) -> Bool',
- (l, r) => !operators['<'](l, r)
- ),
- '==': f (
- 'operator.equal',
- `function operator.equal (a: Operand<'=='>, b: Operand<'=='>) -> Bool`,
- (a, b) => apply_operator('==', a, b),
- 'function operator.equal (p: Bool, q: Bool) -> Bool',
- (p, q) => (p === q),
- 'function operator.equal (a: String, b: String) -> Bool',
- (a, b) => (a === b),
- 'function operator.equal (x: Number, y: Number) -> Bool',
- (x, y) => (x === y)
- ),
- '!=': f (
- 'operator.not_equal',
- 'function operator.not_equal (l: Any, r: Any) -> Bool',
- (l, r) => !operators['=='](l, r)
- ),
- '~~': f (
- 'operator.same',
- 'function operator.same (l: Any, r: Any) -> Bool',
- (l, r) => (Number.isNaN(l) && Number.isNaN(r)) || (l === r)
- ),
- '!~': f (
- 'operator.not_same',
- 'function operator.not_same (l: Any, r: Any) -> Bool',
- (l, r) => !operators['~~'](l, r)
- ),
- '<=>': f (
- 'operator.type_equal',
- 'function operator.type_equal (L: Type, R: Type) -> Bool',
- (L, R) => type_equivalent(L, R)
- ),
- '<!=>': f (
- 'operator.type_not_equal',
- 'function operator.type_not_equal (L: Type, R: Type) -> Bool',
- (L, R) => !operators['<=>'](L, R)
- ),
- /* Logic */
- '&&': f (
- 'operator.and',
- 'function operator.and (p: Bool, q: Callable) -> Bool',
- (p, q) => !p? false: lazy_bool(q(), 'operator.and', 'q')
- ),
- '||': f (
- 'operator.or',
- 'function operator.or (p: Bool, q: Callable) -> Bool',
- (p, q) => p? true: lazy_bool(q(), 'operator.or', 'q')
- ),
- '!': f (
- 'operator.not',
- 'function operator.not (p: Bool) -> Bool',
- p => !p
- ),
- '&': f (
- 'operator.intersect',
- 'function operator.intersect (A: Type, B: Type) -> Type',
- (A, B) => Ins(A, B)
- ),
- '|': f (
- 'operator.union',
- 'function operator.union (A: Type, B: Type) -> Type',
- (A, B) => Uni(A, B)
- ),
- '~': f (
- 'operator.complement',
- 'function operator.complement (A: Type) -> Type',
- A => Not(A)
- ),
- '\\': f (
- 'operator.difference',
- 'function operator.difference (A: Type, B: Type) -> Type',
- (A, B) => Ins(A, Not(B))
- ),
- 'not': f (
- 'operator.keyword_not',
- 'function operator.keyword_not (p: Bool) -> Bool',
- p => !p,
- 'function operator.keyword_not (T: Type) -> Type',
- T => Not(T)
- ),
- /* Arithmetic */
- '+': f (
- 'operator.plus',
- `function operator.plus (a: Operand<'+'>, b: Operand<'+'>) -> Object`,
- (a, b) => apply_operator('+', a, b),
- 'function operator.plus (a: List, b: List) -> List',
- (a, b) => [...a, ...b],
- 'function operator.plus (a: String, b: String) -> String',
- (a, b) => a + b,
- 'function operator.plus (x: Number, y: Number) -> GeneralNumber',
- (x, y) => x + y
- ),
- '-': f (
- 'operator.minus',
- `function operator.minus (a: Operand<'-'>, b: Operand<'-'>) -> Object`,
- (a, b) => apply_operator('-', a, b),
- 'function operator.minus (x: Number, y: Number) -> GeneralNumber',
- (x, y) => x - y
- ),
- '*': f (
- 'operator.times',
- `function operator.times (a: Operand<'*'>, b: Operand<'*'>) -> Object`,
- (a, b) => apply_operator('*', a, b),
- 'function operator.times (x: Number, y: Number) -> GeneralNumber',
- (x, y) => x * y
- ),
- '/': f (
- 'operator.divide',
- `function operator.divide (a: Operand<'/'>, b: Operand<'/'>) -> Object`,
- (a, b) => apply_operator('/', a, b),
- 'function operator.divide (x: Number, y: Number) -> GeneralNumber',
- (x, y) => x / y
- ),
- '%': f (
- 'operator.modulo',
- `function operator.modulo (a: Operand<'%'>, b: Operand<'%'>) -> Object`,
- (a, b) => apply_operator('%', a, b),
- 'function operator.modulo (x: Number, y: Number) -> GeneralNumber',
- (x, y) => x % y
- ),
- '^': f (
- 'operator.power',
- `function operator.power (a: Operand<'^'>, b: Operand<'^'>) -> Object`,
- (a, b) => apply_operator('^', a, b),
- 'function operator.power (x: Number, y: Number) -> GeneralNumber',
- (x, y) => Math.pow(x, y)
- )
- }
- Object.freeze(operators)
- let operator_is = operators['is']
- function str (value) {
- return call(operators['str'], [value])
- }
- function prms (value) {
- return call(operators['prms'], [value])
- }
- function iter (value) {
- return call(operators['iter'], [value])
- }
- function obsv (value) {
- return call(operators['obsv'], [value])
- }
- function async_iter (value) {
- return call(operators['async_iter'], [value])
- }
- function enum_ (value) {
- return call(operators['enum'], [value])
- }
- function get_operator (name) {
- assert(has(name, operators))
- return operators[name]
- }
|