#lang scheme/base
(require (for-syntax scheme/base
(file "syntax-internal.ss"))
(file "../test-base.ss")
(file "render.ss")
(file "struct.ss")
(file "syntax.ss"))
(define-syntax (test-js stx)
(syntax-case stx ()
[(_ message actual expected)
(with-handlers ([exn? (lambda (exn)
#`(test-case message
(fail #,(format "Could not compile javascript: ~a" (exn-message exn)))))])
(with-syntax ([expanded (expand-javascript #'actual)])
#`(test-case message
(with-check-info (['compiled expanded])
(check-equal? (javascript->string expanded)
expected)))))]))
(define syntax-tests
(test-suite "syntax.ss"
(test-js "decl: function"
(function sum3 (a b c) (return (+ a b c)))
"function sum3(a, b, c) { return a + b + c; }")
(test-js "decl: anonymous function"
(function (a b c) (return (+ a b c)))
"function(a, b, c) { return a + b + c; };")
(test-js "decl: anonymous function as an expression argument"
(+ (,(js (function (a b c) (return (+ a b c))))) 1)
"(function(a, b, c) { return a + b + c; })() + 1;")
(test-js "decl: var"
(var [x 1] [y (+ 2 3)])
"var x = 1, y = 2 + 3;")
(test-js "decl: var unquote"
(var [,(make-Identifier #f 'x) 1] [y ,(+ 2 3)])
"var x = 1, y = 5;")
(test-js "stmt: empty begin" (!begin) "")
(test-js "stmt: begin"
(!begin (+ 1 2 3)
(!begin (var [x (+ 2 3 4)]))
(+ 3 4 5))
"1 + 2 + 3; var x = 2 + 3 + 4; 3 + 4 + 5;")
(test-js "stmt: empty block" (!block) "{}")
(test-js "stmt: block"
(!block (+ 1 2 3)
(!block (var [x (+ 2 3 4)]))
(+ 3 4 5))
"{ 1 + 2 + 3; { var x = 2 + 3 + 4; } 3 + 4 + 5; }")
(test-js "stmt: if version 1"
(if x (return y))
"if (x) return y; ")
(test-js "stmt: if version 2"
(if x (return y) (return z))
"if (x) return y; else return z;")
(test-js "stmt: for-in version 1"
(for-in (x (!array 1 2 3))
(alert x))
"for (x in [ 1, 2, 3 ]) alert(x);")
(test-js "stmt: for-in version 2"
(for-in ((var x) (!array 1 2 3))
(alert x))
"for (var x in [ 1, 2, 3 ]) alert(x);")
(test-js "stmt: for-in version 3"
(for-in ([key val] (!object [a 1] [b 2] [c 3]))
(alert (+ key ": " val)))
"for (key, val in { a: 1, b: 2, c: 3 }) alert(key + \": \" + val);")
(test-js "stmt: for-in version 4"
(for-in ((var key val) (!object [a 1] [b 2] [c 3]))
(alert (+ key ": " val)))
"for (var key, val in { a: 1, b: 2, c: 3 }) alert(key + \": \" + val);")
(test-js "stmt: try version 1"
(try (+ 1 2) (+ 2 3) (catch e (+ 3 4)) (finally (+ 4 5)))
"try { 1 + 2; 2 + 3; } catch (e) { 3 + 4; } finally { 4 + 5; }")
(test-js "stmt: try version 2"
(try (+ 1 2) (catch e (+ 3 4)) (finally (+ 4 5)))
"try { 1 + 2; } catch (e) { 3 + 4; } finally { 4 + 5; }")
(test-js "stmt: unquote"
(!begin (while (< x 10) (post++ x))
,(js (while (> x 5) (post-- x))
(while (< x 15) (pre++ x))))
"while (x < 10) x++; while (x > 5) x--; while (x < 15) ++x;")
(test-js "stmt: unquote-splicing"
(!begin (while (< x 10) (post++ x))
,@(list (js (while (> x 5) (post-- x)))
(js (while (< x 15) (pre++ x)))))
"while (x < 10) x++; while (x > 5) x--; while (x < 15) ++x;")
(test-js "expr: array" (!array x "y" 123) "[ x, \"y\", 123 ];")
(test-js "expr: object" (!object [x 1] ["y" 2] [3 4]) "{ x: 1, \"y\": 2, 3: 4 };")
(test-js "expr: dot" (!dot x y z) "x.y.z;")
(test-js "expr: index" (!index (getStuff 1) (+ 2 3)) "getStuff(1)[2 + 3];")
(test-js "expr: infix" (+ 1 2 3) "1 + 2 + 3;")
(test-js "expr: prefix" (pre++ x) "++x;")
(test-js "expr: postfix" (post++ x) "x++;")
(test-js "expr: call" (x y z) "x(y, z);")
(test-js "expr: conditional"
(? (== a b) c d)
"a == b ? c : d;")
(test-js "expr: anonymous function wrapper"
((function () (alert "Dave")))
"(function() { alert(\"Dave\"); })();")
(test-js "expr: unquote"
(return (+ 1 ,(js (/ 4 2)) 3))
"return 1 + 4 / 2 + 3;")
(test-js "expr: function with local variable declarations"
((function () (var [x 1]) (return x)))
"(function() { var x = 1; return x; })();")
))
(provide syntax-tests)