public
Description: Haskell implemented JavaScript interpreter
Homepage:
Clone URL: git://github.com/motemen/jusk.git
jusk / JSFunction.hs
100644 67 lines (55 sloc) 2.103 kb
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
{-
JSFunction.hs
Functionオブジェクト
http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/15-3_Function_Objects.html
-}
 
module JSFunction where
import Monad
import qualified Data.Map as Map
import Maybe
 
import DataTypes
import Eval hiding(callMethod)
import Internal
import JSType
 
-- Function.prototype
prototypeObject :: Value
prototypeObject =
    nullObject {
        objPropMap = nativeFuncPropMap [("constructor", constructor, 1),
                                        ("toString", toStringMethod, 0),
                                        ("call", callMethod, 1),
                                        ("apply", apply, 2)]
    }
 
toStringMethod :: NativeCode
toStringMethod this _ =
    do this <- readRef this
       if isFunction this || isNativeFunction this
          then return $ toValue $ show this
          else throw "TypeError" $ "Function.prototype.toString: " ++ getName this ++ " is not a function"
 
-- Function
function :: NativeCode
function args = constructor args
 
-- new Function
constructor :: NativeCode
constructor _ _ = throw "NotImplemented" "Function.prototype.constructor"
 
-- Function.prototype.call
callMethod :: NativeCode
callMethod this (thisArg:args) =
    callWithThis thisArg this args
 
-- Function.prototype.apply
apply :: NativeCode
apply this [thisArg] =
    apply this [thisArg, nullObject { objObject = Array [] }]
 
apply this (thisArg:argArray:_) =
    do argArray <- readRef argArray
       case argArray of
            Object { objObject = Array args } -> callWithThis thisArg this args
            _ | isArguments argArray ->
                do length <- toUInt $ argArray ! "length"
                   args <- mapM (getProp argArray . show) [0..length-1]
                   callWithThis thisArg this args
            _ -> throw "TypeError" "second argument to Function.prototype.apply must be an array"
 
isArguments :: Value -> Bool
isArguments (Object { objPropMap = propMap }) =
    fromMaybe False (Map.lookup "callee" propMap >>= return . (elem DontEnum) . propAttr)
 
isArguments _ = False