qcert
qcert copied to clipboard
WASM: Priority list of runtime & operators
Part of #153.
Operators
- [x] EJsonOpNot
- [x] EJsonOpNeg
- [x] EJsonOpAnd
- [x] EJsonOpOr
- [x] EJsonOpLt
- [x] EJsonOpLe
- [x] EJsonOpGt
- [x] EJsonOpGe
- [x] EJsonOpAddString
- [x] EJsonOpAddNumber
- [x] EJsonOpSub
- [x] EJsonOpMult
- [x] EJsonOpDiv
- [x] EJsonOpStrictEqual ( currently = EJsonRuntimeEqual)
- [x] EJsonOpStrictDisequal ( currently = not EJsonRuntimeEqual)
- [x] EJsonOpArray (n-ary, handled by compiler)
- [x] EJsonOpArrayLength
- [x] EJsonOpArrayPush
- [x] EJsonOpArrayAccess
- [x] EJsonOpObject _ (n-ary, handled by compiler)
- [x] EJsonOpAccess _
- [x] EJsonOpHasOwnProperty _
- [x] EJsonOpMathMin
- [x] EJsonOpMathMax
- [x] EJsonOpMathPow
- [x] EJsonOpMathExp
- [x] EJsonOpMathAbs
- [x] EJsonOpMathLog
- [x] EJsonOpMathLog10
- [x] EJsonOpMathSqrt
- [x] EJsonOpMathCeil
- [x] EJsonOpMathFloor
- [x] EJsonOpMathTrunc
Runtime
- [x] EJsonRuntimeEqual (** XXX First *)
- [x] EJsonRuntimeCompare
- [x] EJsonRuntimeToString ( XXX Third )
- [ ] EJsonRuntimeToText ( will be removed )
Record
- [x] EJsonRuntimeRecConcat (** XXX First *)
- [x] EJsonRuntimeRecMerge (** XXX Second *)
- [x] EJsonRuntimeRecRemove (** XXX Second *)
- [x] EJsonRuntimeRecProject (** XXX Second *)
- [x] EJsonRuntimeRecDot (** XXX First *) ( = EJsonOpAccess)
Array
- [x] EJsonRuntimeArray (n-ary, handled by compiler) = EJsonOpArray
- [x] EJsonRuntimeArrayLength (= EJsonOpArrayLength)
- [x] EJsonRuntimeArrayPush (** XXX Third = EJsonOpArrayPush **)
- [x] EJsonRuntimeArrayAccess (** XXX Third = EJsonOpArrayAccess **)
Sum
- [x] EJsonRuntimeEither (** XXX First *)
- [x] EJsonRuntimeToLeft (** XXX First *)
- [x] EJsonRuntimeToRight (** XXX First *)
Brand
- [x] EJsonRuntimeBrand (** XXX Second -- not existing / eliminated? *)
- [x] EJsonRuntimeUnbrand (** XXX Second -- eliminate with
runtimeRecDot "$data"? *) - [x] EJsonRuntimeCast (** XXX Second -- maybe eliminate *)
Collection
- [x] EJsonRuntimeDistinct
- [x] EJsonRuntimeSingleton (** XXX Second *)
- [x] EJsonRuntimeFlatten (** XXX Second *)
- [x] EJsonRuntimeUnion (** XXX Second *)
- [x] EJsonRuntimeMinus (** XXX Second *)
- [x] EJsonRuntimeMin
- [x] EJsonRuntimeMax
- [x] EJsonRuntimeNth (** XXX Second *)
- [x] EJsonRuntimeCount (** XXX Second *) ( redundant with OpArrayLength )
- [x] EJsonRuntimeContains
- [ ] EJsonRuntimeSort (** XXX Ignore *)
- [ ] EJsonRuntimeGroupBy (** XXX Ignore *)
String
- [x] EJsonRuntimeLength
- [x] EJsonRuntimeSubstring
- [x] EJsonRuntimeSubstringEnd
- [x] EJsonRuntimeStringJoin
- [x] EJsonRuntimeLike (** XXX Not used in Ergo *)
Integer
- [x] EJsonRuntimeNatLt
- [x] EJsonRuntimeNatLe
- [x] EJsonRuntimeNatPlus
- [x] EJsonRuntimeNatMinus
- [x] EJsonRuntimeNatMult
- [x] EJsonRuntimeNatDiv
- [x] EJsonRuntimeNatRem
- [x] EJsonRuntimeNatAbs
- [x] EJsonRuntimeNatLog2
- [x] EJsonRuntimeNatSqrt
- [x] EJsonRuntimeNatMinPair
- [x] EJsonRuntimeNatMaxPair
- [x] EJsonRuntimeNatSum
- [x] EJsonRuntimeNatMin
- [x] EJsonRuntimeNatMax
- [x] EJsonRuntimeNatArithMean
- [x] EJsonRuntimeFloatOfNat
Float
- [x] EJsonRuntimeFloatSum
- [x] EJsonRuntimeFloatArithMean
- [x] EJsonRuntimeFloatMin
- [x] EJsonRuntimeFloatMax
- [x] EJsonRuntimeNatOfFloat
Foreign
- [ ] EJsonRuntimeForeign ( to be implemented before toString )
The array operators are missing on this list. They are probably important?
https://github.com/querycert/qcert/blob/wasm/compiler/core/EJson/Operators/EJsonRuntimeOperators.v#L48-L51
RuntimeArray is n-ary and the n is not known locally. I need to know the n for compilation.
Just updated the list to reflect the latest state. Also added the non-runtime operators.
I made some progress in 95782518286.
I think implementing and debugging the runtime would benefit from a set of unit tests per operator. How would you do it? My current best guess is to add Imp tests per operator under /tests/operators/<operatorName>.imp_ejson. Or do you have something like this already?
I made some progress in 9578251. I think implementing and debugging the runtime would benefit from a set of unit tests per operator. How would you do it? My current best guess is to add Imp tests per operator under
/tests/operators/<operatorName>.imp_ejson. Or do you have something like this already?
hm. that's a really good question. And no, we don't have anything of the kind even for JS. This would be super great though.
I think one question is whether those tests are written in imp_ejson or are they written against the runtime itself (i.e., in JS, AssemblyScript).
I'd implement them in imp_ejson. Makes them reusable for other backends / runtime implementations.
I'd implement them in imp_ejson. Makes them reusable for other backends / runtime implementations.
agreed. Not sure how to make those systematic, would we like a syntax for those things.
Your imp_ejson parser undestands runtime operators like Runtime.array(arg0, ...). How much effort is it to do something similar for non-runtime Operators? E.g. something like Op.object(keys)(val1, val2) which translates directly to the variant type in EJsonOperators.v.
Currently, I do not fully understand the semantics of imp_ejson. Maybe such a change will help.
Your imp_ejson parser undestands runtime operators like
Runtime.array(arg0, ...). How much effort is it to do something similar for non-runtime Operators? E.g. something likeOp.object(keys)(val1, val2)which translates directly to the variant type inEJsonOperators.v.Currently, I do not fully understand the semantics of imp_ejson. Maybe such a change will help.
🤔 I forgot we had two kinds of operators in Imp... Let me look at the parser, I think there was a reason why I only did it for runtime operators, but let me double check.
Now I get what you meant with "syntax for those things". I think we could do something like this.
{ "name": "Runtime Operator Equal",
"operator": "EJsonRuntimeEqual",
"type": "ejson_runtime_op",
"inputs": [ [ ejson_test0_arg0, ejson_test0_arg1 ],
[ ejson_test1_arg1, ejson_test1_arg2 ],
...
]}
The ejson_* parts would be actual EJson values. The semantics of the test would be
- parse above json
- foreach args in inputs
- a := imp eval operator with arguments in verified system
- b := wasm/js eval compiled version of the statement in unverified system
- if a != b then fail and print name/operator/type/args
That would be super useful. Requires some plumping on your side, though.
Now I get what you meant with "syntax for those things". I think we could do something like this.
{ "name": "Runtime Operator Equal", "operator": "EJsonRuntimeEqual", "type": "ejson_runtime_op", "inputs": [ [ ejson_test0_arg0, ejson_test0_arg1 ], [ ejson_test1_arg1, ejson_test1_arg2 ], ... ]}
yes that's what I was wondering!
The
ejson_*parts would be actual EJson values. The semantics of the test would be
parse above json
foreach args in inputs
- a := imp eval operator with arguments in verified system
- b := wasm/js eval compiled version of the statement in unverified system
- if a != b then fail and print name/operator/type/args
That would be super useful. Requires some plumping on your side, though.
Sounds good. Let me see if I can get some traction on this, will need to page in current status. Thanks for a concrete proposal! I'll see if I can start with that.
Will need to figure out how to write ejson values (in JSON? maybe that's too obvious)
Will need to figure out how to write ejson values (in JSON? maybe that's too obvious)
Yes in JSON. I think you already have serializer/parsers? That's my main reason for writing the tests in JSON. I'd appreciate another format for writing the tests. Something supporting comments. But I guess that would be more work?
Will need to figure out how to write ejson values (in JSON? maybe that's too obvious)
Yes in JSON. I think you already have serializer/parsers? That's my main reason for writing the tests in JSON. I'd appreciate another format for writing the tests. Something supporting comments. But I guess that would be more work?
JSON = 👍
proper syntax would be more work, but yes I'd love that too. main factor will be available time I'm afraid.
Coming back to the operator unit test proposed above.
I think we save a lot of time by coding the tests in OCaml. I've a basic proof-of-concept working. I compose small Imp functions with one expression and one operator. Then I evaluate these function using Imp's eval and Wasm's eval and compare the result. In my opinion, the syntax is effective.
https://github.com/querycert/qcert/blob/fd572815675f125a2147bd6ebeffbb5940ce88b0/tests/operators/main.ml#L87-L99