diff --git a/runtimes/assemblyscript/assembly/index.ts b/runtimes/assemblyscript/assembly/index.ts index 3ed47a92..06c36eef 100644 --- a/runtimes/assemblyscript/assembly/index.ts +++ b/runtimes/assemblyscript/assembly/index.ts @@ -41,6 +41,14 @@ const c_0 = new EjNumber(0); export class EjBigInt extends EjValue { value: i64 constructor(a: i64) { super(); this.value = a; } + + safe_to_i32() : i32 { + if (this.value > I32.MAX_VALUE || this.value < I32.MIN_VALUE) { + throw new Error("EjBigInt: cannot convert to i32"); + } else { + return this.value; + } + } } export const IdEjBigInt = idof() export function ejBigInt_of_f64(x: f64) : EjBigInt { @@ -53,6 +61,7 @@ export class EjString extends EjValue { constructor(a: string) { super(); this.value = a; } } export const IdEjString = idof() +const c_empty_string = new EjString("") export class EjArray extends EjValue { values: Array @@ -505,60 +514,64 @@ export function opMathTrunc(a: EjNumber): EjNumber { // EJson Runtime Operators // ///////////////////////////// -export function runtimeEqual(a: EjValue, b: EjValue): EjBool { +function equal(a: EjValue, b: EjValue): boolean { if (a instanceof EjNull && b instanceof EjNull) { - return c_true; + return true; } if (a instanceof EjBool && b instanceof EjBool) { let aa : EjBool = changetype(a) ; let bb : EjBool = changetype(b) ; - return aa.value == bb.value ? c_true : c_false; + return aa.value == bb.value ? true : false; } if (a instanceof EjNumber && b instanceof EjNumber) { let aa : EjNumber = changetype(a) ; let bb : EjNumber = changetype(b) ; - return aa.value == bb.value ? c_true : c_false; + return aa.value == bb.value ? true : false; } if (a instanceof EjBigInt && b instanceof EjBigInt) { let aa : EjBigInt = changetype(a) ; let bb : EjBigInt = changetype(b) ; - return aa.value == bb.value ? c_true : c_false; + return aa.value == bb.value ? true : false; } if (a instanceof EjString && b instanceof EjString) { let aa : EjString = changetype(a) ; let bb : EjString = changetype(b) ; - return aa.value == bb.value ? c_true : c_false; + return aa.value == bb.value ? true : false; } if (a instanceof EjArray && b instanceof EjArray) { let aa : EjArray = changetype(a) ; let bb : EjArray = changetype(b) ; if (aa.values.length != bb.values.length) { - return c_false; + return false; } for (let i = 0; i < aa.values.length; i++) { if (! runtimeEqual(aa.values[i], bb.values[i]).value) { - return c_false; + return false; } } - return c_true; + return true; } if (a instanceof EjObject && b instanceof EjObject) { let aa : EjObject = changetype(a) ; let bb : EjObject = changetype(b) ; if (aa.values.size != bb.values.size) { - return c_false; + return false; } let keys = aa.values.keys(); for (let i = 0; i < keys.length; i++) { let k = keys[i]; if (! bb.values.has(k) || ! runtimeEqual(aa.values[k], bb.values[k]).value ) { - return c_false; + return false; } } - return c_true; + return true; } - return c_false; + return false; +} + +export function runtimeEqual(a: EjValue, b: EjValue): EjBool { + return equal(a, b) ? c_true : c_false; } // This is actually a compare negative. @@ -998,7 +1011,10 @@ export function runtimeCount(a: EjArray) : EjBigInt { } export function runtimeContains(a: EjValue, b: EjArray) : EjBool { - throw new Error('runtimeContains: not implemented'); + for (let i=0; i < b.values.length; i++) { + if (equal(a, b.values[i])) { return c_true; } + } + return c_false; } export function runtimeSort(a: EjArray, b: EjNull) : EjArray { @@ -1010,19 +1026,29 @@ export function runtimeGroupBy(a: EjArray, b: EjNull, c:EjNull) : EjArray { } export function runtimeLength(a: EjString) : EjBigInt { - throw new Error('runtimeLength: not implemented'); + return new EjBigInt(a.value.length); } export function runtimeSubstring(a: EjString, start: EjBigInt, len:EjBigInt) : EjString { - throw new Error('runtimeSubstring: not implemented'); + let istart = start.safe_to_i32(); + let iend = istart + len.safe_to_i32(); + return new EjString(a.value.substring(istart, iend)); } export function runtimeSubstringEnd(a: EjString, start: EjBigInt) : EjString { - throw new Error('runtimeSubstringEnd: not implemented'); + return new EjString(a.value.substring(start.safe_to_i32())); } export function runtimeStringJoin(sep: EjString, a: EjArray): EjString { - throw new Error('runtimeStringJoin: not implemented'); + let v = a.values; + if (v.length < 1) { return c_empty_string; } + let i = 0; + let r = cast(v[i++]).value; + while (i < v.length) { + r += sep.value; + r += cast(v[i++]).value; + } + return new EjString(r); } export function runtimeLike(reg: EjString, target:EjString): EjBool { diff --git a/runtimes/assemblyscript/runtime.wasm b/runtimes/assemblyscript/runtime.wasm index 703f1234..1abdf8f4 100644 Binary files a/runtimes/assemblyscript/runtime.wasm and b/runtimes/assemblyscript/runtime.wasm differ diff --git a/tests/operators/main.ml b/tests/operators/main.ml index 86343efd..9a65ebcd 100644 --- a/tests/operators/main.ml +++ b/tests/operators/main.ml @@ -442,6 +442,55 @@ let _ = ; [ arr [null] ] ; [ arr [] ] ]; + test_rtop + EJsonRuntimeContains + [ [ null; arr [] ] + ; [ null; arr [null] ] + ; [ null; arr [bool true] ] + ; [ bool true; arr [bool true; bool false] ] + ; [ bool false; arr [bool true; null] ] + ; [ int 0; arr [int 0; int 1; int 2] ] + ; [ int 1; arr [int 0; int 1; int 2] ] + ; [ int 2; arr [int 0; int 1; int 2] ] + ; [ int 3; arr [int 0; int 1; int 2] ] + ]; + test_rtop + EJsonRuntimeLength + [ [ str "" ] + ; [ str "a" ] + ; [ str "abcc" ] + (* ; [ str "abccᵤ" ] *) (* Coq uses char list, JS/Wasm use UTF16. *) + ]; + test_rtop + EJsonRuntimeSubstring (* string, start, target length *) + [ [ str "" ; int 0; int 0 ] + ; [ str "" ; int 1; int 1 ] + ; [ str "" ; int 1; int (-1) ] + ; [ str "0" ; int 0; int 1 ] + ; [ str "0" ; int 0; int 0 ] + ; [ str "0" ; int 0; int (-1) ] + ; [ str "012345" ; int 0; int 3 ] + ; [ str "012345" ; int 2; int 3 ] + ; [ str "012345" ; int 0; int 6 ] + ]; + test_rtop + EJsonRuntimeSubstringEnd + [ [ str "" ; int 0] + ; [ str "" ; int 1] + ; [ str "0" ; int 0] + ; [ str "012345" ; int 0] + ; [ str "012345" ; int 2] + ; [ str "012345" ; int 5] + ; [ str "012345" ; int 6] + ]; + test_rtop + EJsonRuntimeStringJoin (* sep, string array *) + [ [ str ""; arr [] ] + ; [ str "_"; arr [] ] + ; [ str "_"; arr [str "-"] ] + ; [ str "_"; arr [str "-"; str "-"] ] + ; [ str "/"; arr [str "a"; str "b"; str "c"] ] + ]; test_rtop EJsonRuntimeNatPlus [ [int 41; int 1]