eval(readFile('Compiled_JavaScript_Compiler')) userNs = [`getp, [`string, 'userNs'], [`get, 'NS']] ometa NSJSParser <: JSParser { isKeyword :x = ?(x == 'once') | super(`isKeyword, x), ns = "[" expr:e "]" -> e, stmt = "while" ( ns | empty -> userNs ):n "(" expr:c ")" stmt:s -> [`begin, [`while, c, [`namespace, n, s]], [`do_or_propagate]] | "break" ( ns | empty -> userNs):n sc -> [`break, n] | "continue" ( ns | empty -> userNs):n sc -> [`continue, n] | "try" ( ns | empty -> userNs):n block:t "catch" "(" "name":e ")" block:c ( "finally" block | empty -> [`get, 'undefined'] ):f -> [`try, [`namespace, n, t], e, [`begin, [`do_or_propagate], c], f] | "throw" ( ns | empty -> userNs):n spacesNoNl expr:e sc -> [`throw, n, e] | "once" block:t -> [`once, t] | ~("while"|"break"|"continue"|"try"|"throw") ^stmt, funcRest = "(" listOf(`formal, ','):fs ")" "{" srcElems:body "}" -> [`func, fs, [`begin, [`once, body]]], primExprHd = "any" -> [`any] | ^primExprHd, topLevel = srcElems:r spaces end -> [`once, r] } do_or_propagate_str = //enter the block only if we're jumping 'if (NS.in_progress) {\n' + 'if (NS.workinglist.length == 1)' + 'throw "Unhandled namespace : " + NS.what\n' + //this is our destination, do whatever it takes 'if (NS.current == NS.destination) {\n' + //'alert("do! " + NS.workinglist)\n' + 'NS.in_progress = false\n' + 'if (NS.action == "break") break\n' + 'if (NS.action == "continue") continue\n' + 'if (NS.action == "throw") throw NS.parameter\n' + 'if (NS.action == "nothing") {}\n' + //this isn't our destination, we're going to propagate '} else {\n' + //'alert("propagate... " + NS.workinglist)\n' + 'if (NS.propagate == "break") break\n' + 'if (NS.propagate == "continue") continue\n' + 'if (NS.propagate == "throw") throw NS.parameter\n' + 'if (NS.propagate == "nothing") {}\n' + '}\n' + '}\n' ometa NSJSTranslator <: JSTranslator { do_or_propagate -> ( do_or_propagate_str ), namespace trans:n trans:s -> ( //save the previous namespace 'try {\n' + //'alert("entering " + ' + n + ')\n' + 'NS.workinglist.push(' + n + ')\n' + 'NS.current = '+ n + '\n' + //the real stuff s + '} finally {\n' + 'NS.workinglist.pop()\n' + 'NS.current = NS.workinglist[NS.workinglist.length-1]\n' + //'alert("exiting out to namespace " + NS.current)\n' + '}\n' ), break trans:n -> ( 'NS.destination = '+ n + '\n' + 'NS.action = "break"\n' + 'NS.propagate = "break"\n' + 'NS.in_progress = true\n' + 'NS.what = "break " + NS.destination\n' + do_or_propagate_str ), continue trans:n -> ( 'NS.destination = '+ n + '\n' + 'NS.action = "continue"\n' + 'NS.propagate = "break"\n' + 'NS.in_progress = true\n' + 'NS.what = "continue " + NS.destination\n' + do_or_propagate_str ), throw trans:n trans:c -> ( 'NS.destination = '+ n + '\n' + 'NS.action = "throw"\n' + 'NS.propagate = "throw"\n' + 'NS.in_progress = true\n' + 'NS.parameter = ' + c + '\n' + 'NS.what = "throw " + NS.destination + " " + NS.parameter\n' + do_or_propagate_str ), once trans:s -> ('do {\n' + s + '}while (false);') } NS = { end_normally : false, workinglist : [new Object()], current : new Object(), destination : {}, action : "", propagate : "", what : "", parameter : "", in_progress : false, debugMode : true, // predefined namespaces userNs : new Object() }