-
Notifications
You must be signed in to change notification settings - Fork 11
/
IdrisScript.idr
170 lines (145 loc) · 4.98 KB
/
IdrisScript.idr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
module IdrisScript
%access public export
JSRef : Type
JSRef = Ptr
%inline
jscall : (fname : String) -> (ty : Type) ->
{auto fty : FTy FFI_JS [] ty} -> ty
jscall fname ty = foreign FFI_JS fname ty
data JSType = JSNumber
| JSString
| JSBoolean
| JSFunction
| JSNull
| JSObject String
| JSUndefined
implementation Eq JSType where
JSNumber == JSNumber = True
JSString == JSString = True
JSBoolean == JSBoolean = True
JSFunction == JSFunction = True
JSNull == JSNull = True
(JSObject c) == (JSObject c') = c == c'
JSUndefined == JSUndefined = True
_ == _ = False
data JSValue : JSType -> Type where
MkJSNumber : JSRef -> JSValue JSNumber
MkJSString : JSRef -> JSValue JSString
MkJSBoolean : JSRef -> JSValue JSBoolean
MkJSFunction : JSRef -> JSValue JSFunction
MkJSNull : JSRef -> JSValue JSNull
MkJSObject : JSRef -> JSValue (JSObject con)
MkJSUndefined : JSRef -> JSValue JSUndefined
JSArray : JSType
JSArray = JSObject "Array"
typeOf : JSRef -> JS_IO JSType
typeOf JSRef = do
res <- jscall checkType (Ptr -> JS_IO Int) JSRef
case res of
0 => pure JSNumber
1 => pure JSString
2 => pure JSBoolean
3 => pure JSFunction
4 => pure JSUndefined
5 => pure (JSObject !ctrName)
_ => pure JSNull
where
ctrName : JS_IO String
ctrName =
jscall "%0.constructor.name" (Ptr -> JS_IO String) JSRef
checkType : String
checkType =
"""(function(arg) {
if (typeof arg == 'number')
return 0;
else if (typeof arg == 'string')
return 1;
else if (typeof arg == 'boolean')
return 2;
else if (typeof arg == 'function')
return 3;
else if (typeof arg == 'undefined')
return 4;
else if (typeof arg == 'object')
return 5;
else
return 6;
})(%0)"""
interface ToJS from (to : JSType) where
toJS : from -> JSValue to
implementation ToJS String JSString where
toJS str = MkJSString (believe_me str)
implementation ToJS Int JSNumber where
toJS num = MkJSNumber (believe_me num)
implementation ToJS Double JSNumber where
toJS num = MkJSNumber (believe_me num)
implementation ToJS Bool JSBoolean where
toJS False = MkJSBoolean (believe_me 0)
toJS True = MkJSBoolean (believe_me 1)
interface FromJS (from : JSType) to where
fromJS : JSValue from -> to
implementation FromJS JSString String where
fromJS (MkJSString str) = believe_me str
implementation FromJS JSNumber Int where
fromJS (MkJSNumber num) = cast {from=Double} {to=Int} (believe_me num)
implementation FromJS JSNumber Double where
fromJS (MkJSNumber num) = believe_me num
implementation FromJS JSBoolean Bool where
fromJS (MkJSBoolean b) = check (believe_me b)
where
check : Int -> Bool
check b = b >= 1
||| Unpacks a JavaScript value
total
unpack : JSValue t -> JSRef
unpack (MkJSNumber JSRef) = JSRef
unpack (MkJSString JSRef) = JSRef
unpack (MkJSBoolean JSRef) = JSRef
unpack (MkJSFunction JSRef) = JSRef
unpack (MkJSNull JSRef) = JSRef
unpack (MkJSObject JSRef) = JSRef
unpack (MkJSUndefined JSRef) = JSRef
||| Packs up a JavaScript referenc into a JSValue
pack : JSRef -> JS_IO (t ** JSValue t)
pack JSRef =
case !(typeOf JSRef) of
JSNumber => pure (JSNumber ** MkJSNumber JSRef)
JSString => pure (JSString ** MkJSString JSRef)
JSBoolean => pure (JSBoolean ** MkJSBoolean JSRef)
JSFunction => pure (JSFunction ** MkJSFunction JSRef)
JSNull => pure (JSNull ** MkJSNull JSRef)
JSObject c => pure (JSObject c ** MkJSObject JSRef)
_ => pure (JSUndefined ** MkJSUndefined JSRef)
||| Log a value to console
log : JSValue t -> JS_IO ()
log js = jscall "console.log(%0)" (Ptr -> JS_IO ()) (unpack js)
||| Check if a value is undefined
isUndefined : JSValue t -> JS_IO Bool
isUndefined val = do
ty <- typeOf (unpack val)
pure $ ty == JSUndefined
||| Check if a value is null
isNull : JSValue t -> JS_IO Bool
isNull val = do
ty <- typeOf (unpack val)
pure $ ty == JSNull
||| Create a new object with a constructor function
||| @ con constructor function
||| @ args constructor arguments
new : (con : JSValue JSFunction)
-> (args : JSValue JSArray)
-> JS_IO (c ** JSValue (JSObject c))
new con args = do
obj <- jscall """(function(con,args) {
function Con(con, args) {
return con.apply(this, args);
}
Con.prototype = con.prototype;
return new Con(con, args);
})(%0, %1)""" (Ptr -> Ptr -> JS_IO Ptr)
(unpack con) (unpack args)
pure $ (!(ctrName obj) ** MkJSObject obj)
where
ctrName : JSRef -> JS_IO String
ctrName JSRef =
jscall "%0.constructor.name" (Ptr -> JS_IO String) JSRef