on master help sign in
Merge branch 'master' of github.com:idris-lang/Idris-dev into issue_3697
commitb71febef068512d1d7dc88618953c4bd76d54ed2 authorRui Barreiro <rui.barreiro@gmail.com> dateTue 13 Jun 2017, 13:49 (9 years ago) parent1f50430edf03ee
8 files changed+101−47
CHANGELOG.md+7−4 src/IRTS/JavaScript/Codegen.hs+37−37 src/IRTS/JavaScript/PrimOp.hs+5−5 test/README.md+1−1 test/TestData.hs+1 test/ffi010/expected+3 test/ffi010/ffi010.idr+43 test/ffi010/run+4
CHANGELOG.md+7−4
@@ -1,13 +1,16 @@
11
22## Tool Updates
33
4−+ New javascript code generator that uses an higher level intermediate
4++ New JavaScript code generator that uses an higher level intermediate
55 representation.
6−
6+
7++ Various optimizations of the novel JavaScript code generator to make
8+ its results fast.
9+
710+ Names are now annotated with their representations over the IDE
811 protocol, which allows IDEs to provide commands that work on special
9− names that don't have syntax, such as case block names
10−
12+ names that don't have syntax, such as case block names.
13+
1114
1215# New in 1.0
1316
src/IRTS/JavaScript/Codegen.hs+37−37
@@ -89,12 +89,7 @@ isYes _ = False
8989codegenJs :: CGConf -> CodeGenerator
9090codegenJs conf ci =
9191 do
92− optim <- isYes <$> lookupEnv "IDRISJS_OPTIM"
9392 debug <- isYes <$> lookupEnv "IDRISJS_DEBUG"
94− if debug then
95− if optim then putStrLn "compiling width idris-js optimizations"
96− else putStrLn "compiling widthout idris-js optimizations"
97− else pure ()
9893 let defs = Map.fromList $ liftDecls ci
9994 let used = Map.elems $ removeDeadCode defs [sMN 0 "runMain"]
10095 if debug then
@@ -118,13 +113,16 @@ codegenJs conf ci =
118113 TIO.writeFile (outputFile ci) $ T.concat [ header conf
119114 , "\"use strict\";\n\n"
120115 , "(function(){\n\n"
116+ -- rts
121117 , runtimeCommon, "\n"
122118 , extraRT, "\n"
123119 , jsbn, "\n"
124− , doPartials (partialApplications stats), "\n"
125− , doHiddenClasses (hiddenClasses stats), "\n"
120+ -- external libraries
126121 , includes, "\n"
127122 , libs, "\n"
123+ -- user code
124+ , doPartials (partialApplications stats), "\n"
125+ , doHiddenClasses (hiddenClasses stats), "\n"
128126 , out, "\n"
129127 , jsName (sMN 0 "runMain"), "();\n"
130128 , "}.call(this))"
@@ -146,6 +144,7 @@ doHiddenClasses :: Set HiddenClass -> Text
146144doHiddenClasses x =
147145 T.intercalate "\n" (map f $ Set.toList x)
148146 where
147+ f p@(HiddenClass n id 0) = jsStmt2Text $ JsDecConst (jsNameHiddenClass p) $ JsObj [("type", JsInt id)]
149148 f p@(HiddenClass n id arity) =
150149 let vars = map dataPartName $ take arity [1..]
151150 in jsStmt2Text $
@@ -360,27 +359,9 @@ cgBody' rt (LApp tailcall (LV (Glob fn)) args) =
360359 let ((y1,y2), y3) = tailCallOptimRefreshArgs (zip argN argVals) Set.empty
361360 addUsedArgsTailCallOptim y3
362361 pure (preDecs, y1 `JsSeq` y2)
363− _ ->
364− do
365− argsFn <- getArgList fn
366− case argsFn of
367− Nothing -> do
368− fn' <- cgName fn
369− pure (preDecs, addRT rt $ jsCurryApp fn' argVals )
370− Just agFn ->
371− do
372− let lenAgFn = length agFn
373− let lenArgs = length args
374− case compare lenAgFn lenArgs of
375− EQ ->
376− pure (preDecs, addRT rt $ jsAppN fname argVals)
377− LT ->
378− pure (preDecs, addRT rt $ jsCurryApp (jsAppN fname (take lenAgFn argVals)) (drop lenAgFn argVals) )
379− GT ->
380− do
381− let part = Partial fn lenArgs lenAgFn
382− addPartial part
383− pure (preDecs, addRT rt $ jsAppN (jsNamePartial part) argVals )
362+ _ -> do
363+ app <- formApp fn argVals
364+ pure (preDecs, addRT rt app)
384365
385366cgBody' rt (LForce (LLazyApp n args)) = cgBody rt (LApp False (LV (Glob n)) args)
386367cgBody' rt (LLazyApp n args) =
@@ -458,18 +439,36 @@ altHasNoProj :: LAlt -> Bool
458439altHasNoProj (LConCase _ _ args _) = args == []
459440altHasNoProj _ = True
460441
442+formApp :: Name -> [JsExpr] -> State CGBodyState JsExpr
443+formApp fn argVals = case specialCall fn of
444+ Just (arity, g) | arity == length argVals -> pure $ g argVals
445+ _ -> do
446+ argsFn <- getArgList fn
447+ fname <- cgName fn
448+ case argsFn of
449+ Nothing -> pure $ jsCurryApp fname argVals
450+ Just agFn -> do
451+ let lenAgFn = length agFn
452+ let lenArgs = length argVals
453+ case compare lenAgFn lenArgs of
454+ EQ -> pure $ JsApp fname argVals
455+ LT -> pure $ jsCurryApp (JsApp fname (take lenAgFn argVals)) (drop lenAgFn argVals)
456+ GT -> do
457+ let part = Partial fn lenArgs lenAgFn
458+ addPartial part
459+ pure $ jsAppN (jsNamePartial part) argVals
460+
461461formCon :: Name -> [JsExpr] -> State CGBodyState JsExpr
462462formCon n args = do
463463 case specialCased n of
464464 Just (ctor, test, match) -> pure $ ctor args
465465 Nothing -> do
466466 (conId, arity) <- getConsId n
467− if (arity > 0)
468− then do
469− let hc = HiddenClass n conId arity
470− addHiddenClass hc
471− pure $ JsNew (JsVar $ jsNameHiddenClass hc) args
472− else pure $ JsInt conId
467+ let hc = HiddenClass n conId arity
468+ addHiddenClass hc
469+ pure $ if (arity > 0)
470+ then JsNew (JsVar $ jsNameHiddenClass hc) args
471+ else JsVar $ jsNameHiddenClass hc
473472
474473formConTest :: Name -> JsExpr -> State CGBodyState JsExpr
475474formConTest n x = do
@@ -477,9 +476,10 @@ formConTest n x = do
477476 Just (ctor, test, match) -> pure $ test x
478477 Nothing -> do
479478 (conId, arity) <- getConsId n
480− if (arity > 0)
481− then pure $ JsBinOp "===" (JsProp x (T.pack "type")) (JsInt conId)
482− else pure $ JsBinOp "===" x (JsInt conId)
479+ pure $ JsBinOp "===" (JsProp x (T.pack "type")) (JsInt conId)
480+ -- if (arity > 0)
481+ -- then pure $ JsBinOp "===" (JsProp x (T.pack "type")) (JsInt conId)
482+ -- else pure $ JsBinOp "===" x (JsInt conId)
483483
484484formProj :: Name -> JsExpr -> Int -> JsExpr
485485formProj n v i =
src/IRTS/JavaScript/PrimOp.hs+5−5
@@ -37,7 +37,7 @@ primDB =
3737 Map.fromList [
3838 item (LPlus ATFloat) False PTAny $ binop "+"
3939 , item (LPlus (ATInt ITChar)) False PTAny $ JsForeign "String.fromCharCode(%0.charCodeAt(0) + %1.charCodeAt(0))"
40− , item (LPlus (ATInt ITNative)) False PTAny $ JsForeign "%0+%1|0"
40+ , item (LPlus (ATInt ITNative)) False PTAny $ binop "+"
4141 , item (LPlus (ATInt (ITFixed IT8))) False PTAny $ JsForeign "%0 + %1 & 0xFF"
4242 , item (LPlus (ATInt (ITFixed IT16))) False PTAny $ JsForeign "%0 + %1 & 0xFFFF"
4343 , item (LPlus (ATInt (ITFixed IT32))) False PTAny $ JsForeign "%0+%1|0"
@@ -46,7 +46,7 @@ primDB =
4646 \[l, r] -> JsForeign "%0.add(%1).and(new $JSRTS.jsbn.BigInteger(%2))" [l,r, JsStr $ show 0xFFFFFFFFFFFFFFFF]
4747 , item (LMinus ATFloat) False PTAny $ binop "-"
4848 , item (LMinus (ATInt ITChar)) False PTAny $ JsForeign "String.fromCharCode(%0.charCodeAt(0) - %1.charCodeAt(0))"
49− , item (LMinus (ATInt ITNative)) False PTAny $ JsForeign "%0-%1|0"
49+ , item (LMinus (ATInt ITNative)) False PTAny $ binop "-"
5050 , item (LMinus (ATInt (ITFixed IT8))) False PTAny $ JsForeign "%0 - %1 & 0xFF"
5151 , item (LMinus (ATInt (ITFixed IT16))) False PTAny $ JsForeign "%0 - %1 & 0xFFFF"
5252 , item (LMinus (ATInt (ITFixed IT32))) False PTAny $ JsForeign "%0-%1|0"
@@ -55,7 +55,7 @@ primDB =
5555 \[l, r] -> JsForeign "%0.subtract(%1).and(new $JSRTS.jsbn.BigInteger(%2))" [l,r, JsStr $ show 0xFFFFFFFFFFFFFFFF]
5656 , item (LTimes ATFloat) False PTAny $ binop "*"
5757 , item (LTimes (ATInt ITChar)) False PTAny $ JsForeign "String.fromCharCode(%0.charCodeAt(0) * %1.charCodeAt(0))"
58− , item (LTimes (ATInt ITNative)) False PTAny $ JsForeign "%0*%1|0"
58+ , item (LTimes (ATInt ITNative)) False PTAny $ binop "*"
5959 , item (LTimes (ATInt (ITFixed IT8))) False PTAny $ JsForeign "%0 * %1 & 0xFF"
6060 , item (LTimes (ATInt (ITFixed IT16))) False PTAny $ JsForeign "%0 * %1 & 0xFFFF"
6161 , item (LTimes (ATInt (ITFixed IT32))) False PTAny $ JsForeign "%0*%1|0"
@@ -71,14 +71,14 @@ primDB =
7171 , item (LSDiv (ATInt (ITFixed IT16))) False PTAny $ JsForeign "%0 / %1"
7272 , item (LSDiv (ATInt (ITFixed IT32))) False PTAny $ JsForeign "%0 / %1 |0"
7373 , item (LSDiv (ATInt (ITFixed IT64))) True PTAny $ JsForeign "%0.divide(%1)"
74− , item (LSDiv (ATInt ITNative)) False PTAny $ JsForeign "%0/%1|0"
74+ , item (LSDiv (ATInt ITNative)) False PTAny $ JsForeign "%0/%1|0" -- we need "|0" in this
7575 , item (LSDiv (ATInt ITBig)) True PTAny $ method "divide"
7676 , item (LURem (ITFixed IT8)) False PTAny $ JsForeign "%0 % %1"
7777 , item (LURem (ITFixed IT16)) False PTAny $ JsForeign "%0 % %1"
7878 , item (LURem (ITFixed IT32)) False PTAny $ JsForeign "(%0>>>0) % (%1>>>0) |0"
7979 , item (LURem (ITFixed IT64)) True PTAny $ method "remainder"
8080 , item (LSRem ATFloat) False PTAny $ binop "%"
81− , item (LSRem (ATInt ITNative)) False PTAny $ JsForeign "%0 % %1 |0"
81+ , item (LSRem (ATInt ITNative)) False PTAny $ binop "%"
8282 , item (LSRem (ATInt (ITFixed IT8))) False PTAny $ JsForeign "%0 % %1"
8383 , item (LSRem (ATInt (ITFixed IT16))) False PTAny $ JsForeign "%0 % %1"
8484 , item (LSRem (ATInt (ITFixed IT32))) False PTAny $ JsForeign "%0 % %1 |0"
test/README.md+1−1
@@ -132,7 +132,7 @@ for the compatible backends are:
132132
133133- `ANY`: choose this if your test will work with any code generator
134134- `C_CG`: choose this to only test against the C code generator
135−- `JS_CG`: choose this to only test against the Node code generator
135+- `NODE_CG`: choose this to only test against the Node code generator
136136- `NONE`: choose this if you don't want your test to be run with multiple code
137137generators (mainly for tests that only perform type checking)
138138
test/TestData.hs+1
@@ -127,6 +127,7 @@ testFamiliesData = [
127127 , ( 7, C_CG )
128128 , ( 8, C_CG )
129129 , ( 9, C_CG )
130+ , ( 10, NODE_CG )
130131 ]),
131132 ("folding", "Folding",
132133 [ ( 1, ANY )]),
test/ffi010/expectednew file+3
@@ -0,0 +1,3 @@
1+start
2+olare
3+end
test/ffi010/ffi010.idrnew file+43
@@ -0,0 +1,43 @@
1+
2+%inline
3+public export
4+jscall : (fname : String) -> (ty : Type) ->
5+ {auto fty : FTy FFI_JS [] ty} -> ty
6+jscall fname ty = foreign FFI_JS fname ty
7+
8+export
9+data ServiceM : Type -> Type where
10+ PureServ : a -> ServiceM a
11+
12+
13+get_jsio : ServiceM a -> JS_IO (Either String a)
14+get_jsio (PureServ x) = do
15+ pure $ Right x
16+
17+export
18+mytst : String -> ServiceM String
19+mytst x = PureServ $ "end"
20+
21+call_fn : (String -> JS_IO String) -> String -> JS_IO String
22+call_fn f x = jscall
23+ "%0(%1)"
24+ ((JsFn (String -> JS_IO String)) -> String -> JS_IO String)
25+ (MkJsFn f)
26+ x
27+
28+mytstJs : String -> JS_IO String
29+mytstJs x = do
30+ r <- get_jsio $ mytst "arst"
31+ case r of
32+ Right k => pure k
33+
34+tst2 : JS_IO String
35+tst2 = call_fn mytstJs "inputmytst"
36+
37+export
38+main : JS_IO ()
39+main = do
40+ putStrLn' "start"
41+ r <- tst2
42+ putStrLn' "olare"
43+ putStrLn' r
test/ffi010/runnew file+4
@@ -0,0 +1,4 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ ffi010.idr -o ffi010
3+./ffi010
4+rm -f ffi010 *.ibc