summaryrefslogtreecommitdiff
path: root/rts/js/verify.js
diff options
context:
space:
mode:
Diffstat (limited to 'rts/js/verify.js')
-rw-r--r--rts/js/verify.js175
1 files changed, 175 insertions, 0 deletions
diff --git a/rts/js/verify.js b/rts/js/verify.js
new file mode 100644
index 0000000000..a04a562b7f
--- /dev/null
+++ b/rts/js/verify.js
@@ -0,0 +1,175 @@
+//#OPTIONS: CPP
+
+/*
+ Runtime inspection of Haskell data.
+
+ The code generator can emit calls to these functions
+ */
+/*
+function h$verify_rep_int64(x, y) {
+
+}
+
+function h$verify_rep_word64(x, y) {
+
+}
+*/
+
+/*
+ an int rep is an integer in range [-2^31..2^31-1]
+ (for Word# values, the value is treated as unsigned by the RTS. From
+ JavaScript it still looks signed.
+ )
+ */
+function h$verify_rep_int(x) {
+ if(typeof x === 'number' &&
+ (x|0) === x
+ ) return;
+ throw new Error("invalid int rep " + h$show_val(x));
+}
+
+/*
+function h$verify_rep_word(x, y) {
+
+}
+*/
+/*
+ a long rep is two integers in rage [-2^31..2^31-1]
+ */
+function h$verify_rep_long(x, y) {
+ if(typeof x === 'number' &&
+ typeof y === 'number' &&
+ (x|0) === x &&
+ (y|0) === y
+ ) return;
+ throw new Error("invalid long rep " + h$show_val(x) + " " + h$show_val(y));
+}
+
+/*
+function h$verify_rep_float(x) {
+
+}
+*/
+
+function h$verify_rep_double(x) {
+ if(typeof x === 'number') return;
+ throw new Error("invalid double rep " + h$show_val(x));
+}
+
+/*
+ an array rep is a JavaScript array. The elements are other
+ array reps or heap objects.
+ */
+function h$verify_rep_arr(x) {
+ if(h$verify_rep_is_arr(x)) return;
+ throw new Error("invalid array rep " + h$show_val(x));
+}
+
+function h$verify_rep_is_arr(x) {
+ // XXX check the elements?
+ return (typeof x === 'object'
+ && x
+ && Array.isArray(x)
+ // XXX enable this check
+ // && x.__ghcjsArray === true
+ );
+}
+
+function h$verify_rep_rtsobj(x) {
+ // unspecified unlifted value
+}
+
+/*
+ an rts object rep is one of the known RTS object types
+ */
+function h$verify_rep_is_rtsobj(o) {
+ return (o instanceof h$MVar ||
+ o instanceof h$MutVar ||
+ o instanceof h$TVar ||
+ o instanceof h$Transaction ||
+ o instanceof h$Thread ||
+ o instanceof h$Weak ||
+ o instanceof h$StableName ||
+ h$verify_rep_is_bytearray(o) ||
+ h$verify_rep_is_arr(o));
+}
+
+function h$verify_rep_is_bytearray(o) {
+ return (typeof o === 'object' &&
+ o &&
+ typeof o.buf === 'object' &&
+ o.buf &&
+ o.buf instanceof ArrayBuffer &&
+ typeof o.len === 'number');
+}
+
+/*
+ a heap object rep is either an object or an unboxed heap object
+
+ unboxed heap objects store evaluated values of type 'number' or 'boolean'
+ without wrapping them in a normal heap object. this is only done for
+ data types with a single constructor and a single field of an appropriate type
+ */
+function h$verify_rep_heapobj(o) {
+ // possibly an unlifted rts object
+ // XXX: we should do a different check for these
+ if(h$verify_rep_is_rtsobj(o)) return;
+ // unboxed rep
+ if(typeof o === 'number' || typeof o === 'boolean') return;
+ // boxed rep
+ if(typeof o === 'object' &&
+ o &&
+ typeof o.f === 'function' &&
+ typeof o.f.a === 'number' &&
+ (typeof o.m === 'number' || (typeof o.m === 'object' && o.m))
+ ) return;
+ throw new Error("invalid heapobj rep " + h$show_val(o));
+}
+
+/*
+ an addr rep is a data object and an integer offset
+ */
+function h$verify_rep_addr(v, o) {
+ if(typeof o === 'number' &&
+ (o|0) === o &&
+ // o >= 0 && // XXX we could treat it as unsigned, should we?
+ typeof v === 'object'
+ ) return;
+ throw new Error("invalid addr rep " + h$show_val(v) + " " + o);
+}
+
+/*
+ v must be a value of type tc that can be matched
+ */
+function h$verify_match_alg(tc, v) {
+ if(typeof v === 'boolean') {
+ if(tc === "ghc-prim:GHC.Types.Bool") return;
+ throw new Error("invalid pattern match boolean rep " + tc);
+ } else if(typeof v === 'number') {
+ // h$log("h$verify_match_alg number: " + tc);
+ return;
+ } else if(typeof v === 'object') {
+ // h$log("verify_match_alg_obj: " + tc);
+ if(!(typeof v.f === 'function' &&
+ typeof v.f.a === 'number' &&
+ typeof v.f.t === 'number' &&
+ v.f.t === 2 /// con
+ )) {
+ throw new Error("not a data constructor " + tc + ": " + h$show_val(v));
+ }
+ // XXX add check for the type
+ return;
+ }
+ throw new Error("invalid pattern match rep " + tc + ": " + h$show_val(v));
+}
+
+/*
+ debug show object
+ */
+
+function h$show_val(o) {
+ if(typeof o === 'undefined') return '<undefined>'
+ if(o === null) return '<null>'
+ if(typeof o !== 'object') return '[' + (typeof o) + ': ' + o + ']'
+ return '' + o + ' [' + o.constructor.name + '] ' + h$collectProps(o);
+}