on master help sign in
javascript: split javascript and node target
commitc020e504e8359b8e4d97bc111aecedd1991dffa1 authorraichoo <raichoo@googlemail.com> dateWed 13 Feb 2013, 19:24 (14 years ago) parentf31c76a
10 files changed+430−28
CHANGELOG+1 idris.cabal+1 js/Runtime-node.js+393 js/Runtime.js+3−13 src/IRTS/CodegenJavaScript.hs+10−4 src/IRTS/Compiler.hs+13−7 src/Idris/AbsSyntaxTree.hs+5−1 src/Idris/REPL.hs+2−1 src/Idris/REPLParser.hs+1−1 src/Main.hs+1−1
CHANGELOG+1
@@ -8,6 +8,7 @@ Internal changes:
88* Change unification so that it keeps track of failed constraints in case
99 later information helps to resolve them
1010* Distinguishing parameters and indices in data types
11+* Split 'javascript' target into 'javascript' and 'node'
1112
1213New in 0.9.6:
1314-------------
idris.cabal+1
@@ -48,6 +48,7 @@ Data-files: rts/libidris_rts.a rts/idris_rts.h rts/idris_gc.h
4848 rts/idris_stdfgn.h rts/idris_main.c rts/idris_gmp.h
4949 rts/libtest.c
5050 js/Runtime.js
51+ js/Runtime-node.js
5152Extra-source-files: lib/Makefile lib/*.idr lib/Prelude/*.idr
5253 lib/Network/*.idr lib/Control/*.idr
5354 lib/Control/Monad/*.idr lib/Language/*.idr
js/Runtime-node.jsnew file+393
@@ -0,0 +1,393 @@
1+var __IDRRT__ = {};
2+
3+/** @constructor */
4+__IDRRT__.Type = function(type) {
5+ this.type = type;
6+};
7+
8+__IDRRT__.Int = new __IDRRT__.Type('Int');
9+__IDRRT__.Char = new __IDRRT__.Type('Char');
10+__IDRRT__.String = new __IDRRT__.Type('String');
11+__IDRRT__.Integer = new __IDRRT__.Type('Integer');
12+__IDRRT__.Float = new __IDRRT__.Type('Float');
13+__IDRRT__.Forgot = new __IDRRT__.Type('Forgot');
14+
15+/** @constructor */
16+__IDRRT__.Tailcall = function(f) { this.f = f };
17+
18+/** @constructor */
19+__IDRRT__.Con = function(i,vars) {
20+ this.i = i;
21+ this.vars = vars;
22+};
23+
24+__IDRRT__.tailcall = function(f) {
25+ var __f = f;
26+ var ret;
27+ while (__f) {
28+ f = __f;
29+ __f = null;
30+ ret = f();
31+
32+ if (ret instanceof __IDRRT__.Tailcall) {
33+ __f = ret.f;
34+ } else {
35+ return ret;
36+ }
37+ }
38+};
39+
40+__IDRRT__.print = (function() {
41+ var util = require('util');
42+ return function(s) {
43+ util.print(s);
44+ };
45+})();
46+
47+/*
48+ BigInteger Javascript code taken from:
49+ https://github.com/peterolson
50+*/
51+__IDRRT__.bigInt = (function () {
52+ var base = 10000000, logBase = 7;
53+ var sign = {
54+ positive: false,
55+ negative: true
56+ };
57+
58+ var normalize = function (first, second) {
59+ var a = first.value, b = second.value;
60+ var length = a.length > b.length ? a.length : b.length;
61+ for (var i = 0; i < length; i++) {
62+ a[i] = a[i] || 0;
63+ b[i] = b[i] || 0;
64+ }
65+ for (var i = length - 1; i >= 0; i--) {
66+ if (a[i] === 0 && b[i] === 0) {
67+ a.pop();
68+ b.pop();
69+ } else break;
70+ }
71+ if (!a.length) a = [0], b = [0];
72+ first.value = a;
73+ second.value = b;
74+ };
75+
76+ var parse = function (text, first) {
77+ if (typeof text === "object") return text;
78+ text += "";
79+ var s = sign.positive, value = [];
80+ if (text[0] === "-") {
81+ s = sign.negative;
82+ text = text.slice(1);
83+ }
84+ var text = text.split("e");
85+ if (text.length > 2) throw new Error("Invalid integer");
86+ if (text[1]) {
87+ var exp = text[1];
88+ if (exp[0] === "+") exp = exp.slice(1);
89+ exp = parse(exp);
90+ if (exp.lesser(0)) throw new Error("Cannot include negative exponent part for integers");
91+ while (exp.notEquals(0)) {
92+ text[0] += "0";
93+ exp = exp.prev();
94+ }
95+ }
96+ text = text[0];
97+ if (text === "-0") text = "0";
98+ var isValid = /^([0-9][0-9]*)$/.test(text);
99+ if (!isValid) throw new Error("Invalid integer");
100+ while (text.length) {
101+ var divider = text.length > logBase ? text.length - logBase : 0;
102+ value.push(+text.slice(divider));
103+ text = text.slice(0, divider);
104+ }
105+ var val = bigInt(value, s);
106+ if (first) normalize(first, val);
107+ return val;
108+ };
109+
110+ var goesInto = function (a, b) {
111+ var a = bigInt(a, sign.positive), b = bigInt(b, sign.positive);
112+ if (a.equals(0)) throw new Error("Cannot divide by 0");
113+ var n = 0;
114+ do {
115+ var inc = 1;
116+ var c = bigInt(a.value, sign.positive), t = c.times(10);
117+ while (t.lesser(b)) {
118+ c = t;
119+ inc *= 10;
120+ t = t.times(10);
121+ }
122+ while (c.lesserOrEquals(b)) {
123+ b = b.minus(c);
124+ n += inc;
125+ }
126+ } while (a.lesserOrEquals(b));
127+
128+ return {
129+ remainder: b.value,
130+ result: n
131+ };
132+ };
133+
134+ var bigInt = function (value, s) {
135+ var self = {
136+ value: value,
137+ sign: s
138+ };
139+ var o = {
140+ value: value,
141+ sign: s,
142+ negate: function (m) {
143+ var first = m || self;
144+ return bigInt(first.value, !first.sign);
145+ },
146+ abs: function (m) {
147+ var first = m || self;
148+ return bigInt(first.value, sign.positive);
149+ },
150+ add: function (n, m) {
151+ var s, first = self, second;
152+ if (m) (first = parse(n)) && (second = parse(m));
153+ else second = parse(n, first);
154+ s = first.sign;
155+ if (first.sign !== second.sign) {
156+ first = bigInt(first.value, sign.positive);
157+ second = bigInt(second.value, sign.positive);
158+ return s === sign.positive ?
159+ o.subtract(first, second) :
160+ o.subtract(second, first);
161+ }
162+ normalize(first, second);
163+ var a = first.value, b = second.value;
164+ var result = [],
165+ carry = 0;
166+ for (var i = 0; i < a.length || carry > 0; i++) {
167+ var sum = (a[i] || 0) + (b[i] || 0) + carry;
168+ carry = sum >= base ? 1 : 0;
169+ sum -= carry * base;
170+ result.push(sum);
171+ }
172+ return bigInt(result, s);
173+ },
174+ plus: function (n, m) {
175+ return o.add(n, m);
176+ },
177+ subtract: function (n, m) {
178+ var first = self, second;
179+ if (m) (first = parse(n)) && (second = parse(m));
180+ else second = parse(n, first);
181+ if (first.sign !== second.sign) return o.add(first, o.negate(second));
182+ if (first.sign === sign.negative) return o.subtract(o.negate(second), o.negate(first));
183+ if (o.compare(first, second) === -1) return o.negate(o.subtract(second, first));
184+ var a = first.value, b = second.value;
185+ var result = [],
186+ borrow = 0;
187+ for (var i = 0; i < a.length; i++) {
188+ a[i] -= borrow;
189+ borrow = a[i] < b[i] ? 1 : 0;
190+ var minuend = (borrow * base) + a[i] - b[i];
191+ result.push(minuend);
192+ }
193+ return bigInt(result, sign.positive);
194+ },
195+ minus: function (n, m) {
196+ return o.subtract(n, m);
197+ },
198+ multiply: function (n, m) {
199+ var s, first = self, second;
200+ if (m) (first = parse(n)) && (second = parse(m));
201+ else second = parse(n, first);
202+ s = first.sign !== second.sign;
203+ var a = first.value, b = second.value;
204+ var resultSum = [];
205+ for (var i = 0; i < a.length; i++) {
206+ resultSum[i] = [];
207+ var j = i;
208+ while (j--) {
209+ resultSum[i].push(0);
210+ }
211+ }
212+ var carry = 0;
213+ for (var i = 0; i < a.length; i++) {
214+ var x = a[i];
215+ for (var j = 0; j < b.length || carry > 0; j++) {
216+ var y = b[j];
217+ var product = y ? (x * y) + carry : carry;
218+ carry = product > base ? Math.floor(product / base) : 0;
219+ product -= carry * base;
220+ resultSum[i].push(product);
221+ }
222+ }
223+ var max = -1;
224+ for (var i = 0; i < resultSum.length; i++) {
225+ var len = resultSum[i].length;
226+ if (len > max) max = len;
227+ }
228+ var result = [], carry = 0;
229+ for (var i = 0; i < max || carry > 0; i++) {
230+ var sum = carry;
231+ for (var j = 0; j < resultSum.length; j++) {
232+ sum += resultSum[j][i] || 0;
233+ }
234+ carry = sum > base ? Math.floor(sum / base) : 0;
235+ sum -= carry * base;
236+ result.push(sum);
237+ }
238+ return bigInt(result, s);
239+ },
240+ times: function (n, m) {
241+ return o.multiply(n, m);
242+ },
243+ divmod: function (n, m) {
244+ var s, first = self, second;
245+ if (m) (first = parse(n)) && (second = parse(m));
246+ else second = parse(n, first);
247+ s = first.sign !== second.sign;
248+ if (bigInt(first.value, first.sign).equals(0)) return {
249+ quotient: bigInt([0], sign.positive),
250+ remainder: bigInt([0], sign.positive)
251+ };
252+ if (second.equals(0)) throw new Error("Cannot divide by zero");
253+ var a = first.value, b = second.value;
254+ var result = [], remainder = [];
255+ for (var i = a.length - 1; i >= 0; i--) {
256+ var n = [a[i]].concat(remainder);
257+ var quotient = goesInto(b, n);
258+ result.push(quotient.result);
259+ remainder = quotient.remainder;
260+ }
261+ result.reverse();
262+ return {
263+ quotient: bigInt(result, s),
264+ remainder: bigInt(remainder, first.sign)
265+ };
266+ },
267+ divide: function (n, m) {
268+ return o.divmod(n, m).quotient;
269+ },
270+ over: function (n, m) {
271+ return o.divide(n, m);
272+ },
273+ mod: function (n, m) {
274+ return o.divmod(n, m).remainder;
275+ },
276+ pow: function (n, m) {
277+ var first = self, second;
278+ if (m) (first = parse(n)) && (second = parse(m));
279+ else second = parse(n, first);
280+ var a = first, b = second;
281+ if (b.lesser(0)) return ZERO;
282+ if (b.equals(0)) return ONE;
283+ var result = bigInt(a.value, a.sign);
284+
285+ if (b.mod(2).equals(0)) {
286+ var c = result.pow(b.over(2));
287+ return c.times(c);
288+ } else {
289+ return result.times(result.pow(b.minus(1)));
290+ }
291+ },
292+ next: function (m) {
293+ var first = m || self;
294+ return o.add(first, 1);
295+ },
296+ prev: function (m) {
297+ var first = m || self;
298+ return o.subtract(first, 1);
299+ },
300+ compare: function (n, m) {
301+ var first = self, second;
302+ if (m) (first = parse(n)) && (second = parse(m, first));
303+ else second = parse(n, first);
304+ normalize(first, second);
305+ if (first.value.length === 1 && second.value.length === 1 && first.value[0] === 0 && second.value[0] === 0) return 0;
306+ if (second.sign !== first.sign) return first.sign === sign.positive ? 1 : -1;
307+ var multiplier = first.sign === sign.positive ? 1 : -1;
308+ var a = first.value, b = second.value;
309+ for (var i = a.length - 1; i >= 0; i--) {
310+ if (a[i] > b[i]) return 1 * multiplier;
311+ if (b[i] > a[i]) return -1 * multiplier;
312+ }
313+ return 0;
314+ },
315+ compareAbs: function (n, m) {
316+ var first = self, second;
317+ if (m) (first = parse(n)) && (second = parse(m, first));
318+ else second = parse(n, first);
319+ first.sign = second.sign = sign.positive;
320+ return o.compare(first, second);
321+ },
322+ equals: function (n, m) {
323+ return o.compare(n, m) === 0;
324+ },
325+ notEquals: function (n, m) {
326+ return !o.equals(n, m);
327+ },
328+ lesser: function (n, m) {
329+ return o.compare(n, m) < 0;
330+ },
331+ greater: function (n, m) {
332+ return o.compare(n, m) > 0;
333+ },
334+ greaterOrEquals: function (n, m) {
335+ return o.compare(n, m) >= 0;
336+ },
337+ lesserOrEquals: function (n, m) {
338+ return o.compare(n, m) <= 0;
339+ },
340+ isPositive: function (m) {
341+ var first = m || self;
342+ return first.sign === sign.positive;
343+ },
344+ isNegative: function (m) {
345+ var first = m || self;
346+ return first.sign === sign.negative;
347+ },
348+ isEven: function (m) {
349+ var first = m || self;
350+ return first.value[0] % 2 === 0;
351+ },
352+ isOdd: function (m) {
353+ var first = m || self;
354+ return first.value[0] % 2 === 1;
355+ },
356+ toString: function (m) {
357+ var first = m || self;
358+ var str = "", len = first.value.length;
359+ while (len--) {
360+ str += (base.toString() + first.value[len]).slice(-logBase);
361+ }
362+ while (str[0] === "0") {
363+ str = str.slice(1);
364+ }
365+ if (!str.length) str = "0";
366+ var s = first.sign === sign.positive ? "" : "-";
367+ return s + str;
368+ },
369+ toJSNumber: function (m) {
370+ return +o.toString(m);
371+ },
372+ valueOf: function (m) {
373+ return o.toJSNumber(m);
374+ }
375+ };
376+ return o;
377+ };
378+
379+ var ZERO = bigInt([0], sign.positive);
380+ var ONE = bigInt([1], sign.positive);
381+ var MINUS_ONE = bigInt([1], sign.negative);
382+
383+ var fnReturn = function (a) {
384+ if (typeof a === "undefined") return ZERO;
385+ return parse(a);
386+ };
387+ fnReturn.zero = ZERO;
388+ fnReturn.one = ONE;
389+ fnReturn.minusOne = MINUS_ONE;
390+ return fnReturn;
391+})();
392+
393+var __IDR__ = {};
js/Runtime.js+3−13
@@ -1,4 +1,3 @@
1−var require;
21var __IDRRT__ = {};
32
43/** @constructor */
@@ -38,18 +37,9 @@ __IDRRT__.tailcall = function(f) {
3837 }
3938};
4039
41−__IDRRT__.print = (function(){
42− if (require) {
43− var util = require('util');
44− return function(s) {
45− util.print(s);
46− };
47− } else {
48− return function(s) {
49− console.log(s);
50− };
51− }
52−})();
40+__IDRRT__.print = function(s) {
41+ console.log(s);
42+};
5343
5444/*
5545 BigInteger Javascript code taken from:
src/IRTS/CodegenJavaScript.hs+10−4
@@ -1,6 +1,6 @@
11{-# LANGUAGE PatternGuards #-}
22
3−module IRTS.CodegenJavaScript (codegenJavaScript) where
3+module IRTS.CodegenJavaScript (codegenJavaScript, JSTarget(..)) where
44
55import Idris.AbsSyntax
66import IRTS.Bytecode
@@ -20,14 +20,20 @@ import System.IO
2020idrNamespace :: String
2121idrNamespace = "__IDR__"
2222
23+data JSTarget = Node | JavaScript
24+
2325codegenJavaScript
24− :: [(Name, SDecl)]
26+ :: JSTarget
27+ -> [(Name, SDecl)]
2528 -> FilePath
2629 -> OutputType
2730 -> IO ()
28−codegenJavaScript definitions filename outputType = do
31+codegenJavaScript target definitions filename outputType = do
32+ let runtime = case target of
33+ Node -> "-node"
34+ JavaScript -> ""
2935 path <- getDataDir
30− idrRuntime <- readFile (path ++ "/js/Runtime.js")
36+ idrRuntime <- readFile $ concat [path, "/js/Runtime", runtime, ".js"]
3137 writeFile filename (idrRuntime ++ modules ++ functions ++ mainLoop)
3238 where
3339 def = map (first translateNamespace) definitions
src/IRTS/Compiler.hs+13−7
@@ -65,13 +65,19 @@ compile target f tm
6565 Just f -> liftIO $ writeFile f (dumpDefuns defuns)
6666 iLOG "Building output"
6767 case checked of
68− OK c -> case target of
69− ViaC -> liftIO $ codegenC c f outty hdrs
70− (concatMap mkObj objs)
71− (concatMap mkLib libs) NONE
72− ViaJava -> liftIO $ codegenJava c f outty
73− Bytecode -> liftIO $ dumpBC c f
74− ToJavaScript -> liftIO $ codegenJavaScript c f outty
68+ OK c -> liftIO $ case target of
69+ ViaC ->
70+ codegenC c f outty hdrs
71+ (concatMap mkObj objs)
72+ (concatMap mkLib libs) NONE
73+ ViaJava ->
74+ codegenJava c f outty
75+ ViaJavaScript ->
76+ codegenJavaScript JavaScript c f outty
77+ ViaNode ->
78+ codegenJavaScript Node c f outty
79+
80+ Bytecode -> dumpBC c f
7581 Error e -> fail $ show e
7682 where checkMVs = do i <- getIState
7783 case idris_metavars i \\ primDefs of
src/Idris/AbsSyntaxTree.hs+5−1
@@ -140,7 +140,11 @@ type Idris = StateT IState IO
140140
141141-- Commands in the REPL
142142
143−data Target = ViaC | ViaJava | Bytecode | ToJavaScript
143+data Target = ViaC
144+ | ViaJava
145+ | ViaNode
146+ | ViaJavaScript
147+ | Bytecode
144148 deriving (Show, Eq)
145149
146150data Command = Quit
src/Idris/REPL.hs+2−1
@@ -423,7 +423,8 @@ parseTarget :: String -> Target
423423parseTarget "C" = ViaC
424424parseTarget "Java" = ViaJava
425425parseTarget "bytecode" = Bytecode
426−parseTarget "javascript" = ToJavaScript
426+parseTarget "javascript" = ViaJavaScript
427+parseTarget "node" = ViaNode
427428parseTarget _ = error "unknown target" -- FIXME: partial function
428429
429430parseArgs :: [String] -> [Opt]
src/Idris/REPLParser.hs+1−1
@@ -33,7 +33,7 @@ pCmd = try (do cmd ["q", "quit"]; eof; return Quit)
3333 <|> try (do cmd ["ttshell"]; eof; return TTShell)
3434 <|> try (do cmd ["c", "compile"]; f <- identifier; eof; return (Compile ViaC f))
3535 <|> try (do cmd ["jc", "newcompile"]; f <- identifier; eof; return (Compile ViaJava f))
36− <|> try (do cmd ["js", "javascript"]; f <- identifier; eof; return (Compile ToJavaScript f))
36+ <|> try (do cmd ["js", "javascript"]; f <- identifier; eof; return (Compile ViaJavaScript f))
3737 <|> try (do cmd ["nc", "newcompile"]; f <- identifier; eof; return (NewCompile f))
3838 <|> try (do cmd ["m", "metavars"]; eof; return Metavars)
3939 <|> try (do cmd ["proofs"]; eof; return Proofs)
src/Main.hs+1−1
@@ -92,4 +92,4 @@ usagemsg = "Idris version " ++ ver ++ "\n" ++
9292 "\t--libdir Show library install directory and exit\n" ++
9393 "\t--link Show C library directories and exit (for C linking)\n" ++
9494 "\t--include Show C include directories and exit (for C linking)\n" ++
95− "\t--target [target] Type the target: C, Java, bytecode, javascript\n"
95+ "\t--target [target] Type the target: C, Java, bytecode, javascript, node\n"