@@ -1,7 +1,6 @@
1module Generate.JavaScript.Variable
1module Generate.JavaScript.Variable
3 , canonical
3 , canonical
@@ -18,8 +17,10 @@ import qualified AST.Variable as Var
18import qualified Generate.JavaScript.Helpers as JS
17import qualified Generate.JavaScript.Helpers as JS
21-- FRESH NAMES
21-- FRESH NAMES
23fresh :: State.State Int String
24fresh :: State.State Int String
25 do n <- State.get
26 do n <- State.get
@@ -27,54 +28,96 @@ fresh =
27 return ("_v" ++ show n)
28 return ("_v" ++ show n)
30-- DEF NAMES
32-- DEF NAMES
32−define :: String -> JS.Expression () -> JS.Statement ()
34− if Help.isOp name then
37− JS.VarRef () (JS.Id () "_op")
39− lvalue =
35+define :: Maybe ModuleName.Canonical -> String -> JS.Expression () -> [JS.Statement ()]
40− JS.LBracket () root (JS.StringLit () name)
36+define maybeHome name body =
37+ if not (Help.isOp name) then
40+ maybe unqualified qualified maybeHome name
42− JS.ExprStmt () (JS.AssignExpr () JS.OpAssign lvalue body)
42+ [ JS.VarDeclStmt () [ JS.varDecl jsName body ] ]
45− JS.VarDeclStmt () [ JS.VarDecl () (JS.Id () (safe name)) (Just body) ]
45+ case maybeHome of
47+ error "can only define infix operators at the top level"
52+ getOpsDictName (Var.TopLevel home)
55+ JS.LBracket () (JS.ref opsDictName) (JS.StringLit () name)
57+ [ JS.VarDeclStmt () [ JS.varDecl opsDictName (JS.refOrObject opsDictName) ]
58+ , JS.ExprStmt () (JS.AssignExpr () JS.OpAssign lvalue body)
48-- INSTANTIATE VARIABLES
63-- INSTANTIATE VARIABLES
50canonical :: Var.Canonical -> JS.Expression ()
66canonical :: Var.Canonical -> JS.Expression ()
51canonical (Var.Canonical home name) =
67canonical (Var.Canonical home name) =
52 if Help.isOp name then
68 if Help.isOp name then
53− JS.BracketRef () (addRoot home "_op") (JS.StringLit () name)
69+ JS.BracketRef () (JS.ref (getOpsDictName home)) (JS.StringLit () name)
56− addRoot home (safe name)
72+ case home of
74+ JS.ref (unqualified name)
77+ JS.ref (unqualified name)
79+ Var.Module moduleName@(ModuleName.Canonical _ rawName) ->
80+ if ModuleName.isNative rawName then
81+ native moduleName name
59−addRoot :: Var.Home -> String -> JS.Expression ()
83+ else
60−addRoot home name =
84+ JS.ref (qualified moduleName name)
65− Var.TopLevel _moduleName ->
86+ Var.TopLevel moduleName ->
66− JS.ref name
87+ JS.ref (qualified moduleName name)
71− Var.Module (ModuleName.Canonical _ moduleName) ->
90+unqualified :: String -> String
72− JS.DotRef () (JS.ref (modulePrefix moduleName)) (JS.Id () name)
91+unqualified =
75−modulePrefix :: ModuleName.Raw -> String
95+qualified :: ModuleName.Canonical -> String -> String
76−modulePrefix moduleName =
96+qualified moduleName name =
97+ moduleToString moduleName ++ "$" ++ removePrimes name
100+native :: ModuleName.Canonical -> String -> JS.Expression ()
101+native moduleName name =
102+ JS.obj [ moduleToString moduleName, name ]
105+getOpsDictName :: Var.Home -> String
106+getOpsDictName home =
110+ Var.Local -> error "infix operators should only be defined in top-level declarations"
111+ Var.BuiltIn -> error "there should be no built-in infix operators"
112+ Var.Module name -> name
113+ Var.TopLevel name -> name
115+ moduleToString moduleName ++ "_ops"
118+moduleToString :: ModuleName.Canonical -> String
119+moduleToString (ModuleName.Canonical _ moduleName) =
77− '$' : List.intercalate "$" moduleName
120+ '_' : List.intercalate "_" moduleName
80swap :: Char -> Char -> Char -> Char
123swap :: Char -> Char -> Char -> Char
@@ -82,14 +125,19 @@ swap from to c =
82 if c == from then to else c
125 if c == from then to else c
85-- SAFE NAMES
129-- SAFE NAMES
87safe :: String -> String
132safe :: String -> String
88safe name =
133safe name =
89− let saferName =
134+ removePrimes $
90− if Set.member name jsReserveds then '$' : name else name
135+ if Set.member name jsReserveds then '$' : name else name
138+removePrimes :: String -> String
92− map (swap '\'' '$') saferName
140+ map (swap '\'' '$') name
95jsReserveds :: Set.Set String
143jsReserveds :: Set.Set String