diff --git a/Foundation/CPPredicate/CPComparisonPredicate.j b/Foundation/CPPredicate/CPComparisonPredicate.j index cac3d5fe0..f028b595c 100644 --- a/Foundation/CPPredicate/CPComparisonPredicate.j +++ b/Foundation/CPPredicate/CPComparisonPredicate.j @@ -320,8 +320,8 @@ lhs = lhs.stripDiacritics(); rhs = rhs.stripDiacritics(); } - var commut = (_options & CPCaseInsensitivePredicateOption) ? "gi":"g", - reg = new RegExp(rhs.escapeForRegExp(),commut); + var commut = (_options & CPCaseInsensitivePredicateOption) ? "i":"", + reg = new RegExp("^" + rhs.escapeForRegExp() + "$",commut); return reg.test(lhs); case CPBeginsWithPredicateOperatorType: var range = CPMakeRange(0, MIN([lhs length], [rhs length])); diff --git a/Foundation/CPURLConnection.j b/Foundation/CPURLConnection.j index 94738193f..3f86ef8d2 100644 --- a/Foundation/CPURLConnection.j +++ b/Foundation/CPURLConnection.j @@ -154,6 +154,31 @@ var CPURLConnectionDelegate = nil; return [[self alloc] _initWithRequest:aRequest queue:aQueue completionHandler:aHandler]; } +/* + Loads the data for a URL request and returns a Promise. + @param aRequest contains the URL to obtain data from. + @discussion If the request completes successfully, the data parameter of the function contains the resource data, and the error parameter is nil. If the request fails, the data parameter is nil and the error parameter contain information about the failure. + + Typical use can be like this: + + - (async @action)doAction:(id)sender { + const { response, data, error } = await [CPURLConnection sendAsynchronousRequest:[CPURLRequest requestWithURL:@"http://cappuccino.dev"]]; + if (error == nil) { + //do the stuff... + } else { + // Handle errors + } + } +*/ ++ (async JSObject /* { response: CPURLResponse, data: CPData, error: CPError } */)sendAsynchronousRequest:(CPURLRequest)aRequest +{ + return new Promise((resolve, reject) => + [[self alloc] _initWithRequest:aRequest + queue:[CPOperationQueue mainQueue] + completionHandler:(aResponse, aData, anError) => resolve( {response: aResponse, data: aData, error:anError })] + ); +} + /* Creates a url connection with a delegate to monitor the request progress. @param aRequest contains the URL to obtain data from diff --git a/Objective-J/FileExecutable.js b/Objective-J/FileExecutable.js index 3b01c79fc..613f97c6b 100644 --- a/Objective-J/FileExecutable.js +++ b/Objective-J/FileExecutable.js @@ -66,7 +66,7 @@ FileExecutable.prototype = new Executable(); var compile = function(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary) { - var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {}); + var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {ecmaVersion: 2022}); acornOptions.preprocessGetIncludeFile = function(filePath, isQuoted) { var referenceURL = new CFURL(".", aURL), // Remove the filename from the url diff --git a/Objective-J/Includes.js b/Objective-J/Includes.js index 296cda757..5346db26a 100644 --- a/Objective-J/Includes.js +++ b/Objective-J/Includes.js @@ -47,9 +47,9 @@ #include "StaticResource.js" #include "Preprocessor.js" #include "source-map.js" -#include "acorn.js" -#include "acornwalk.js" -#include "ObjJAcornCompiler.js" +#include "../node_modules/acorn-walk/dist/walk.js" +#include "../node_modules/objj-parser/dist/objj-parser.js" +#include "../node_modules/objj-transpiler/dist/objj-transpiler.cjs" #include "FileDependency.js" #include "Executable.js" #include "FileExecutable.js" diff --git a/Objective-J/Jakefile b/Objective-J/Jakefile index fac488ec6..b1e2112a3 100644 --- a/Objective-J/Jakefile +++ b/Objective-J/Jakefile @@ -35,10 +35,10 @@ var path = require("path"); var fs = require("fs"); var terser = require("terser"); -var walk = require("./acornwalk").acorn.walk; +var walk = require("acorn-walk"); acorn = {walk: walk}; -acorn = require("./acorn").acorn; -var compiler = require("./ObjJAcornCompiler").ObjJCompiler; +acorn = require("objj-parser"); +var compiler = require("objj-transpiler"); const term = ObjectiveJ.term; const utilsFile = ObjectiveJ.utils.file; @@ -136,7 +136,7 @@ async function gcc(inputFilePath, outputFilePath, flags, compress) term.stream.print("Building... \0green(" + outputFilePath +"\0)"); var source = fs.readFileSync(inputFilePath, { charset : "utf8" }).toString(); var compilerOptions = compiler.parseGccCompilerFlags(flags.join(" ")); - var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {}); + var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {ecmaVersion: 2022}); acornOptions.preprocessGetIncludeFile = function(filePath, isQuoted) { var includeContent = fs.readFileSync(filePath, { charset : "utf8" }).toString(); diff --git a/Objective-J/ObjJAcornCompiler.js b/Objective-J/ObjJAcornCompiler.js deleted file mode 100644 index 47fca86c5..000000000 --- a/Objective-J/ObjJAcornCompiler.js +++ /dev/null @@ -1,3926 +0,0 @@ -// ObjJAcornCompiler was written by Martin Carlberg and released under -// an MIT license. -// -// Git repositories for ObjJAcornCompiler are available at -// -// https://github.com/mrcarlberg/ObjJAcornCompiler.git -// -// Please use the [github bug tracker][ghbt] to report issues. -// -// [ghbt]: https://github.com/mrcarlberg/ObjJAcornCompiler/issues -// -// This file defines the main compiler interface. -// -// Copyright 2013, 2014, 2015, 2016, Martin Carlberg. - - -(function(mod) -{ - mod(exports.ObjJCompiler || (exports.ObjJCompiler = {}), exports.acorn || acorn, (exports.acorn || acorn).walk, typeof exports.sourceMap != "undefined" ? exports.sourceMap : (typeof module != "undefined" && typeof module.exports === "object" ? module.exports : null)); // Plain browser env -})(function(exports, acorn, walk, sourceMap) -{ -"use strict"; - -exports.version = "0.3.7"; - -var Scope = function(prev, base) -{ - this.vars = Object.create(null); - - if (base) for (var key in base) this[key] = base[key]; - this.prev = prev; - - if (prev) - { - this.compiler = prev.compiler; - this.nodeStack = prev.nodeStack.slice(0); - this.nodePriorStack = prev.nodePriorStack.slice(0); - this.nodeStackOverrideType = prev.nodeStackOverrideType.slice(0); - } - else - { - this.nodeStack = []; - this.nodePriorStack = []; - this.nodeStackOverrideType = []; - } -} - -Scope.prototype.toString = function() -{ - return this.ivars ? "ivars: " + JSON.stringify(this.ivars) : ""; -} - -Scope.prototype.compiler = function() -{ - return this.compiler; -} - -Scope.prototype.rootScope = function() -{ - return this.prev ? this.prev.rootScope() : this; -} - -Scope.prototype.isRootScope = function() -{ - return !this.prev; -} - -Scope.prototype.currentClassName = function() -{ - return this.classDef ? this.classDef.name : this.prev ? this.prev.currentClassName() : null; -} - -Scope.prototype.currentProtocolName = function() -{ - return this.protocolDef ? this.protocolDef.name : this.prev ? this.prev.currentProtocolName() : null; -} - -Scope.prototype.getIvarForCurrentClass = function(/* String */ ivarName) -{ - if (this.ivars) - { - var ivar = this.ivars[ivarName]; - if (ivar) - return ivar; - } - - var prev = this.prev; - - // Stop at the class declaration - if (prev && !this.classDef) - return prev.getIvarForCurrentClass(ivarName); - - return null; -} - -Scope.prototype.getLvarScope = function(/* String */ lvarName, /* BOOL */ stopAtMethod) -{ - if (this.vars) - { - var lvar = this.vars[lvarName]; - if (lvar) - return this; - } - - var prev = this.prev; - - // Stop at the method declaration - if (prev && (!stopAtMethod || !this.methodType)) - return prev.getLvarScope(lvarName, stopAtMethod); - - return this; -} - -Scope.prototype.getLvar = function(/* String */ lvarName, /* BOOL */ stopAtMethod) -{ - if (this.vars) - { - var lvar = this.vars[lvarName]; - if (lvar) - return lvar; - } - - var prev = this.prev; - - // Stop at the method declaration - if (prev && (!stopAtMethod || !this.methodType)) - return prev.getLvar(lvarName, stopAtMethod); - - return null; -} - -Scope.prototype.getVarScope = function() -{ - var prev = this.prev; - - return prev ? prev.getVarScope() : this; -} - -Scope.prototype.currentMethodType = function() -{ - return this.methodType ? this.methodType : this.prev ? this.prev.currentMethodType() : null; -} - -Scope.prototype.copyAddedSelfToIvarsToParent = function() -{ - if (this.prev && this.addedSelfToIvars) for (var key in this.addedSelfToIvars) - { - var addedSelfToIvar = this.addedSelfToIvars[key], - scopeAddedSelfToIvar = (this.prev.addedSelfToIvars || (this.prev.addedSelfToIvars = Object.create(null)))[key] || (this.prev.addedSelfToIvars[key] = []); - - scopeAddedSelfToIvar.push.apply(scopeAddedSelfToIvar, addedSelfToIvar); // Append at end in parent scope - } -} - -Scope.prototype.addMaybeWarning = function(warning) -{ - var rootScope = this.rootScope(), - maybeWarnings = rootScope._maybeWarnings; - - if (!maybeWarnings) - rootScope._maybeWarnings = maybeWarnings = [warning]; - else - { - var lastWarning = maybeWarnings[maybeWarnings.length - 1]; - - // MessageSendExpression (and maybe others) will walk some expressions multible times and - // possible generate warnings multible times. Here we check if this warning is already added - if (!lastWarning.isEqualTo(warning)) - maybeWarnings.push(warning); - } -} - -Scope.prototype.variablesNotReadWarnings = function() -{ - var compiler = this.compiler; - - // The warning option must be turned on. We can't be top scope. The scope must have some variables - if (compiler.options.warnings.includes(warningUnusedButSetVariable) && this.prev && this.vars) for (var key in this.vars) - { - var lvar = this.vars[key]; - - if (!lvar.isRead && lvar.type === "var") - { - //print("Variable '" + key + "' is never read: " + lvar.type + ", line: " + lvar.node.start); - compiler.addWarning(createMessage("Variable '" + key + "' is never read", lvar.node, compiler.source)); - } - } -} - -Scope.prototype.maybeWarnings = function() -{ - return this.rootScope()._maybeWarnings; -} - -Scope.prototype.pushNode = function(node, overrideType) -{ - // Here we push 3 things to a stack. The node, override type and an array that can keep track of prior nodes on this level. - // The current node is also pushed to the last prior array. - // Special case when node is the same as the parent node. This happends when using an override type when walking the AST - // The same prior list is then used instead of a new empty one. - var nodePriorStack = this.nodePriorStack, - length = nodePriorStack.length, - lastPriorList = length ? nodePriorStack[length - 1] : null, - lastNode = length ? this.nodeStack[length - 1] : null; - // First add this node to parent list of nodes, if it has one - if (lastPriorList) { - if (lastNode !== node) { - // If not the same node push the node - lastPriorList.push(node); - } - } - // Use the last prior list if it is the same node - nodePriorStack.push(lastNode === node ? lastPriorList : []); - this.nodeStack.push(node); - this.nodeStackOverrideType.push(overrideType); -} - -Scope.prototype.popNode = function() -{ - this.nodeStackOverrideType.pop(); - this.nodePriorStack.pop(); - return this.nodeStack.pop(); -} - -Scope.prototype.currentNode = function() -{ - var nodeStack = this.nodeStack; - return nodeStack[nodeStack.length - 1]; -} - -Scope.prototype.currentOverrideType = function() -{ - var nodeStackOverrideType = this.nodeStackOverrideType; - return nodeStackOverrideType[nodeStackOverrideType.length - 1]; -} - -Scope.prototype.priorNode = function() -{ - var nodePriorStack = this.nodePriorStack, - length = nodePriorStack.length; - - if (length > 1) { - var parent = nodePriorStack[length - 2], - l = parent.length; - return parent[l - 2] || null; - } - return null; -} - -Scope.prototype.formatDescription = function(index, formatDescription, useOverrideForNode) -{ - var nodeStack = this.nodeStack, - length = nodeStack.length; - - index = index || 0; - if (index >= length) - return null; - - // Get the nodes backwards from the stack - var i = length - index - 1; - var currentNode = nodeStack[i]; - var currentFormatDescription = formatDescription || this.compiler.formatDescription; - // Get the parent descriptions except if no formatDescription was provided, then it is the root description - var parentFormatDescriptions = formatDescription ? formatDescription.parent : currentFormatDescription; - - var nextFormatDescription; - if (parentFormatDescriptions) { - var nodeType = useOverrideForNode === currentNode ? this.nodeStackOverrideType[i] : currentNode.type; - //console.log("nodeType: " + nodeType + ", (useOverrideForNode === currentNode):" + + !!(useOverrideForNode === currentNode)); - nextFormatDescription = parentFormatDescriptions[nodeType]; - if (useOverrideForNode === currentNode && !nextFormatDescription) { - //console.log("Stop"); - return null; - } - } - - //console.log("index: " + index + ", currentNode: " + JSON.stringify(currentNode) + ", currentFormatDescription: " + JSON.stringify(currentFormatDescription) + ", nextFormatDescription: " + JSON.stringify(nextFormatDescription)); - - if (nextFormatDescription) { - // Check for more 'parent' attributes or return nextFormatDescription - return this.formatDescription(index + 1, nextFormatDescription); - } else { - // Check for a virtual node one step up in the stack - nextFormatDescription = this.formatDescription(index + 1, formatDescription, currentNode); - if (nextFormatDescription) - return nextFormatDescription; - else { - // Ok, we have found a format description (currentFormatDescription). - // Lets check if we have any other descriptions dependent on the prior node. - var priorFormatDescriptions = currentFormatDescription.prior; - if (priorFormatDescriptions) { - var priorNode = this.priorNode(), - priorFormatDescription = priorFormatDescriptions[priorNode ? priorNode.type : "None"]; - if (priorFormatDescription) - return priorFormatDescription; - } - return currentFormatDescription; - } - } -} - -var FunctionScope = function(prev, base) -{ - Scope.call(this, prev, base); -} - -FunctionScope.prototype = Object.create(Scope.prototype); - -FunctionScope.prototype.constructor = FunctionScope; - -FunctionScope.prototype.getVarScope = function() -{ - return this; -} - -FunctionScope.prototype.variablesNotReadWarnings = function() -{ - Scope.prototype.variablesNotReadWarnings.call(this); - - var prev = this.prev; - - // Any possible hoisted variable in this scope has to be moved to the previous scope if it is not declared in the previsous scope - // We can't be top scope. The scope must have some possible hoisted variables - if (prev && this.possibleHoistedVariables) for (var key in this.possibleHoistedVariables) - { - var possibleHoistedVariable = this.possibleHoistedVariables[key]; - - if (possibleHoistedVariable) - { - var varInPrevScope = prev.vars && prev.vars[key]; - - if (varInPrevScope != null) - { - var prevPossibleHoistedVariable = (prev.possibleHoistedVariables || (prev.possibleHoistedVariables = Object.create(null)))[key]; - - if (prevPossibleHoistedVariable == null) { - prev.possibleHoistedVariables[key] = possibleHoistedVariable; - } else { - throw new Error("Internal inconsistency, previous scope should not have this possible hoisted variable '" + key + "'"); - } - } - } - } -} - - -var GlobalVariableMaybeWarning = function(/* String */ aMessage, /* SpiderMonkey AST node */ node, /* String */ code) -{ - this.message = createMessage(aMessage, node, code); - this.node = node; -} - -GlobalVariableMaybeWarning.prototype.checkIfWarning = function(/* Scope */ st) -{ - var identifier = this.node.name; - return !st.getLvar(identifier) && typeof global[identifier] === "undefined" && (typeof window === 'undefined' || typeof window[identifier] === "undefined") && !st.compiler.getClassDef(identifier); -} - -GlobalVariableMaybeWarning.prototype.isEqualTo = function(/* GlobalVariableMaybeWarning */ aWarning) -{ - if (this.message.message !== aWarning.message.message) return false; - if (this.node.start !== aWarning.node.start) return false; - if (this.node.end !== aWarning.node.end) return false; - - return true; -} - -function StringBuffer(useSourceNode, file, sourceContent) -{ - if (useSourceNode) { - this.rootNode = new sourceMap.SourceNode(); - this.concat = this.concatSourceNode; - this.toString = this.toStringSourceNode; - this.isEmpty = this.isEmptySourceNode; - this.appendStringBuffer = this.appendStringBufferSourceNode; - this.length = this.lengthSourceNode; - if (file) { - var fileString = file.toString(), - filename = fileString.substr(fileString.lastIndexOf('/') + 1), - sourceRoot = fileString.substr(0, fileString.lastIndexOf('/') + 1); - - this.filename = filename; - - if (sourceRoot.length > 0) - this.sourceRoot = sourceRoot; - if (sourceContent != null) - this.rootNode.setSourceContent(filename, sourceContent); - } - - if (sourceContent != null) - this.sourceContent = sourceContent; - } else { - this.atoms = []; - this.concat = this.concatString; - this.toString = this.toStringString; - this.isEmpty = this.isEmptyString; - this.appendStringBuffer = this.appendStringBufferString; - this.length = this.lengthString; - } -} - -StringBuffer.prototype.toStringString = function() -{ - return this.atoms.join(""); -} - -StringBuffer.prototype.toStringSourceNode = function() -{ - return this.rootNode.toStringWithSourceMap({file: this.filename + "s", sourceRoot:this.sourceRoot}); -} - -StringBuffer.prototype.concatString = function(aString) -{ - this.atoms.push(aString); -} - -StringBuffer.prototype.concatSourceNode = function(aString, node, originalName) -{ - if (node) { - //console.log("Snippet: " + aString + ", line: " + node.loc.start.line + ", column: " + node.loc.start.column + ", source: " + node.loc.source); - this.rootNode.add(new sourceMap.SourceNode(node.loc.start.line, node.loc.start.column, node.loc.source, aString, originalName)); - } else - this.rootNode.add(aString); - if (!this.notEmpty) - this.notEmpty = true; -} - -// '\n' will indent. '\n\0' will not indent. '\n\1' will indent one more then the current indent level. -// '\n\-1' will indent one less then the current indent level. Numbers from 0-9 can me used. -StringBuffer.prototype.concatFormat = function(aString) -{ - if (!aString) return; - var lines = aString.split("\n"), - size = lines.length; - if (size > 1) { - this.concat(lines[0]); - for (var i = 1; i < size; i++) { - var line = lines[i]; - this.concat("\n"); - if (line.slice(0, 1) === "\\") { - var numberLength = 1; - var indent = line.slice(1, 1 + numberLength); - if (indent === '-') { - numberLength = 2; - indent = line.slice(1, 1 + numberLength); - } - var indentationNumber = parseInt(indent); - if (indentationNumber) { - this.concat(indentationNumber > 0 ? indentation + Array(indentationNumber * indentationSpaces + 1).join(indentType) : indentation.substring(indentationSize * -indentationNumber)); - } - line = line.slice(1 + numberLength); - } else if (line || i === size - 1) { - // Ident if there is something between line breaks or the last linebreak - this.concat(indentation); - } - if (line) this.concat(line); - } - } else - this.concat(aString); -} - -StringBuffer.prototype.isEmptyString = function() -{ - return this.atoms.length !== 0; -} - -StringBuffer.prototype.isEmptySourceNode = function() -{ - return this.notEmpty; -} - -StringBuffer.prototype.appendStringBufferString = function(stringBuffer) -{ - // We can't do 'this.atoms.push.apply(this.atoms, stringBuffer.atoms);' as JavaScriptCore (WebKit) has a limit on number of arguments at 65536. - // Other browsers also have simular limits. - var thisAtoms = this.atoms; - var thisLength = thisAtoms.length; - var stringBufferAtoms = stringBuffer.atoms; - var stringBufferLength = stringBufferAtoms.length; - - thisAtoms.length = thisLength + stringBufferLength; - - for (var i = 0; i < stringBufferLength; i++) { - thisAtoms[thisLength + i] = stringBufferAtoms[i]; - } -} - -StringBuffer.prototype.appendStringBufferSourceNode = function(stringBuffer) -{ - this.rootNode.add(stringBuffer.rootNode); -} - -StringBuffer.prototype.lengthString = function() -{ - return this.atoms.length; -} - -StringBuffer.prototype.lengthSourceNode = function() -{ - return this.rootNode.children.length; -} - -// Both the ClassDef and ProtocolDef conforms to a 'protocol' (That we can't declare in Javascript). -// Both Objects have the attribute 'protocols': Array of ProtocolDef that they conform to -// Both also have the functions: addInstanceMethod, addClassMethod, getInstanceMethod and getClassMethod -// classDef = {"className": aClassName, "superClass": superClass , "ivars": myIvars, "instanceMethods": instanceMethodDefs, "classMethods": classMethodDefs, "protocols": myProtocols}; -var ClassDef = function(isImplementationDeclaration, name, superClass, ivars, instanceMethods, classMethods, protocols) -{ - this.name = name; - if (superClass) - this.superClass = superClass; - if (ivars) - this.ivars = ivars; - if (isImplementationDeclaration) { - this.instanceMethods = instanceMethods || Object.create(null); - this.classMethods = classMethods || Object.create(null); - } - if (protocols) - this.protocols = protocols; -} - -ClassDef.prototype.addInstanceMethod = function(methodDef) { - this.instanceMethods[methodDef.name] = methodDef; -} - -ClassDef.prototype.addClassMethod = function(methodDef) { - this.classMethods[methodDef.name] = methodDef; -} - -ClassDef.prototype.listOfNotImplementedMethodsForProtocols = function(protocolDefs) { - var resultList = [], - instanceMethods = this.getInstanceMethods(), - classMethods = this.getClassMethods(); - - for (var i = 0, size = protocolDefs.length; i < size; i++) - { - var protocolDef = protocolDefs[i], - protocolInstanceMethods = protocolDef.requiredInstanceMethods, - protocolClassMethods = protocolDef.requiredClassMethods, - inheritFromProtocols = protocolDef.protocols; - - if (protocolInstanceMethods) for (var methodName in protocolInstanceMethods) { - var methodDef = protocolInstanceMethods[methodName]; - - if (!instanceMethods[methodName]) - resultList.push({"methodDef": methodDef, "protocolDef": protocolDef}); - } - - if (protocolClassMethods) for (var methodName in protocolClassMethods) { - var methodDef = protocolClassMethods[methodName]; - - if (!classMethods[methodName]) - resultList.push({"methodDef": methodDef, "protocolDef": protocolDef}); - } - - if (inheritFromProtocols) - resultList = resultList.concat(this.listOfNotImplementedMethodsForProtocols(inheritFromProtocols)); - } - - return resultList; -} - -ClassDef.prototype.getInstanceMethod = function(name) { - var instanceMethods = this.instanceMethods; - - if (instanceMethods) { - var method = instanceMethods[name]; - - if (method) - return method; - } - - var superClass = this.superClass; - - if (superClass) - return superClass.getInstanceMethod(name); - - return null; -} - -ClassDef.prototype.getClassMethod = function(name) { - var classMethods = this.classMethods; - if (classMethods) { - var method = classMethods[name]; - - if (method) - return method; - } - - var superClass = this.superClass; - - if (superClass) - return superClass.getClassMethod(name); - - return null; -} - -// Return a new Array with all instance methods -ClassDef.prototype.getInstanceMethods = function() { - var instanceMethods = this.instanceMethods; - if (instanceMethods) { - var superClass = this.superClass, - returnObject = Object.create(null); - if (superClass) { - var superClassMethods = superClass.getInstanceMethods(); - for (var methodName in superClassMethods) - returnObject[methodName] = superClassMethods[methodName]; - } - - for (var methodName in instanceMethods) - returnObject[methodName] = instanceMethods[methodName]; - - return returnObject; - } - - return []; -} - -// Return a new Array with all class methods -ClassDef.prototype.getClassMethods = function() { - var classMethods = this.classMethods; - if (classMethods) { - var superClass = this.superClass, - returnObject = Object.create(null); - if (superClass) { - var superClassMethods = superClass.getClassMethods(); - for (var methodName in superClassMethods) - returnObject[methodName] = superClassMethods[methodName]; - } - - for (var methodName in classMethods) - returnObject[methodName] = classMethods[methodName]; - - return returnObject; - } - - return []; -} - -// protocolDef = {"name": aProtocolName, "protocols": inheritFromProtocols, "requiredInstanceMethods": requiredInstanceMethodDefs, "requiredClassMethods": requiredClassMethodDefs}; -var ProtocolDef = function(name, protocols, requiredInstanceMethodDefs, requiredClassMethodDefs) -{ - this.name = name; - this.protocols = protocols; - if (requiredInstanceMethodDefs) - this.requiredInstanceMethods = requiredInstanceMethodDefs; - if (requiredClassMethodDefs) - this.requiredClassMethods = requiredClassMethodDefs; -} - -ProtocolDef.prototype.addInstanceMethod = function(methodDef) { - (this.requiredInstanceMethods || (this.requiredInstanceMethods = Object.create(null)))[methodDef.name] = methodDef; -} - -ProtocolDef.prototype.addClassMethod = function(methodDef) { - (this.requiredClassMethods || (this.requiredClassMethods = Object.create(null)))[methodDef.name] = methodDef; -} - -ProtocolDef.prototype.getInstanceMethod = function(name) { - var instanceMethods = this.requiredInstanceMethods; - - if (instanceMethods) { - var method = instanceMethods[name]; - - if (method) - return method; - } - - var protocols = this.protocols; - - for (var i = 0, size = protocols.length; i < size; i++) { - var protocol = protocols[i], - method = protocol.getInstanceMethod(name); - - if (method) - return method; - } - - return null; -} - -ProtocolDef.prototype.getClassMethod = function(name) { - var classMethods = this.requiredClassMethods; - - if (classMethods) { - var method = classMethods[name]; - - if (method) - return method; - } - - var protocols = this.protocols; - - for (var i = 0, size = protocols.length; i < size; i++) { - var protocol = protocols[i], - method = protocol.getClassMethod(name); - - if (method) - return method; - } - - return null; -} - -var TypeDef = function(name) -{ - this.name = name; -} - -// methodDef = {"types": types, "name": selector} -var MethodDef = function(name, types) -{ - this.name = name; - this.types = types; -} - -var reservedIdentifiers = acorn.makePredicate("self _cmd undefined localStorage arguments"); - -var wordPrefixOperators = acorn.makePredicate("delete in instanceof new typeof void"); - -var isLogicalBinary = acorn.makePredicate("LogicalExpression BinaryExpression"); - -var warningUnusedButSetVariable = {name: "unused-but-set-variable"}; -var warningShadowIvar = {name: "shadow-ivar"}; -var warningCreateGlobalInsideFunctionOrMethod = {name: "create-global-inside-function-or-method"}; -var warningUnknownClassOrGlobal = {name: "unknown-class-or-global"}; -var warningUnknownIvarType = {name: "unknown-ivar-type"}; - -var AllWarnings = [warningUnusedButSetVariable, warningShadowIvar, warningCreateGlobalInsideFunctionOrMethod, warningUnknownClassOrGlobal, warningUnknownIvarType]; - -exports.warningUnusedButSetVariable = warningUnusedButSetVariable; -exports.warningShadowIvar = warningShadowIvar; -exports.warningCreateGlobalInsideFunctionOrMethod = warningCreateGlobalInsideFunctionOrMethod; -exports.warningUnknownClassOrGlobal = warningUnknownClassOrGlobal; -exports.warningUnknownIvarType = warningUnknownIvarType; - - // A optional argument can be given to further configure - // the compiler. These options are recognized: - - var defaultOptions = { - // Acorn options. For more information check objj-acorn. - // We have a function here to create a new object every time we copy - // the default options. - acornOptions: function() { return Object.create(null) }, - - // Turn on `sourceMap` generate a source map for the compiler file. - sourceMap: false, - - // Turn on `sourceMapIncludeSource` will include the source code in the source map. - sourceMapIncludeSource: false, - - // The compiler can do different passes. - // 1: Parse and walk AST tree to collect file dependencies. - // 2: Parse and walk to generate code. - // Pass one is only for the Objective-J load and runtime. - pass: 2, - - // Pass in class definitions. New class definitions in source file will be added here when compiling. - classDefs: function() { return Object.create(null) }, - - // Pass in protocol definitions. New protocol definitions in source file will be added here when compiling. - protocolDefs: function() { return Object.create(null) }, - - // Pass in typeDef definitions. New typeDef definitions in source file will be added here when compiling. - typeDefs: function() { return Object.create(null) }, - - // Turn off `generate` to make the compile copy the code from the source file (and replace needed parts) - // instead of generate it from the AST tree. The preprocessor does not work if this is turn off as it alters - // the AST tree and not the original source. We should deprecate this in the future. - generate: true, - - // Turn on `generateObjJ` to generate Objecitve-J code instead of Javascript code. This can be used to beautify - // the code. - generateObjJ: false, - - // Format description for generated code. For more information look at the readme file in the format folder. - formatDescription: null, - - // How many spaces for indentation when generation code. - indentationSpaces: 4, - - // The type of indentation. Default is space. Can be changed to tab or any other string. - indentationType: " ", - - // Include comments when generating code. This option will turn on the acorn options trackComments and trackCommentsIncludeLineBreak. - includeComments: false, - - // There is a bug in Safari 2.0 that can't handle a named function declaration. See http://kangax.github.io/nfe/#safari-bug - // Turn on `transformNamedFunctionDeclarationToAssignment` to make the compiler transform these. - // We support this here as the old Objective-J compiler (Not a real compiler, Preprocessor.js) transformed - // named function declarations to assignments. - // Example: 'function f(x) { return x }' transforms to: 'f = function(x) { return x }' - transformNamedFunctionDeclarationToAssignment: false, - - // Turn off `includeMethodFunctionNames` to remove function names on methods. - includeMethodFunctionNames: true, - - // Turn off `includeMethodArgumentTypeSignatures` to remove type information on method arguments. - includeMethodArgumentTypeSignatures: true, - - // Turn off `includeIvarTypeSignatures` to remove type information on ivars. - includeIvarTypeSignatures: true, - - // Turn off `inlineMsgSendFunctions` to use message send functions. Needed to use message send decorators. - inlineMsgSendFunctions: true, - - // `warning` includes the warnings that are turned on. It is just used for some warnings. - warnings: [warningUnusedButSetVariable, warningShadowIvar, warningCreateGlobalInsideFunctionOrMethod, warningUnknownClassOrGlobal, warningUnknownIvarType], - - // An array of macro objects and/or text definitions may be passed in. - // Definitions may be in one of two forms: - // macro - // macro=body - macros: null, - }; - - // We copy the options to a new object as we don't want to mess up incoming options when we start compiling. - function setupOptions(opts) { - var options = Object.create(null); - for (var opt in defaultOptions) { - if (opts && Object.prototype.hasOwnProperty.call(opts, opt)) { - var incomingOpt = opts[opt]; - options[opt] = typeof incomingOpt === 'function' ? incomingOpt() : incomingOpt; - } else if (defaultOptions.hasOwnProperty(opt)) { - var defaultOpt = defaultOptions[opt]; - options[opt] = typeof defaultOpt === 'function' ? defaultOpt() : defaultOpt; - } - } - return options; - } - -var ObjJAcornCompiler = function(/*String*/ aString, /*CFURL*/ aURL, options) -{ - this.source = aString; - this.URL = aURL && aURL.toString(); - options = setupOptions(options); - this.options = options; - this.pass = options.pass; - this.classDefs = options.classDefs; - this.protocolDefs = options.protocolDefs; - this.typeDefs = options.typeDefs; - this.generate = options.generate; - this.createSourceMap = options.sourceMap; - this.formatDescription = options.formatDescription; - this.includeComments = options.includeComments; - this.transformNamedFunctionDeclarationToAssignment = options.transformNamedFunctionDeclarationToAssignment; - this.jsBuffer = new StringBuffer(this.createSourceMap, aURL, options.sourceMap && options.sourceMapIncludeSource ? this.source : null); - this.imBuffer = null; - this.cmBuffer = null; - this.dependencies = []; - this.warningsAndErrors = []; - this.lastPos = 0; - - //this.formatDescription = { - // Identifier: {before:"", after:"", parent: {ReturnStatement: {after:"", before:""}, Statement: {after:"", before:""}}}, - // BlockStatement: {before:" ", after:"", afterLeftBrace: "\n", beforeRightBrace: "/* Before Brace */"}, - // Statement: {before:"", after:"/*Statement after*/;\n"} - //}; - - var acornOptions = options.acornOptions; - - if (acornOptions) - { - if (this.URL) - acornOptions.sourceFile = this.URL.substr(this.URL.lastIndexOf('/') + 1); - if (options.sourceMap && !acornOptions.locations) - acornOptions.locations = true; - } - else - { - acornOptions = options.acornOptions = this.URL && {sourceFile: this.URL.substr(this.URL.lastIndexOf('/') + 1)}; - if (options.sourceMap) - acornOptions.locations = true; - } - - if (options.macros) - { - if (acornOptions.macros) - acornOptions.macros.concat(options.macros); - else - acornOptions.macros = options.macros; - } - - try { - this.tokens = acorn.parse(aString, options.acornOptions); - (this.pass === 2 && (options.includeComments || options.formatDescription) ? compileWithFormat : compile)(this.tokens, new Scope(null ,{ compiler: this }), this.pass === 2 ? pass2 : pass1); - } - catch (e) { - if (e.lineStart != null) - { - e.messageForLine = aString.substring(e.lineStart, e.lineEnd); - } - this.addWarning(e); - return; - } - this.setCompiledCode(this.jsBuffer); -} - -ObjJAcornCompiler.prototype.setCompiledCode = function(stringBuffer) -{ - if (this.createSourceMap) - { - var s = stringBuffer.toString(); - this.compiledCode = s.code; - this.sourceMap = s.map; - } - else - { - this.compiledCode = stringBuffer.toString(); - } -} - -// This might not be used -exports.compileToExecutable = function(/*String*/ aString, /*CFURL*/ aURL, options) -{ - exports.currentCompileFile = aURL; - return new ObjJAcornCompiler(aString, aURL, options).executable(); -} - -exports.compileToIMBuffer = function(/*String*/ aString, /*CFURL*/ aURL, options) -{ - return new ObjJAcornCompiler(aString, aURL, options).IMBuffer(); -} - -exports.compile = function(/*String*/ aString, /*CFURL*/ aURL, options) -{ - return new ObjJAcornCompiler(aString, aURL, options); -} - -exports.compileFileDependencies = function(/*String*/ aString, /*CFURL*/ aURL, options) -{ - exports.currentCompileFile = aURL; - (options || (options = {})).pass = 1; - return new ObjJAcornCompiler(aString, aURL, options); -} - -/*! - This function is used to calculate the number of lines that is added when a 'new Function(...) call is used. - This is used to make sure source maps are correct - Currently Safari is adding one line and Chrome and Firefox is adding two lines. - - We calculate this by creating a function and counts the number of new lines at the top of the function - The result is cached so we only need to make the calculation once. - */ -exports.numberOfLinesAtTopOfFunction = function() { - var f = new Function("x", "return x;"); - var fString = f.toString(); - var index = fString.indexOf("return x;"); - var firstPart = fString.substring(0, index); - var numberOfLines = (firstPart.match(/\n/g) || []).length; - - ObjJAcornCompiler.numberOfLinesAtTopOfFunction = function() { - return numberOfLines; - } - - return numberOfLines; -} - -ObjJAcornCompiler.prototype.compilePass2 = function() -{ - var options = this.options; - - exports.currentCompileFile = this.URL; - this.pass = options.pass = 2; - this.jsBuffer = new StringBuffer(this.createSourceMap, this.URL, options.sourceMap && options.sourceMapIncludeSource ? this.source : null); - - // To get the source mapping correct when the new Function construtor is used we add a - // new line as first thing in the code. - if (this.createSourceMap) - this.jsBuffer.concat("\n\n"); - - this.warningsAndErrors = []; - try { - compile(this.tokens, new Scope(null ,{ compiler: this }), pass2); - } catch (e) { - this.addWarning(e); - return null; - } - - this.setCompiledCode(this.jsBuffer); - - return this.compiledCode; -} - -/*! - Add warning or error to the list - */ -ObjJAcornCompiler.prototype.addWarning = function(/* Warning */ aWarning) -{ - if (aWarning.path == null) - aWarning.path = this.URL; - - this.warningsAndErrors.push(aWarning); -} - -ObjJAcornCompiler.prototype.getIvarForClass = function(/* String */ ivarName, /* Scope */ scope) -{ - var ivar = scope.getIvarForCurrentClass(ivarName); - - if (ivar) - return ivar; - - var c = this.getClassDef(scope.currentClassName()); - - while (c) - { - var ivars = c.ivars; - if (ivars) - { - var ivarDef = ivars[ivarName]; - if (ivarDef) - return ivarDef; - } - c = c.superClass; - } -} - -ObjJAcornCompiler.prototype.getClassDef = function(/* String */ aClassName) -{ - if (!aClassName) return null; - - var c = this.classDefs[aClassName]; - - if (c) return c; - - if (typeof objj_getClass === 'function') - { - var aClass = objj_getClass(aClassName); - if (aClass) - { - var ivars = class_copyIvarList(aClass), - ivarSize = ivars.length, - myIvars = Object.create(null), - protocols = class_copyProtocolList(aClass), - protocolSize = protocols.length, - myProtocols = Object.create(null), - instanceMethodDefs = ObjJAcornCompiler.methodDefsFromMethodList(class_copyMethodList(aClass)), - classMethodDefs = ObjJAcornCompiler.methodDefsFromMethodList(class_copyMethodList(aClass.isa)), - superClass = class_getSuperclass(aClass); - - for (var i = 0; i < ivarSize; i++) - { - var ivar = ivars[i]; - - myIvars[ivar.name] = {"type": ivar.type, "name": ivar.name}; - } - - for (var i = 0; i < protocolSize; i++) - { - var protocol = protocols[i], - protocolName = protocol_getName(protocol), - protocolDef = this.getProtocolDef(protocolName); - - myProtocols[protocolName] = protocolDef; - } - - c = new ClassDef(true, aClassName, superClass ? this.getClassDef(superClass.name) : null, myIvars, instanceMethodDefs, classMethodDefs, myProtocols); - this.classDefs[aClassName] = c; - return c; - } - } - - return null; -} - -ObjJAcornCompiler.prototype.getProtocolDef = function(/* String */ aProtocolName) -{ - if (!aProtocolName) return null; - - var p = this.protocolDefs[aProtocolName]; - - if (p) return p; - - if (typeof objj_getProtocol === 'function') - { - var aProtocol = objj_getProtocol(aProtocolName); - if (aProtocol) - { - var protocolName = protocol_getName(aProtocol), - requiredInstanceMethods = protocol_copyMethodDescriptionList(aProtocol, true, true), - requiredInstanceMethodDefs = ObjJAcornCompiler.methodDefsFromMethodList(requiredInstanceMethods), - requiredClassMethods = protocol_copyMethodDescriptionList(aProtocol, true, false), - requiredClassMethodDefs = ObjJAcornCompiler.methodDefsFromMethodList(requiredClassMethods), - protocols = aProtocol.protocols, - inheritFromProtocols = []; - - if (protocols) - for (var i = 0, size = protocols.length; i < size; i++) - inheritFromProtocols.push(compiler.getProtocolDef(protocols[i].name)); - - p = new ProtocolDef(protocolName, inheritFromProtocols, requiredInstanceMethodDefs, requiredClassMethodDefs); - - this.protocolDefs[aProtocolName] = p; - return p; - } - } - - return null; -// protocolDef = {"name": protocolName, "protocols": Object.create(null), "required": Object.create(null), "optional": Object.create(null)}; -} - -ObjJAcornCompiler.prototype.getTypeDef = function(/* String */ aTypeDefName) -{ - if (!aTypeDefName) - return null; - - var t = this.typeDefs[aTypeDefName]; - - if (t) - return t; - - if (typeof objj_getTypeDef === 'function') - { - var aTypeDef = objj_getTypeDef(aTypeDefName); - if (aTypeDef) - { - var typeDefName = typeDef_getName(aTypeDef) - t = new TypeDef(typeDefName); - this.typeDefs[typeDefName] = t; - return t; - } - } - - return null; -} - -/*! - Return a parsed option dictionary - */ -exports.parseGccCompilerFlags = function(/* String */ compilerFlags) -{ - var args = (compilerFlags || "").split(" "), - count = args.length, - objjcFlags = {}; - - for (var index = 0; index < count; ++index) - { - var argument = args[index]; - - if (argument.indexOf("-g") === 0) - objjcFlags.includeMethodFunctionNames = true; - else if (argument.indexOf("-O") === 0) { - objjcFlags.compress = true; // This is not used in the compiler option dictionary but we add it here as it is also done if compiling from command line. - // FIXME: currently we are sending in '-O2' when we want InlineMsgSend. Here we only check if it is '-O...'. - // Maybe we should have some other option for this - if (argument.length > 2) - objjcFlags.inlineMsgSendFunctions = true; - } - //else if (argument.indexOf("-G") === 0) - //objjcFlags |= ObjJAcornCompiler.Flags.Generate; - else if (argument.indexOf("-T") === 0) { - objjcFlags.includeIvarTypeSignatures = false; - objjcFlags.includeMethodArgumentTypeSignatures = false; - } - else if (argument.indexOf("-S") === 0) { - objjcFlags.sourceMap = true; - objjcFlags.sourceMapIncludeSource = true; - } - else if (argument.indexOf("--include") === 0) { - var includeUrl = args[++index], - firstChar = includeUrl && includeUrl.charCodeAt(0); - - // Poor mans unquote - if (firstChar === 34 || firstChar === 39) // '"', "'" - includeUrl = includeUrl.substring(1, includeUrl.length - 1); - - (objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl); - } - else if (argument.indexOf("--inline-msg-send") === 0) - { - // This option is if you only want to inline message send functions - objjcFlags.inlineMsgSendFunctions = true; - } -/* else if (argument.indexOf("-I") === 0) { - var includeUrl = argument.substring(2), - firstChar = includeUrl && includeUrl.charCodeAt(0); - - (objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl); - } - else if (argument.indexOf("'-I") === 0) { - var includeUrl = argument.substring(3, argument.length - 1), - firstChar = includeUrl && includeUrl.charCodeAt(0); - - (objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl); - } - else if (argument.indexOf('"-I') === 0) { - var includeUrl = argument.substring(3, argument.length - 1), - firstChar = includeUrl && includeUrl.charCodeAt(0); - - (objjcFlags.includeFiles || (objjcFlags.includeFiles = [])).push(includeUrl); - }*/ - else if (argument.indexOf("-D") === 0) { - var macroDefinition = argument.substring(2); - - (objjcFlags.macros || (objjcFlags.macros = [])).push(macroDefinition); - } - else if (argument.indexOf("-W") === 0) { - // TODO: Check if the warning name is a valid one. Now we just grab what is written and set/remove it. - var isNo = argument.indexOf("no-", 2) === 2 - var warningName = argument.substring(isNo ? 5 : 2); - var indexOfWarning = (objjcFlags.warnings || (objjcFlags.warnings = defaultOptions.warnings.slice())).findIndex(function (element) { return element.name === warningName }); - - if (isNo) { - if (indexOfWarning !== -1) { - // remove if it exists - objjcFlags.warnings.splice(indexOfWarning, 1); - } - } else { - if (indexOfWarning === -1) { - // Add if it does not exists - var theWarning = AllWarnings.find(function (element) { return element.name === warningName }); - if (theWarning) objjcFlags.warnings.push(theWarning); - } - } - } - } - - return objjcFlags; -} - -ObjJAcornCompiler.methodDefsFromMethodList = function(/* Array */ methodList) -{ - var methodSize = methodList.length, - myMethods = Object.create(null); - - for (var i = 0; i < methodSize; i++) - { - var method = methodList[i], - methodName = method_getName(method); - - myMethods[methodName] = new MethodDef(methodName, method.types); - } - - return myMethods; -} - -//FIXME: Does not work anymore -ObjJAcornCompiler.prototype.executable = function() -{ - if (!this._executable) - this._executable = new Executable(this.jsBuffer ? this.jsBuffer.toString() : null, this.dependencies, this.URL, null, this); - return this._executable; -} - -ObjJAcornCompiler.prototype.IMBuffer = function() -{ - return this.imBuffer; -} - -ObjJAcornCompiler.prototype.code = function() -{ - return this.compiledCode; -} - -ObjJAcornCompiler.prototype.ast = function() -{ - return JSON.stringify(this.tokens, null, indentationSpaces); -} - -ObjJAcornCompiler.prototype.map = function() -{ - return JSON.stringify(this.sourceMap); -} - -ObjJAcornCompiler.prototype.prettifyMessage = function(/* Message */ aMessage) -{ - var line = aMessage.messageForLine, - message = "\n" + (line || ""); - - message += (new Array((aMessage.messageOnColumn || 0) + 1)).join(" "); - if (line) message += (new Array(Math.min(1, line.length || 1) + 1)).join("^") + "\n"; - message += aMessage.messageType + " line " + aMessage.messageOnLine + " in " + this.URL + ":" + aMessage.messageOnLine + ": " + aMessage.message; - - return message; -} - -ObjJAcornCompiler.prototype.error_message = function(errorMessage, node) -{ - var pos = acorn.getLineInfo(this.source, node.start), - syntaxError = new SyntaxError(errorMessage); - - syntaxError.messageOnLine = pos.line; - syntaxError.messageOnColumn = pos.column; - syntaxError.path = this.URL; - syntaxError.messageForNode = node; - syntaxError.messageType = "ERROR"; - syntaxError.messageForLine = this.source.substring(pos.lineStart, pos.lineEnd); - - return syntaxError; -} - -ObjJAcornCompiler.prototype.pushImport = function(url) -{ - if (!ObjJAcornCompiler.importStack) ObjJAcornCompiler.importStack = []; // This is used to keep track of imports. Each time the compiler imports a file the url is pushed here. - - ObjJAcornCompiler.importStack.push(url); -} - -ObjJAcornCompiler.prototype.popImport = function() -{ - ObjJAcornCompiler.importStack.pop(); -} - -function createMessage(/* String */ aMessage, /* SpiderMonkey AST node */ node, /* String */ code) -{ - var message = acorn.getLineInfo(code, node.start); - - message.message = aMessage; - // As a SyntaxError object can't change the property 'line' we also set the property 'messageOnLine' - message.messageOnLine = message.line; - message.messageOnColumn = message.column; - message.messageForNode = node; - message.messageType = "WARNING"; - message.messageForLine = code.substring(message.lineStart, message.lineEnd); - - return message; -} - -function compile(node, state, visitor) { - function c(node, st, override) { - visitor[override || node.type](node, st, c); - } - c(node, state); -} - -function compileWithFormat(node, state, visitor) { - var lastNode, lastComment; - function c(node, st, override) { - var compiler = st.compiler, - includeComments = compiler.includeComments, - localLastNode = lastNode, - sameNode = localLastNode === node; - //console.log(override || node.type); - lastNode = node; - if (includeComments && !sameNode && node.commentsBefore && node.commentsBefore !== lastComment) { - for (var i = 0; i < node.commentsBefore.length; i++) - compiler.jsBuffer.concat(node.commentsBefore[i]); - } - st.pushNode(node, override); - var formatDescription = st.formatDescription(); - //console.log("formatDescription: " + JSON.stringify(formatDescription) + ", node.type: " + node.type + ", override: " + override); - if (!sameNode && formatDescription && formatDescription.before) - compiler.jsBuffer.concatFormat(formatDescription.before); - visitor[override || node.type](node, st, c, formatDescription); - if (!sameNode && formatDescription && formatDescription.after) - compiler.jsBuffer.concatFormat(formatDescription.after); - st.popNode(); - if (includeComments && !sameNode && node.commentsAfter) { - for (var i = 0; i < node.commentsAfter.length; i++) - compiler.jsBuffer.concat(node.commentsAfter[i]); - lastComment = node.commentsAfter; - } else { - lastComment = null; - } - } - c(node, state); -} - -function isIdempotentExpression(node) { - switch (node.type) { - case "Literal": - case "Identifier": - return true; - - case "ArrayExpression": - for (var i = 0; i < node.elements.length; ++i) { - if (!isIdempotentExpression(node.elements[i])) - return false; - } - - return true; - - case "DictionaryLiteral": - for (var i = 0; i < node.keys.length; ++i) { - if (!isIdempotentExpression(node.keys[i])) - return false; - if (!isIdempotentExpression(node.values[i])) - return false; - } - - return true; - - case "ObjectExpression": - for (var i = 0; i < node.properties.length; ++i) - if (!isIdempotentExpression(node.properties[i].value)) - return false; - - return true; - - case "FunctionExpression": - for (var i = 0; i < node.params.length; ++i) - if (!isIdempotentExpression(node.params[i])) - return false; - - return true; - - case "SequenceExpression": - for (var i = 0; i < node.expressions.length; ++i) - if (!isIdempotentExpression(node.expressions[i])) - return false; - - return true; - - case "UnaryExpression": - return isIdempotentExpression(node.argument); - - case "BinaryExpression": - return isIdempotentExpression(node.left) && isIdempotentExpression(node.right); - - case "ConditionalExpression": - return isIdempotentExpression(node.test) && isIdempotentExpression(node.consequent) && isIdempotentExpression(node.alternate); - - case "MemberExpression": - return isIdempotentExpression(node.object) && (!node.computed || isIdempotentExpression(node.property)); - - case "Dereference": - return isIdempotentExpression(node.expr); - - case "Reference": - return isIdempotentExpression(node.element); - - default: - return false; - } -} - -// We do not allow dereferencing of expressions with side effects because we might need to evaluate the expression twice in certain uses of deref, which is not obvious when you look at the deref operator in plain code. -function checkCanDereference(st, node) { - if (!isIdempotentExpression(node)) - throw st.compiler.error_message("Dereference of expression with side effects", node); -} - -// Surround expression with parentheses -function surroundExpression(c) { - return function(node, st, override, format) { - st.compiler.jsBuffer.concat("("); - c(node, st, override, format); - st.compiler.jsBuffer.concat(")"); - } -} - -var operatorPrecedence = { - // MemberExpression - // These two are never used as they are a MemberExpression with the attribute 'computed' which tells what operator it uses. - //".": 0, "[]": 0, - // NewExpression - // This is never used. - //"new": 1, - // All these are UnaryExpression or UpdateExpression and never used. - //"!": 2, "~": 2, "-": 2, "+": 2, "++": 2, "--": 2, "typeof": 2, "void": 2, "delete": 2, - // BinaryExpression - "*": 3, "/": 3, "%": 3, - "+": 4, "-": 4, - "<<": 5, ">>": 5, ">>>": 5, - "<": 6, "<=": 6, ">": 6, ">=": 6, "in": 6, "instanceof": 6, - "==": 7, "!=": 7, "===": 7, "!==": 7, - "&": 8, - "^": 9, - "|": 10, - // LogicalExpression - "&&": 11, - "||": 12 - // ConditionalExpression - // AssignmentExpression -} - -var expressionTypePrecedence = { - MemberExpression: 0, - CallExpression: 1, - NewExpression: 2, - FunctionExpression: 3, - UnaryExpression: 4, UpdateExpression: 4, - BinaryExpression: 5, - LogicalExpression: 6, - ConditionalExpression: 7, - AssignmentExpression: 8 -} - -// Returns true if subNode has higher precedence the the root node. -// If the subNode is the right (as in left/right) subNode -function nodePrecedence(node, subNode, right) { - var nodeType = node.type, - nodePrecedence = expressionTypePrecedence[nodeType] || -1, - subNodePrecedence = expressionTypePrecedence[subNode.type] || -1, - nodeOperatorPrecedence, - subNodeOperatorPrecedence; - return nodePrecedence < subNodePrecedence || (nodePrecedence === subNodePrecedence && isLogicalBinary(nodeType) && ((nodeOperatorPrecedence = operatorPrecedence[node.operator]) < (subNodeOperatorPrecedence = operatorPrecedence[subNode.operator]) || (right && nodeOperatorPrecedence === subNodeOperatorPrecedence))); -} - -var pass1 = walk.make({ -ImportStatement: function(node, st, c) { - var urlString = node.filename.value; - - st.compiler.dependencies.push({url: urlString, isLocal: node.localfilepath}); - //st.compiler.dependencies.push(typeof FileDependency !== 'undefined' ? new FileDependency(typeof CFURL !== 'undefined' ? new CFURL(urlString) : urlString, node.localfilepath) : urlString); -} -}); - -var indentType = " "; -var indentationSpaces = 4; -var indentationSize = indentationSpaces * indentType.length; -var indentStep = Array(indentationSpaces + 1).join(indentType); -var indentation = ""; - -var pass2 = walk.make({ -Program: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate; - - indentType = compiler.options.indentationType; - indentationSpaces = compiler.options.indentationSpaces; - indentationSize = indentationSpaces * indentType.length; - indentStep = Array(indentationSpaces + 1).join(indentType); - indentation = ""; - - for (var i = 0; i < node.body.length; ++i) { - c(node.body[i], st, "Statement"); - } - if (!generate) compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, node.end)); - - // Check maybe warnings - var maybeWarnings = st.maybeWarnings(); - if (maybeWarnings) for (var i = 0; i < maybeWarnings.length; i++) { - var maybeWarning = maybeWarnings[i]; - if (maybeWarning.checkIfWarning(st)) { - compiler.addWarning(maybeWarning.message); - } - } -}, -BlockStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - endOfScopeBody = st.endOfScopeBody, - buffer; - - if (endOfScopeBody) - delete st.endOfScopeBody; - - if (generate) { - var skipIndentation = st.skipIndentation; - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("{", node); - buffer.concatFormat(format.afterLeftBrace); - } else { - if (skipIndentation) - delete st.skipIndentation; - else - buffer.concat(indentation.substring(indentationSize)); - buffer.concat("{\n", node); - } - } - for (var i = 0; i < node.body.length; ++i) { - c(node.body[i], st, "Statement"); - } - if (generate) { - var maxReceiverLevel = st.maxReceiverLevel; - if (endOfScopeBody && maxReceiverLevel) { - buffer.concat(indentation); - buffer.concat("var "); - for (var i = 0; i < maxReceiverLevel; i++) { - if (i) buffer.concat(", "); - buffer.concat("___r"); - buffer.concat((i + 1) + ""); - } - buffer.concat(";\n"); - } - - //Simulate a node for the last curly bracket -// var endNode = node.loc && { loc: { start: { line : node.loc.end.line, column: node.loc.end.column}}, source: node.loc.source}; - if (format) { - buffer.concatFormat(format.beforeRightBrace); - buffer.concat("}", node); - } else { - buffer.concat(indentation.substring(indentationSize)); - buffer.concat("}", node); - if (!skipIndentation && st.isDecl !== false) - buffer.concat("\n"); - st.indentBlockLevel--; - } - } -}, -ExpressionStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate && !format; - if (generate) compiler.jsBuffer.concat(indentation); - c(node.expression, st, "Expression"); - if (generate) compiler.jsBuffer.concat(";\n", node); -}, -IfStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("if", node); - buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("("); - } else { - // Keep the 'else' and 'if' on the same line if it is an 'else if' - if (!st.superNodeIsElse) - buffer.concat(indentation); - else - delete st.superNodeIsElse; - buffer.concat("if (", node); - } - } - c(node.test, st, "Expression"); - if (generate) { - if (format) { - buffer.concat(")", node); - buffer.concatFormat(format.afterRightParenthesis); - } else { - // We don't want EmptyStatements to generate an extra parenthesis except when it is in a while, for, ... - buffer.concat(node.consequent.type === "EmptyStatement" ? ");\n" : ")\n", node); - } - } - indentation += indentStep; - c(node.consequent, st, "Statement"); - indentation = indentation.substring(indentationSize); - var alternate = node.alternate; - if (alternate) { - var alternateNotIf = alternate.type !== "IfStatement"; - if (generate) { - if (format) { - buffer.concatFormat(format.beforeElse); // Do we need this? - buffer.concat("else", node); - buffer.concatFormat(format.afterElse); - } else { - var emptyStatement = alternate.type === "EmptyStatement"; - buffer.concat(indentation); - // We don't want EmptyStatements to generate an extra parenthesis except when it is in a while, for, ... - buffer.concat(alternateNotIf ? emptyStatement ? "else;\n" : "else\n" : "else ", node); - } - } - if (alternateNotIf) - indentation += indentStep; - else - st.superNodeIsElse = true; - - c(alternate, st, "Statement"); - if (alternateNotIf) indentation = indentation.substring(indentationSize); - } -}, -LabeledStatement: function(node, st, c, format) { - var compiler = st.compiler; - if (compiler.generate) { - var buffer = compiler.jsBuffer; - if (!format) buffer.concat(indentation); - c(node.label, st, "IdentifierName"); - if (format) { - buffer.concat(":", node); - buffer.concatFormat(format.afterColon); - } else { - buffer.concat(": ", node); - } - } - c(node.body, st, "Statement"); -}, -BreakStatement: function(node, st, c, format) { - var compiler = st.compiler; - if (compiler.generate) { - var label = node.label, - buffer = compiler.jsBuffer; - if (!format) buffer.concat(indentation); - if (label) { - if (format) { - buffer.concat("break", node); - buffer.concatFormat(format.beforeLabel); - } else { - buffer.concat("break ", node); - } - c(label, st, "IdentifierName"); - if (!format) buffer.concat(";\n"); - } else - buffer.concat(format ? "break" : "break;\n", node); - } -}, -ContinueStatement: function(node, st, c, format) { - var compiler = st.compiler; - if (compiler.generate) { - var label = node.label, - buffer = compiler.jsBuffer; - if (!format) buffer.concat(indentation); - if (label) { - if (format) { - buffer.concat("continue", node); - buffer.concatFormat(format.beforeLabel); - } else { - buffer.concat("continue ", node); - } - c(label, st, "IdentifierName"); - if (!format) buffer.concat(";\n"); - } else - buffer.concat(format ? "continue" : "continue;\n", node); - } -}, -WithStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("with", node); - buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("("); - } else { - buffer.concat(indentation); - buffer.concat("with(", node); - } - } - c(node.object, st, "Expression"); - if (generate) - if (format) { - buffer.concat(")", node); - buffer.concatFormat(format.afterRightParenthesis); - } else { - buffer.concat(")\n", node); - } - indentation += indentStep; - c(node.body, st, "Statement"); - indentation = indentation.substring(indentationSize); -}, -SwitchStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("switch", node); - buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("(", node); - } else { - buffer.concat(indentation); - buffer.concat("switch(", node); - } - } - c(node.discriminant, st, "Expression"); - if (generate) - if (format) { - buffer.concat(")"); - buffer.concatFormat(format.afterRightParenthesis); - buffer.concat("{"); - buffer.concatFormat(format.afterLeftBrace); - } else { - buffer.concat(") {\n"); - } - indentation += indentStep; - for (var i = 0; i < node.cases.length; ++i) { - var cs = node.cases[i]; - if (cs.test) { - if (generate) { - if (format) { - buffer.concatFormat(format.beforeCase); - buffer.concat("case", node); - buffer.concatFormat(format.afterCase); - } else { - buffer.concat(indentation); - buffer.concat("case "); - } - } - c(cs.test, st, "Expression"); - if (generate) - if (format) { - buffer.concat(":"); - buffer.concatFormat(format.afterColon); - } else { - buffer.concat(":\n"); - } - } else - if (generate) - if (format) { - buffer.concatFormat(format.beforeCase); - buffer.concat("default"); - buffer.concatFormat(format.afterCase); - buffer.concat(":"); - buffer.concatFormat(format.afterColon); - } else { - buffer.concat("default:\n"); - } - indentation += indentStep; - for (var j = 0; j < cs.consequent.length; ++j) - c(cs.consequent[j], st, "Statement"); - indentation = indentation.substring(indentationSize); - } - indentation = indentation.substring(indentationSize); - if (generate) { - if (format) { - buffer.concatFormat(format.beforeRightBrace); - buffer.concat("}"); - } else { - buffer.concat(indentation); - buffer.concat("}\n"); - } - } -}, -ReturnStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (!format) buffer.concat(indentation); - buffer.concat("return", node); - } - if (node.argument) { - if (generate) buffer.concatFormat(format ? format.beforeExpression : " "); - c(node.argument, st, "Expression"); - } - if (generate && !format) buffer.concat(";\n"); -}, -ThrowStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (!format) buffer.concat(indentation); - buffer.concat("throw", node); - buffer.concatFormat(format ? format.beforeExpression : " "); - } - c(node.argument, st, "Expression"); - if (generate && !format) buffer.concat(";\n"); -}, -TryStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (!format) buffer.concat(indentation); - buffer.concat("try", node); - buffer.concatFormat(format ? format.beforeStatement : " "); - } - indentation += indentStep; - if (!format) st.skipIndentation = true; - c(node.block, st, "Statement"); - indentation = indentation.substring(indentationSize); - if (node.handler) { - var handler = node.handler, - inner = new Scope(st), - param = handler.param, - name = param.name; - inner.vars[name] = {type: "catch clause", node: param}; - if (generate) { - if (format) { - buffer.concatFormat(format.beforeCatch); - buffer.concat("catch"); - buffer.concatFormat(format.afterCatch); - buffer.concat("("); - c(param, st, "IdentifierName"); - buffer.concat(")"); - buffer.concatFormat(format.beforeCatchStatement); - } else { - buffer.concat("\n"); - buffer.concat(indentation); - buffer.concat("catch("); - buffer.concat(name); - buffer.concat(") "); - } - } - indentation += indentStep; - inner.skipIndentation = true; - inner.endOfScopeBody = true; - c(handler.body, inner, "ScopeBody"); - inner.variablesNotReadWarnings(); - indentation = indentation.substring(indentationSize); - inner.copyAddedSelfToIvarsToParent(); - } - if (node.finalizer) { - if (generate) { - if (format) { - buffer.concatFormat(format.beforeCatch); - buffer.concat("finally"); - buffer.concatFormat(format.beforeCatchStatement); - } else { - buffer.concat("\n"); - buffer.concat(indentation); - buffer.concat("finally "); - } - } - indentation += indentStep; - st.skipIndentation = true; - c(node.finalizer, st, "Statement"); - indentation = indentation.substring(indentationSize); - } - if (generate && !format) - buffer.concat("\n"); -}, -WhileStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - body = node.body, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("while", node); - buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("("); - } else { - buffer.concat(indentation); - buffer.concat("while (", node); - } - } - c(node.test, st, "Expression"); - if (generate) - if (format) { - buffer.concat(")"); - buffer.concatFormat(format.afterRightParenthesis); - } else { - // We don't want EmptyStatements to generate an extra parenthesis except when it is in a while, for, ... - buffer.concat(body.type === "EmptyStatement" ? ");\n" : ")\n"); - } - indentation += indentStep; - c(body, st, "Statement"); - indentation = indentation.substring(indentationSize); -}, -DoWhileStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("do", node); - buffer.concatFormat(format.beforeStatement); - } else { - buffer.concat(indentation); - buffer.concat("do\n", node); - } - } - indentation += indentStep; - c(node.body, st, "Statement"); - indentation = indentation.substring(indentationSize); - if (generate) { - if (format) { - buffer.concat("while"); - buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("("); - } else { - buffer.concat(indentation); - buffer.concat("while ("); - } - } - c(node.test, st, "Expression"); - if (generate) buffer.concatFormat(format ? ")" : ");\n"); -}, -ForStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - body = node.body, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("for", node); - buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("("); - } else { - buffer.concat(indentation); - buffer.concat("for (", node); - } - } - if (node.init) c(node.init, st, "ForInit"); - if (generate) buffer.concat(format ? ";" : "; "); - if (node.test) c(node.test, st, "Expression"); - if (generate) buffer.concat(format ? ";" : "; "); - if (node.update) c(node.update, st, "Expression"); - if (generate) - if (format) { - buffer.concat(")"); - buffer.concatFormat(format.afterRightParenthesis); - } else { - // We don't want EmptyStatements to generate an extra parenthesis except when it is in a while, for, ... - buffer.concat(body.type === "EmptyStatement" ? ");\n" : ")\n"); - } - indentation += indentStep; - c(body, st, "Statement"); - indentation = indentation.substring(indentationSize); -}, -ForInStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - body = node.body, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concat("for", node); - buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("("); - } else { - buffer.concat(indentation); - buffer.concat("for (", node); - } - } - c(node.left, st, "ForInit"); - if (generate) - if (format) { - buffer.concatFormat(format.beforeIn); - buffer.concat("in"); - buffer.concatFormat(format.afterIn); - } else { - buffer.concat(" in "); - } - c(node.right, st, "Expression"); - if (generate) - if (format) { - buffer.concat(")"); - buffer.concatFormat(format.afterRightParenthesis); - } else { - // We don't want EmptyStatements to generate an extra parenthesis except when it is in a while, for, ... - buffer.concat(body.type === "EmptyStatement" ? ");\n" : ")\n"); - } - indentation += indentStep; - c(body, st, "Statement"); - indentation = indentation.substring(indentationSize); -}, -ForInit: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate; - if (node.type === "VariableDeclaration") { - st.isFor = true; - c(node, st); - delete st.isFor; - } else - c(node, st, "Expression"); -}, -DebuggerStatement: function(node, st, c, format) { - var compiler = st.compiler; - if (compiler.generate) { - var buffer = compiler.jsBuffer; - if (format) { - buffer.concat("debugger", node); - } else { - buffer.concat(indentation); - buffer.concat("debugger;\n", node); - } - } -}, -Function: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer = compiler.jsBuffer, - inner = new FunctionScope(st), - decl = node.type == "FunctionDeclaration", - id = node.id; - - inner.isDecl = decl; - for (var i = 0; i < node.params.length; ++i) - inner.vars[node.params[i].name] = {type: "argument", node: node.params[i]}; - if (generate && !format) - buffer.concat(indentation); - if (id) { - var name = id.name; - (decl ? st : inner).vars[name] = {type: decl ? "function" : "function name", node: id}; - if (compiler.transformNamedFunctionDeclarationToAssignment) { - if (generate) { - buffer.concat(name); - buffer.concat(" = "); - } else { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - buffer.concat(name); - buffer.concat(" = function"); - compiler.lastPos = id.end; - } - } - } - if (generate) { - buffer.concat("function", node); - if (!compiler.transformNamedFunctionDeclarationToAssignment && id) - { - if (!format) buffer.concat(" "); - c(id, st, "IdentifierName"); - } - if (format) buffer.concatFormat(format.beforeLeftParenthesis); - buffer.concat("("); - for (var i = 0; i < node.params.length; ++i) { - if (i) - buffer.concat(format ? "," : ", "); - c(node.params[i], st, "IdentifierName"); - } - if (format) { - buffer.concat(")"); - buffer.concatFormat(format.afterRightParenthesis); - } else { - buffer.concat(")\n"); - } - } - indentation += indentStep; - inner.endOfScopeBody = true; - c(node.body, inner, "ScopeBody"); - inner.variablesNotReadWarnings(); - indentation = indentation.substring(indentationSize); - inner.copyAddedSelfToIvarsToParent(); -}, -VariableDeclaration: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - varScope = st.getVarScope(), - buffer; - if (generate) { - buffer = compiler.jsBuffer; - if (!st.isFor && !format) buffer.concat(indentation); - buffer.concat(format ? "var" : "var ", node); - } - for (var i = 0; i < node.declarations.length; ++i) { - var decl = node.declarations[i], - identifier = decl.id.name, - possibleHoistedVariable = varScope.possibleHoistedVariables && varScope.possibleHoistedVariables[identifier], - variableDeclaration = {type: "var", node: decl.id, isRead: (possibleHoistedVariable ? possibleHoistedVariable.isRead : 0)}; - - // Make sure we count the access for this varaible if it is hoisted. - // Check if this variable has already been accessed above this declaration - if (possibleHoistedVariable) { - // 'variableDeclaration' is already marked as read. This was done by adding the already read amount above. - - // Substract the same amount from possible local variable higher up in the hierarchy that is shadowed by this declaration - if (possibleHoistedVariable.variable) { - possibleHoistedVariable.variable.isRead -= possibleHoistedVariable.isRead; - } - // Remove it as we don't need to care about this variable anymore. - varScope.possibleHoistedVariables[identifier] = null; - } - varScope.vars[identifier] = variableDeclaration; - - if (i) - if (generate) { - if (format) { - buffer.concat(","); - } else { - if (st.isFor) - buffer.concat(", "); - else { - buffer.concat(",\n"); - buffer.concat(indentation); - buffer.concat(" "); - } - } - } - - c(decl.id, st, "IdentifierName"); - if (decl.init) { - if (generate) { - if (format) { - buffer.concatFormat(format.beforeEqual); - buffer.concat("="); - buffer.concatFormat(format.afterEqual); - } else { - buffer.concat(" = "); - } - } - c(decl.init, st, "Expression"); - } - // FIXME: Extract to function - // Here we check back if a ivar with the same name exists and if we have prefixed 'self.' on previous uses. - // If this is the case we have to remove the prefixes and issue a warning that the variable hides the ivar. - if (st.addedSelfToIvars) { - var addedSelfToIvar = st.addedSelfToIvars[identifier]; - if (addedSelfToIvar) { - var atoms = st.compiler.jsBuffer.atoms; - for (var i = 0, size = addedSelfToIvar.length; i < size; i++) { - var dict = addedSelfToIvar[i]; - atoms[dict.index] = ""; - if (compiler.options.warnings.includes(warningShadowIvar)) compiler.addWarning(createMessage("Local declaration of '" + identifier + "' hides instance variable", dict.node, compiler.source)); - } - // Add a read mark to the local variable for each time it is used. - variableDeclaration.isRead += size; - // Remove the variable from list of instance variable uses. - st.addedSelfToIvars[identifier] = []; - } - } - } - if (generate && !format && !st.isFor) buffer.concat(";\n", node); // Don't add ';' if this is a for statement but do it if this is a statement -}, -ThisExpression: function(node, st, c) { - var compiler = st.compiler; - - if (compiler.generate) compiler.jsBuffer.concat("this", node); -}, -ArrayExpression: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - - if (generate) { - buffer = compiler.jsBuffer; - buffer.concat("[", node); - } - - for (var i = 0; i < node.elements.length; ++i) { - var elt = node.elements[i]; - - if (generate && i !== 0) - if (format) { - buffer.concatFormat(format.beforeComma); - buffer.concat(","); - buffer.concatFormat(format.afterComma); - } else - buffer.concat(", "); - - if (elt) c(elt, st, "Expression"); - } - if (generate) buffer.concat("]"); -}, -ObjectExpression: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - properties = node.properties, - buffer = compiler.jsBuffer; - if (generate) buffer.concat("{", node); - for (var i = 0, size = properties.length; i < size; ++i) - { - var prop = properties[i]; - if (generate) { - if (i) - if (format) { - buffer.concatFormat(format.beforeComma); - buffer.concat(","); - buffer.concatFormat(format.afterComma); - } else - buffer.concat(", "); - st.isPropertyKey = true; - c(prop.key, st, "Expression"); - delete st.isPropertyKey; - if (format) { - buffer.concatFormat(format.beforeColon); - buffer.concat(":"); - buffer.concatFormat(format.afterColon); - } else { - buffer.concat(": "); - } - } else if (prop.key.raw && prop.key.raw.charAt(0) === "@") { - buffer.concat(compiler.source.substring(compiler.lastPos, prop.key.start)); - compiler.lastPos = prop.key.start + 1; - } - - c(prop.value, st, "Expression"); - } - if (generate) buffer.concat("}"); -}, -SequenceExpression: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - buffer.concat("(", node); - } - for (var i = 0; i < node.expressions.length; ++i) { - if (generate && i !== 0) - if (format) { - buffer.concatFormat(format.beforeComma); - buffer.concat(","); - buffer.concatFormat(format.afterComma); - } else - buffer.concat(", "); - c(node.expressions[i], st, "Expression"); - } - if (generate) buffer.concat(")"); -}, -UnaryExpression: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - argument = node.argument; - if (generate) { - var buffer = compiler.jsBuffer; - if (node.prefix) { - buffer.concat(node.operator, node); - if (wordPrefixOperators(node.operator)) - buffer.concat(" "); - (nodePrecedence(node, argument) ? surroundExpression(c) : c)(argument, st, "Expression"); - } else { - (nodePrecedence(node, argument) ? surroundExpression(c) : c)(argument, st, "Expression"); - buffer.concat(node.operator); - } - } else { - c(argument, st, "Expression"); - } -}, -UpdateExpression: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - buffer = compiler.jsBuffer; - if (node.argument.type === "Dereference") { - checkCanDereference(st, node.argument); - - // @deref(x)++ and ++@deref(x) require special handling. - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - - // Output the dereference function, "(...)(z)" - buffer.concat((node.prefix ? "" : "(") + "("); - - // The thing being dereferenced. - if (!generate) compiler.lastPos = node.argument.expr.start; - c(node.argument.expr, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.argument.expr.end)); - buffer.concat(")("); - - if (!generate) compiler.lastPos = node.argument.start; - c(node.argument, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.argument.end)); - buffer.concat(" " + node.operator.substring(0, 1) + " 1)" + (node.prefix ? "" : node.operator == '++' ? " - 1)" : " + 1)")); - - if (!generate) compiler.lastPos = node.end; - return; - } - - if (node.prefix) { - if (generate) { - buffer.concat(node.operator, node); - if (wordPrefixOperators(node.operator)) - buffer.concat(" "); - } - (generate && nodePrecedence(node, node.argument) ? surroundExpression(c) : c)(node.argument, st, "Expression"); - } else { - (generate && nodePrecedence(node, node.argument) ? surroundExpression(c) : c)(node.argument, st, "Expression"); - if (generate) buffer.concat(node.operator); - } -}, -BinaryExpression: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate; - (generate && nodePrecedence(node, node.left) ? surroundExpression(c) : c)(node.left, st, "Expression"); - if (generate) { - var buffer = compiler.jsBuffer; - buffer.concatFormat(format ? format.beforeOperator : " "); - buffer.concat(node.operator, node); - buffer.concatFormat(format ? format.afterOperator : " "); - } - (generate && nodePrecedence(node, node.right, true) ? surroundExpression(c) : c)(node.right, st, "Expression"); -}, -LogicalExpression: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate; - (generate && nodePrecedence(node, node.left) ? surroundExpression(c) : c)(node.left, st, "Expression"); - if (generate) { - var buffer = compiler.jsBuffer; - buffer.concatFormat(format ? format.beforeOperator : " "); - buffer.concat(node.operator); - buffer.concatFormat(format ? format.afterOperator : " "); - } - (generate && nodePrecedence(node, node.right, true) ? surroundExpression(c) : c)(node.right, st, "Expression"); -}, -AssignmentExpression: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - saveAssignment = st.assignment, - buffer = compiler.jsBuffer; - - if (node.left.type === "Dereference") { - checkCanDereference(st, node.left); - - // @deref(x) = z -> x(z) etc - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - - // Output the dereference function, "(...)(z)" - buffer.concat("(", node); - // What's being dereferenced could itself be an expression, such as when dereferencing a deref. - if (!generate) compiler.lastPos = node.left.expr.start; - c(node.left.expr, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.left.expr.end)); - buffer.concat(")("); - - // Now "(x)(...)". We have to manually expand +=, -=, *= etc. - if (node.operator !== "=") { - // Output the whole .left, not just .left.expr. - if (!generate) compiler.lastPos = node.left.start; - c(node.left, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.left.end)); - buffer.concat(" " + node.operator.substring(0, 1) + " "); - } - - if (!generate) compiler.lastPos = node.right.start; - c(node.right, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.right.end)); - buffer.concat(")"); - - if (!generate) compiler.lastPos = node.end; - - return; - } - - var saveAssignment = st.assignment, - nodeLeft = node.left; - - st.assignment = true; - if (nodeLeft.type === "Identifier" && nodeLeft.name === "self") { - var lVar = st.getLvar("self", true); - if (lVar) { - var lvarScope = lVar.scope; - if (lvarScope) - lvarScope.assignmentToSelf = true; - } - } - (generate && nodePrecedence(node, nodeLeft) ? surroundExpression(c) : c)(nodeLeft, st, "Expression"); - if (generate) { - buffer.concatFormat(format ? format.beforeOperator : " "); - buffer.concat(node.operator); - buffer.concatFormat(format ? format.afterOperator : " "); - } - st.assignment = saveAssignment; - (generate && nodePrecedence(node, node.right, true) ? surroundExpression(c) : c)(node.right, st, "Expression"); - if (st.isRootScope() && nodeLeft.type === "Identifier" && !st.getLvar(nodeLeft.name)) - st.vars[nodeLeft.name] = {type: "global", node: nodeLeft}; -}, -ConditionalExpression: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - buffer; - (generate && nodePrecedence(node, node.test) ? surroundExpression(c) : c)(node.test, st, "Expression"); - if (generate) { - buffer = compiler.jsBuffer; - if (format) { - buffer.concatFormat(format.beforeOperator); - buffer.concat("?"); - buffer.concatFormat(format.afterOperator); - } else { - buffer.concat(" ? "); - } - } - c(node.consequent, st, "Expression"); - if (generate) - if (format) { - buffer.concatFormat(format.beforeOperator); - buffer.concat(":"); - buffer.concatFormat(format.afterOperator); - } else { - buffer.concat(" : "); - } - c(node.alternate, st, "Expression"); -}, -NewExpression: function(node, st, c, format) { - var compiler = st.compiler, - nodeArguments = node.arguments, - generate = compiler.generate, - buffer; - if (generate) { - buffer = compiler.jsBuffer; - buffer.concat("new ", node); - } - (generate && nodePrecedence(node, node.callee) ? surroundExpression(c) : c)(node.callee, st, "Expression"); - if (generate) buffer.concat("("); - if (nodeArguments) { - for (var i = 0, size = nodeArguments.length; i < size; ++i) { - if (i && generate) - buffer.concatFormat(format ? "," : ", "); - c(nodeArguments[i], st, "Expression"); - } - } - if (generate) buffer.concat(")"); -}, -CallExpression: function(node, st, c, format) { - var compiler = st.compiler, - nodeArguments = node.arguments, - generate = compiler.generate, - callee = node.callee, - buffer; - - // If call to function 'eval' we assume that 'self' can be altered and from this point - // we check if 'self' is null before 'objj_msgSend' is called with 'self' as receiver. - if (callee.type === "Identifier" && callee.name === "eval") { - var selfLvar = st.getLvar("self", true); - if (selfLvar) { - var selfScope = selfLvar.scope; - if (selfScope) { - selfScope.assignmentToSelf = true; - } - } - } - - (generate && nodePrecedence(node, callee) ? surroundExpression(c) : c)(callee, st, "Expression"); - if (generate) { - buffer = compiler.jsBuffer; - buffer.concat("("); - } - if (nodeArguments) { - for (var i = 0, size = nodeArguments.length; i < size; ++i) { - if (i && generate) - buffer.concat(format ? "," : ", "); - c(nodeArguments[i], st, "Expression"); - } - } - if (generate) buffer.concat(")"); -}, -MemberExpression: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - computed = node.computed; - (generate && nodePrecedence(node, node.object) ? surroundExpression(c) : c)(node.object, st, "Expression"); - if (generate) - compiler.jsBuffer.concat(computed ? "[" : ".", node); - st.secondMemberExpression = !computed; - // No parentheses when it is computed, '[' and ']' are the same thing. - (generate && !computed && nodePrecedence(node, node.property) ? surroundExpression(c) : c)(node.property, st, "Expression"); - st.secondMemberExpression = false; - if (generate && computed) - compiler.jsBuffer.concat("]"); -}, -Identifier: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - identifier = node.name; - if (!st.isPropertyKey) { - var lvarScope = st.getLvarScope(identifier, true); // Only look inside method/function scope - var lvar = lvarScope.vars && lvarScope.vars[identifier]; - if (!st.secondMemberExpression && st.currentMethodType() === "-") - { - var ivar = compiler.getIvarForClass(identifier, st); - - if (ivar) - { - if (lvar) { - if (compiler.options.warnings.includes(warningShadowIvar)) compiler.addWarning(createMessage("Local declaration of '" + identifier + "' hides instance variable", node, compiler.source)); - } - else - { - var nodeStart = node.start; - - if (!generate) do { // The Spider Monkey AST tree includes any parentheses in start and end properties so we have to make sure we skip those - compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, nodeStart)); - compiler.lastPos = nodeStart; - } while (compiler.source.substr(nodeStart++, 1) === "(") - // Save the index in where the "self." string is stored and the node. - // These will be used if we find a variable declaration that is hoisting this identifier. - ((st.addedSelfToIvars || (st.addedSelfToIvars = Object.create(null)))[identifier] || (st.addedSelfToIvars[identifier] = [])).push({node: node, index: compiler.jsBuffer.length()}); - compiler.jsBuffer.concat("self.", node); - } - } else if (!reservedIdentifiers(identifier)) { // Don't check for warnings if it is a reserved word like self, localStorage, _cmd, etc... - var message, - classOrGlobal = typeof global[identifier] !== "undefined" || (typeof window !== 'undefined' && typeof window[identifier] !== "undefined") || compiler.getClassDef(identifier), - globalVar = st.getLvar(identifier); - if (classOrGlobal && (!globalVar || globalVar.type !== "class")) { // It can't be declared with a @class statement. - /* Turned off this warning as there are many many warnings when compiling the Cappuccino frameworks - Martin - if (lvar) { - message = compiler.addWarning(createMessage("Local declaration of '" + identifier + "' hides global variable", node, compiler.source)); - }*/ - } else if (!globalVar) { - if (st.assignment && compiler.options.warnings.includes(warningCreateGlobalInsideFunctionOrMethod)) { - message = new GlobalVariableMaybeWarning("Creating global variable inside function or method '" + identifier + "'", node, compiler.source); - // Turn off these warnings for this identifier, we only want one. - st.vars[identifier] = {type: "remove global warning", node: node}; - } else if (compiler.options.warnings.includes(warningUnknownClassOrGlobal)){ - message = new GlobalVariableMaybeWarning("Using unknown class or uninitialized global variable '" + identifier + "'", node, compiler.source); - } - } - if (message) - st.addMaybeWarning(message); - } - } - if (!st.assignment || !st.secondMemberExpression) { - if (lvar) { - lvar.isRead++; - } else { - // If the var is not declared in current var scope (function scope) we need to save which var it is as it can be hoisted. - // First check if the variable is declared higher up in the scope hierarchy - lvarScope = lvarScope.getLvarScope(identifier); - lvar = lvarScope.vars && lvarScope.vars[identifier]; - // We will mark it as read. - if (lvar) { - lvar.isRead++; - } - - // The variable can be declared later on in this function / method scope. - // It can also be declared later on in a higher scope. - // We create a list of possible variables that will be used if it is declared. - // We collect how many times the variable is read and a reference to a possible variable in a - var possibleHoistedVariable = (lvarScope.possibleHoistedVariables || (lvarScope.possibleHoistedVariables = Object.create(null)))[identifier]; - - if (possibleHoistedVariable == null) { - var possibleHoistedVariable = {isRead: 1}; - lvarScope.possibleHoistedVariables[identifier] = possibleHoistedVariable; - } else { - possibleHoistedVariable.isRead++; - } - - if (lvar) { - // If the var and scope are already set it should not be different from what we found now. - if ((possibleHoistedVariable.variable && possibleHoistedVariable.variable !== lvar) || (possibleHoistedVariable.varScope && possibleHoistedVariable.varScope !== lvarScope)) { - throw new Error("Internal inconsistency, var or scope is not the same"); - } - possibleHoistedVariable.variable = lvar; - possibleHoistedVariable.varScope = lvarScope; - } - } - } - } - if (generate) compiler.jsBuffer.concat(identifier, node, identifier === "self" ? "self" : null); -}, -// Use this when there should not be a look up to issue warnings or add 'self.' before ivars -IdentifierName: function(node, st, c) { - var compiler = st.compiler; - if (compiler.generate) - compiler.jsBuffer.concat(node.name, node); -}, -Literal: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate; - if (generate) { - if (node.raw) - if (node.raw.charAt(0) === "@") - compiler.jsBuffer.concat(node.raw.substring(1), node); - else - compiler.jsBuffer.concat(node.raw, node); - else { - var value = node.value, - doubleQuote = value.indexOf('"') !== -1; - compiler.jsBuffer.concat(doubleQuote ? "'" : '"', node); - compiler.jsBuffer.concat(value); - compiler.jsBuffer.concat(doubleQuote ? "'" : '"'); - } - - } else if (node.raw.charAt(0) === "@") { - compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = node.start + 1; - } -}, -ArrayLiteral: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - buffer = compiler.jsBuffer, - generateObjJ = compiler.options.generateObjJ, - elementLength = node.elements.length; - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = node.start; - } - - if (!generate) buffer.concat(" "); // Add an extra space if it looks something like this: "return()". No space between return and expression. - if (!st.receiverLevel) st.receiverLevel = 0; - if (generateObjJ) { - buffer.concat("@["); - } else if (!elementLength) { - if (compiler.options.inlineMsgSendFunctions) { - buffer.concat("(___r", node); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = (CPArray.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPArray, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : (___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.method_msgSend[\"init\"] || _objj_forward)(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"init\"))"); - } else { - buffer.concat("(___r"); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = CPArray.isa.objj_msgSend0(CPArray, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.objj_msgSend0(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"init\"))"); - } - - if (!(st.maxReceiverLevel >= st.receiverLevel)) - st.maxReceiverLevel = st.receiverLevel; - } else { - if (compiler.options.inlineMsgSendFunctions) { - buffer.concat("(___r", node); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = (CPArray.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPArray, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : (___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.method_msgSend[\"initWithObjects:count:\"] || _objj_forward)(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"initWithObjects:count:\", ["); - } else { - buffer.concat("(___r", node); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = CPArray.isa.objj_msgSend0(CPArray, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.objj_msgSend2(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"initWithObjects:count:\", ["); - } - - if (!(st.maxReceiverLevel >= st.receiverLevel)) - st.maxReceiverLevel = st.receiverLevel; - } - if (elementLength) { - for (var i = 0; i < elementLength; i++) { - var elt = node.elements[i]; - - if (i) - buffer.concat(", "); - - if (!generate) compiler.lastPos = elt.start; - c(elt, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, elt.end)); - } - if (!generateObjJ) buffer.concat("], " + elementLength + "))"); - } - - if (generateObjJ) - buffer.concat("]"); - else - st.receiverLevel--; - - if (!generate) compiler.lastPos = node.end; -}, -DictionaryLiteral: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - buffer = compiler.jsBuffer, - generateObjJ = compiler.options.generateObjJ, - keyLength = node.keys.length; - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = node.start; - } - - if (!generate) buffer.concat(" "); // Add an extra space if it looks something like this: "return()". No space between return and expression. - if (!st.receiverLevel) st.receiverLevel = 0; - if (generateObjJ) { - buffer.concat("@{"); - for (var i = 0; i < keyLength; i++) { - if (i !== 0) buffer.concat(","); - c(node.keys[i], st, "Expression"); - buffer.concat(":"); - c(node.values[i], st, "Expression"); - } - buffer.concat("}"); - } else if (!keyLength) { - if (compiler.options.inlineMsgSendFunctions) { - buffer.concat("(___r", node); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = (CPDictionary.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPDictionary, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : (___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.method_msgSend[\"init\"] || _objj_forward)(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"init\"))"); - } else { - buffer.concat("(___r"); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = CPDictionary.isa.objj_msgSend0(CPDictionary, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.objj_msgSend0(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"init\"))"); - } - - if (!(st.maxReceiverLevel >= st.receiverLevel)) - st.maxReceiverLevel = st.receiverLevel; - } else { - if (compiler.options.inlineMsgSendFunctions) { - buffer.concat("(___r", node); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = (CPDictionary.isa.method_msgSend[\"alloc\"] || _objj_forward)(CPDictionary, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : (___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.method_msgSend[\"initWithObjects:forKeys:\"] || _objj_forward)(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"initWithObjects:forKeys:\", ["); - } else { - buffer.concat("(___r", node); - buffer.concat(++st.receiverLevel + ""); - buffer.concat(" = CPDictionary.isa.objj_msgSend0(CPDictionary, \"alloc\"), ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" == null ? ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(" : ___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(".isa.objj_msgSend2(___r"); - buffer.concat(st.receiverLevel + ""); - buffer.concat(", \"initWithObjects:forKeys:\", ["); - } - - if (!(st.maxReceiverLevel >= st.receiverLevel)) - st.maxReceiverLevel = st.receiverLevel; - - for (var i = 0; i < keyLength; i++) { - var value = node.values[i]; - - if (i) buffer.concat(", "); - if (!generate) compiler.lastPos = value.start; - c(value, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, value.end)); - } - - buffer.concat("], ["); - - for (var i = 0; i < keyLength; i++) { - var key = node.keys[i]; - - if (i) buffer.concat(", "); - - if (!generate) compiler.lastPos = key.start; - c(key, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, key.end)); - } - buffer.concat("]))"); - } - - if (!generateObjJ) - st.receiverLevel--; - if (!generate) compiler.lastPos = node.end; -}, -ImportStatement: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - buffer = compiler.jsBuffer, - localfilepath = node.localfilepath, - generateObjJ = compiler.options.generateObjJ; - - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - if (generateObjJ) { - buffer.concat("@import "); - buffer.concat(localfilepath ? "\"" : "<"); - buffer.concat(node.filename.value); - buffer.concat(localfilepath ? "\"" : ">"); - } else { - buffer.concat("objj_executeFile(\"", node); - buffer.concat(node.filename.value); - buffer.concat(localfilepath ? "\", YES);" : "\", NO);"); - } - if (!generate) compiler.lastPos = node.end; -}, -ClassDeclarationStatement: function(node, st, c, format) { - var compiler = st.compiler, - generate = compiler.generate, - saveJSBuffer = compiler.jsBuffer, - className = node.classname.name, - classDef = compiler.getClassDef(className), - classScope = new Scope(st), - isInterfaceDeclaration = node.type === "InterfaceDeclarationStatement", - protocols = node.protocols, - options = compiler.options, - generateObjJ = options.generateObjJ; - - compiler.imBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL, options.sourceMap && options.sourceMapIncludeSource ? compiler.source : null); - compiler.cmBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL); - compiler.classBodyBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL); // TODO: Check if this is needed - - if (compiler.getTypeDef(className)) - throw compiler.error_message(className + " is already declared as a type", node.classname); - - - if (!generate) saveJSBuffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - - // First we declare the class - if (node.superclassname) - { - // Must have methods dictionaries and ivars dictionary to be a real implementaion declaration. - // Without it is a "@class" declaration (without both ivars dictionary and method dictionaries) or - // "interface" declaration (without ivars dictionary) - // TODO: Create a ClassDef object and add this logic to it - if (classDef && classDef.ivars) - // It has a real implementation declaration already - throw compiler.error_message("Duplicate class " + className, node.classname); - - if (isInterfaceDeclaration && classDef && classDef.instanceMethods && classDef.classMethods) - // It has a interface declaration already - throw compiler.error_message("Duplicate interface definition for class " + className, node.classname); - var superClassDef = compiler.getClassDef(node.superclassname.name); - if (!superClassDef) - { - var errorMessage = "Can't find superclass " + node.superclassname.name; - if (ObjJAcornCompiler.importStack) for (var i = ObjJAcornCompiler.importStack.length; --i >= 0;) - errorMessage += "\n" + Array((ObjJAcornCompiler.importStack.length - i) * 2 + 1).join(" ") + "Imported by: " + ObjJAcornCompiler.importStack[i]; - throw compiler.error_message(errorMessage, node.superclassname); - } - - classDef = new ClassDef(!isInterfaceDeclaration, className, superClassDef, Object.create(null)); - - if (!generateObjJ) saveJSBuffer.concat("\n{var the_class = objj_allocateClassPair(" + node.superclassname.name + ", \"" + className + "\"),\nmeta_class = the_class.isa;", node); - } - else if (node.categoryname) - { - classDef = compiler.getClassDef(className); - if (!classDef) - throw compiler.error_message("Class " + className + " not found ", node.classname); - - if (!generateObjJ) { - saveJSBuffer.concat("{\nvar the_class = objj_getClass(\"" + className + "\")\n", node); - saveJSBuffer.concat("if(!the_class) throw new SyntaxError(\"*** Could not find definition for class \\\"" + className + "\\\"\");\n"); - saveJSBuffer.concat("var meta_class = the_class.isa;"); - } - } - else - { - classDef = new ClassDef(!isInterfaceDeclaration, className, null, Object.create(null)); - - if (!generateObjJ) - saveJSBuffer.concat("{var the_class = objj_allocateClassPair(Nil, \"" + className + "\"),\nmeta_class = the_class.isa;", node); - } - - if (generateObjJ) { - saveJSBuffer.concat(isInterfaceDeclaration ? "@interface " : "@implementation "); - saveJSBuffer.concat(className); - if (node.superclassname) { - saveJSBuffer.concat(" : "); - c(node.superclassname, st, "IdentifierName"); - } else if (node.categoryname) { - saveJSBuffer.concat(" ("); - c(node.categoryname, st, "IdentifierName"); - saveJSBuffer.concat(")"); - } - } - - if (protocols) for (var i = 0, size = protocols.length; i < size; i++) - { - if (generateObjJ) { - if (i) - saveJSBuffer.concat(", "); - else - saveJSBuffer.concat(" <"); - c(protocols[i], st, "IdentifierName"); - if (i === size - 1) - saveJSBuffer.concat(">"); - } else { - saveJSBuffer.concat("\nvar aProtocol = objj_getProtocol(\"" + protocols[i].name + "\");", protocols[i]); - saveJSBuffer.concat("\nif (!aProtocol) throw new SyntaxError(\"*** Could not find definition for protocol \\\"" + protocols[i].name + "\\\"\");"); - saveJSBuffer.concat("\nclass_addProtocol(the_class, aProtocol);"); - } - } -/* - if (isInterfaceDeclaration) - classDef.interfaceDeclaration = true; -*/ - classScope.classDef = classDef; - compiler.currentSuperClass = "objj_getClass(\"" + className + "\").super_class"; - compiler.currentSuperMetaClass = "objj_getMetaClass(\"" + className + "\").super_class"; - - var firstIvarDeclaration = true, - ivars = classDef.ivars, - classDefIvars = [], - hasAccessors = false; - - // Then we add all ivars - if (node.ivardeclarations) { - if (generateObjJ) { - saveJSBuffer.concat("{"); - indentation += indentStep; - } - - for (var i = 0; i < node.ivardeclarations.length; ++i) - { - var ivarDecl = node.ivardeclarations[i], - ivarType = ivarDecl.ivartype ? ivarDecl.ivartype.name : null, - ivarTypeIsClass = ivarDecl.ivartype ? ivarDecl.ivartype.typeisclass : false, - ivarIdentifier = ivarDecl.id, - ivarName = ivarIdentifier.name, - ivar = {"type": ivarType, "name": ivarName}, - accessors = ivarDecl.accessors; - - var checkIfIvarIsAlreadyDeclaredAndInSuperClass = function(aClassDef, recursiveFunction) { - if (aClassDef.ivars[ivarName]) - throw compiler.error_message("Instance variable '" + ivarName + "' is already declared for class " + className + (aClassDef.name !== className ? " in superclass " + aClassDef.name : ""), ivarDecl.id); - if (aClassDef.superClass) - recursiveFunction(aClassDef.superClass, recursiveFunction); - } - - // Check if ivar is already declared in this class or its super classes. - checkIfIvarIsAlreadyDeclaredAndInSuperClass(classDef, checkIfIvarIsAlreadyDeclaredAndInSuperClass); - - var isTypeDefined = !ivarTypeIsClass || typeof global[ivarType] !== "undefined" || typeof window[ivarType] !== "undefined" - || compiler.getClassDef(ivarType) || compiler.getTypeDef(ivarType) || ivarType == classDef.name; - - if (!isTypeDefined && compiler.options.warnings.includes(warningUnknownIvarType)) - compiler.addWarning(createMessage("Unknown type '" + ivarType + "' for ivar '" + ivarName + "'", ivarDecl.ivartype, compiler.source)); - - if (generateObjJ) { - c(ivarDecl, st, "IvarDeclaration"); - } else { - if (firstIvarDeclaration) - { - firstIvarDeclaration = false; - saveJSBuffer.concat("class_addIvars(the_class, ["); - } - else - saveJSBuffer.concat(", "); - - if (options.includeIvarTypeSignatures) - saveJSBuffer.concat("new objj_ivar(\"" + ivarName + "\", \"" + ivarType + "\")", node); - else - saveJSBuffer.concat("new objj_ivar(\"" + ivarName + "\")", node); - } - - if (ivarDecl.outlet) - ivar.outlet = true; - - // Store the classDef ivars into array and add them later when accessors are created to prevent ivar duplicate error when generating accessors - classDefIvars.push(ivar); - - if (!classScope.ivars) - classScope.ivars = Object.create(null); - classScope.ivars[ivarName] = {type: "ivar", name: ivarName, node: ivarIdentifier, ivar: ivar}; - - if (accessors) { - // Declare the accessor methods in the class definition. - // TODO: This next couple of lines for getting getterName and setterName are duplicated from below. Create functions for this. - var property = (accessors.property && accessors.property.name) || ivarName, - getterName = (accessors.getter && accessors.getter.name) || property; - - classDef.addInstanceMethod(new MethodDef(getterName, [ivarType])); - - if (!accessors.readonly) { - var setterName = accessors.setter ? accessors.setter.name : null; - - if (!setterName) - { - var start = property.charAt(0) == '_' ? 1 : 0; - - setterName = (start ? "_" : "") + "set" + property.substr(start, 1).toUpperCase() + property.substring(start + 1) + ":"; - } - classDef.addInstanceMethod(new MethodDef(setterName, ["void", ivarType])); - } - hasAccessors = true; - } - } - } - if (generateObjJ) { - indentation = indentation.substring(indentationSize); - saveJSBuffer.concatFormat("\n}"); - } else if (!firstIvarDeclaration) - saveJSBuffer.concat("]);"); - - // If we have accessors add get and set methods for them - if (!generateObjJ && !isInterfaceDeclaration && hasAccessors) - { - // We pass false to the string buffer as we don't need source map when we create the Objective-J code for the accessors - var getterSetterBuffer = new StringBuffer(false); - - // Add the class declaration to compile accessors correctly - // Remove all protocols from class declaration - getterSetterBuffer.concat(compiler.source.substring(node.start, node.endOfIvars).replace(/<.*>/g, "")); - getterSetterBuffer.concat("\n"); - - for (var i = 0; i < node.ivardeclarations.length; ++i) - { - var ivarDecl = node.ivardeclarations[i], - ivarType = ivarDecl.ivartype ? ivarDecl.ivartype.name : null, - ivarName = ivarDecl.id.name, - accessors = ivarDecl.accessors; - - if (!accessors) - continue; - - var property = (accessors.property && accessors.property.name) || ivarName, - getterName = (accessors.getter && accessors.getter.name) || property, - getterCode = "- (" + (ivarType ? ivarType : "id") + ")" + getterName + "\n{\n return " + ivarName + ";\n}\n"; - - getterSetterBuffer.concat(getterCode); - - if (accessors.readonly) - continue; - - var setterName = accessors.setter ? accessors.setter.name : null; - - if (!setterName) - { - var start = property.charAt(0) == '_' ? 1 : 0; - - setterName = (start ? "_" : "") + "set" + property.substr(start, 1).toUpperCase() + property.substring(start + 1) + ":"; - } - - var setterCode = "- (void)" + setterName + "(" + (ivarType ? ivarType : "id") + ")newValue\n{\n "; - - if (accessors.copy) - setterCode += "if (" + ivarName + " !== newValue)\n " + ivarName + " = [newValue copy];\n}\n"; - else - setterCode += ivarName + " = newValue;\n}\n"; - - getterSetterBuffer.concat(setterCode); - } - - getterSetterBuffer.concat("\n@end"); - - // Remove all @accessors or we will get a recursive loop in infinity - var b = getterSetterBuffer.toString().replace(/@accessors(\(.*\))?/g, ""); - var compilerOptions = setupOptions(options); - - compilerOptions.sourceMapIncludeSource = true; - var url = compiler.url; - var filename = url && compiler.URL.substr(compiler.URL.lastIndexOf('/') + 1); - var dotIndex = filename && filename.lastIndexOf("."); - var filenameNoExt = filename && (filename.substr(0, dotIndex === -1 ? filename.length : dotIndex)); - var filenameExt = filename && filename.substr(dotIndex === -1 ? filename.length : dotIndex); - var categoryname = node.categoryname && node.categoryname.id; - var imBuffer = exports.compileToIMBuffer(b, filenameNoExt + "_" + className + (categoryname ? "_" + categoryname : "") + "_Accessors" + (filenameExt || ""), compilerOptions); - - // Add the accessors methods first to instance method buffer. - // This will allow manually added set and get methods to override the compiler generated - var generatedCode = imBuffer.toString(); - - if (compiler.createSourceMap) { - compiler.imBuffer.concat(sourceMap.SourceNode.fromStringWithSourceMap(generatedCode.code, sourceMap.SourceMapConsumer(generatedCode.map.toString()))); - } else { - compiler.imBuffer.concat(generatedCode); - } - } - - // We will store the ivars into the classDef first after accessors are done so we don't get a duplicate ivars error when generating accessors - for (var ivarSize = classDefIvars.length, i = 0; i < ivarSize; i++) { - var ivar = classDefIvars[i], - ivarName = ivar.name; - - // Store the ivar into the classDef - ivars[ivarName] = ivar; - } - - // We will store the classDef first after accessors are done so we don't get a duplicate class error when generating accessors - compiler.classDefs[className] = classDef; - - var bodies = node.body, - bodyLength = bodies.length; - - if (bodyLength > 0) - { - if (!generate) compiler.lastPos = bodies[0].start; - - // And last add methods and other statements - for (var i = 0; i < bodyLength; ++i) { - var body = bodies[i]; - c(body, classScope, "Statement"); - } - if (!generate) saveJSBuffer.concat(compiler.source.substring(compiler.lastPos, body.end)); - } - - // We must make a new class object for our class definition if it's not a category - if (!generateObjJ && !isInterfaceDeclaration && !node.categoryname) { - saveJSBuffer.concat("objj_registerClassPair(the_class);\n"); - } - - // Add instance methods - if (!generateObjJ && compiler.imBuffer.isEmpty()) - { - saveJSBuffer.concat("class_addMethods(the_class, ["); - saveJSBuffer.appendStringBuffer(compiler.imBuffer); - saveJSBuffer.concat("]);\n"); - } - - // Add class methods - if (!generateObjJ && compiler.cmBuffer.isEmpty()) - { - saveJSBuffer.concat("class_addMethods(meta_class, ["); - saveJSBuffer.appendStringBuffer(compiler.cmBuffer); - saveJSBuffer.concat("]);\n"); - } - - if (!generateObjJ) saveJSBuffer.concat("}\n"); - - compiler.jsBuffer = saveJSBuffer; - - // Skip the "@end" - if (!generate) compiler.lastPos = node.end; - - if (generateObjJ) - saveJSBuffer.concat("\n@end"); - - // If the class conforms to protocols check that all required methods are implemented - if (protocols) - { - // Lookup the protocolDefs for the protocols - var protocolDefs = []; - - for (var i = 0, size = protocols.length; i < size; i++) { - var protocol = protocols[i], - protocolDef = compiler.getProtocolDef(protocol.name); - - if (!protocolDef) - throw compiler.error_message("Cannot find protocol declaration for '" + protocol.name + "'", protocol); - - protocolDefs.push(protocolDef); - } - - var unimplementedMethods = classDef.listOfNotImplementedMethodsForProtocols(protocolDefs); - - if (unimplementedMethods && unimplementedMethods.length > 0) - for (var j = 0, unimpSize = unimplementedMethods.length; j < unimpSize; j++) { - var unimplementedMethod = unimplementedMethods[j], - methodDef = unimplementedMethod.methodDef, - protocolDef = unimplementedMethod.protocolDef; - - compiler.addWarning(createMessage("Method '" + methodDef.name + "' in protocol '" + protocolDef.name + "' is not implemented", node.classname, compiler.source)); - } - } -}, -ProtocolDeclarationStatement: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - buffer = compiler.jsBuffer, - protocolName = node.protocolname.name, - protocolDef = compiler.getProtocolDef(protocolName), - protocols = node.protocols, - protocolScope = new Scope(st), - inheritFromProtocols = [], - generateObjJ = compiler.options.generateObjJ; - - if (protocolDef) - throw compiler.error_message("Duplicate protocol " + protocolName, node.protocolname); - - compiler.imBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL); - compiler.cmBuffer = new StringBuffer(compiler.createSourceMap, compiler.URL); - - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - - if (generateObjJ) { - buffer.concat("@protocol "); - c(node.protocolname, st, "IdentifierName"); - } else { - buffer.concat("{var the_protocol = objj_allocateProtocol(\"" + protocolName + "\");", node); - } - - if (protocols) { - if (generateObjJ) - buffer.concat(" <"); - - for (var i = 0, size = protocols.length; i < size; i++) - { - var protocol = protocols[i], - inheritFromProtocolName = protocol.name, - inheritProtocolDef = compiler.getProtocolDef(inheritFromProtocolName); - - if (!inheritProtocolDef) - throw compiler.error_message("Can't find protocol " + inheritFromProtocolName, protocol); - - if (generateObjJ) { - if (i) - buffer.concat(", "); - - c(protocol, st, "IdentifierName"); - } else { - buffer.concat("\nvar aProtocol = objj_getProtocol(\"" + inheritFromProtocolName + "\");", node); - buffer.concat("\nif (!aProtocol) throw new SyntaxError(\"*** Could not find definition for protocol \\\"" + protocolName + "\\\"\");", node); - buffer.concat("\nprotocol_addProtocol(the_protocol, aProtocol);", node); - } - - inheritFromProtocols.push(inheritProtocolDef); - } - - if (generateObjJ) - buffer.concat(">"); - } - - protocolDef = new ProtocolDef(protocolName, inheritFromProtocols); - compiler.protocolDefs[protocolName] = protocolDef; - protocolScope.protocolDef = protocolDef; - - var someRequired = node.required; - - if (someRequired) { - var requiredLength = someRequired.length; - - if (requiredLength > 0) - { - // We only add the required methods - for (var i = 0; i < requiredLength; ++i) { - var required = someRequired[i]; - if (!generate) compiler.lastPos = required.start; - c(required, protocolScope, "Statement"); - } - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, required.end)); - } - } - - if (generateObjJ) { - buffer.concatFormat("\n@end"); - } else { - buffer.concat("\nobjj_registerProtocol(the_protocol);\n"); - - // Add instance methods - if (compiler.imBuffer.isEmpty()) - { - buffer.concat("protocol_addMethodDescriptions(the_protocol, ["); - buffer.appendStringBuffer(compiler.imBuffer); - buffer.concat("], true, true);\n"); - } - - // Add class methods - if (compiler.cmBuffer.isEmpty()) - { - buffer.concat("protocol_addMethodDescriptions(the_protocol, ["); - buffer.appendStringBuffer(compiler.cmBuffer); - buffer.concat("], true, false);\n"); - } - - buffer.concat("}"); - } - - compiler.jsBuffer = buffer; - - // Skip the "@end" - if (!generate) compiler.lastPos = node.end; -}, -IvarDeclaration: function(node, st, c, format) { - var compiler = st.compiler, - buffer = compiler.jsBuffer; - - if (node.outlet) - buffer.concat("@outlet "); - c(node.ivartype, st, "IdentifierName"); - buffer.concat(" "); - c(node.id, st, "IdentifierName"); - if (node.accessors) - buffer.concat(" @accessors"); -}, -MethodDeclarationStatement: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - saveJSBuffer = compiler.jsBuffer, - methodScope = new FunctionScope(st), - isInstanceMethodType = node.methodtype === '-', - selectors = node.selectors, - nodeArguments = node.arguments, - returnType = node.returntype, - types = [returnType ? returnType.name : (node.action ? "void" : "id")], // Return type is 'id' as default except if it is an action declared method, then it's 'void' - returnTypeProtocols = returnType ? returnType.protocols : null, - selector = selectors[0].name, // There is always at least one selector - generateObjJ = compiler.options.generateObjJ; - - if (returnTypeProtocols) for (var i = 0, size = returnTypeProtocols.length; i < size; i++) { - var returnTypeProtocol = returnTypeProtocols[i]; - if (!compiler.getProtocolDef(returnTypeProtocol.name)) { - compiler.addWarning(createMessage("Cannot find protocol declaration for '" + returnTypeProtocol.name + "'", returnTypeProtocol, compiler.source)); - } - } - - if (!generate) saveJSBuffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - - // If we are generating objective-J code write everything directly to the regular buffer - // Otherwise we have one for instance methods and one for class methods. - if (generateObjJ) { - compiler.jsBuffer.concat(isInstanceMethodType ? "- (" : "+ ("); - compiler.jsBuffer.concat(types[0]); - compiler.jsBuffer.concat(")"); - } else { - compiler.jsBuffer = isInstanceMethodType ? compiler.imBuffer : compiler.cmBuffer; - } - - // Put together the selector. Maybe this should be done in the parser... - // Or maybe we should do it here as when genereting Objective-J code it's kind of handy - var size = nodeArguments.length; - if (size > 0) { - for (var i = 0; i < nodeArguments.length; i++) { - var argument = nodeArguments[i], - argumentType = argument.type, - argumentTypeName = argumentType ? argumentType.name : "id", - argumentProtocols = argumentType ? argumentType.protocols : null; - - types.push(argumentTypeName); - - if (i === 0) - selector += ":"; - else - selector += (selectors[i] ? selectors[i].name : "") + ":"; - - if (argumentProtocols) for (var j = 0, size = argumentProtocols.length; j < size; j++) { - var argumentProtocol = argumentProtocols[j]; - if (!compiler.getProtocolDef(argumentProtocol.name)) { - compiler.addWarning(createMessage("Cannot find protocol declaration for '" + argumentProtocol.name + "'", argumentProtocol, compiler.source)); - } - } - - if (generateObjJ) { - var aSelector = selectors[i]; - - if (i) - compiler.jsBuffer.concat(" "); - - compiler.jsBuffer.concat((aSelector ? aSelector.name : "") + ":"); - compiler.jsBuffer.concat("("); - compiler.jsBuffer.concat(argumentTypeName); - if (argumentProtocols) { - compiler.jsBuffer.concat(" <"); - for (var j = 0, size = argumentProtocols.length; j < size; j++) { - var argumentProtocol = argumentProtocols[j]; - - if (j) - compiler.jsBuffer.concat(", "); - - compiler.jsBuffer.concat(argumentProtocol.name); - } - - compiler.jsBuffer.concat(">"); - } - compiler.jsBuffer.concat(")"); - c(argument.identifier, st, "IdentifierName"); - } - } - } else if (generateObjJ) { - var selectorNode = selectors[0]; - compiler.jsBuffer.concat(selectorNode.name, selectorNode); - } - - if (generateObjJ) { - if (node.parameters) { - compiler.jsBuffer.concat(", ..."); - } - } else { - if (compiler.jsBuffer.isEmpty()) // Add comma separator if this is not first method in this buffer - compiler.jsBuffer.concat(", "); - - compiler.jsBuffer.concat("new objj_method(sel_getUid(\"", node); - compiler.jsBuffer.concat(selector); - compiler.jsBuffer.concat("\"), "); - } - - if (node.body) { - if (!generateObjJ) { - compiler.jsBuffer.concat("function"); - - if (compiler.options.includeMethodFunctionNames) - { - compiler.jsBuffer.concat(" $" + st.currentClassName() + "__" + selector.replace(/:/g, "_")); - } - - compiler.jsBuffer.concat("(self, _cmd"); - } - - methodScope.methodType = node.methodtype; - methodScope.vars["self"] = {type: "method base", scope: methodScope}; - methodScope.vars["_cmd"] = {type: "method base", scope: methodScope}; - - if (nodeArguments) for (var i = 0; i < nodeArguments.length; i++) - { - var argument = nodeArguments[i], - argumentName = argument.identifier.name; - - if (!generateObjJ) { - compiler.jsBuffer.concat(", "); - compiler.jsBuffer.concat(argumentName, argument.identifier); - } - methodScope.vars[argumentName] = {type: "method argument", node: argument}; - } - - if (!generateObjJ) - compiler.jsBuffer.concat(")\n"); - - if (!generate) compiler.lastPos = node.startOfBody; - indentation += indentStep; - methodScope.endOfScopeBody = true; - c(node.body, methodScope, "Statement"); - methodScope.variablesNotReadWarnings(); - indentation = indentation.substring(indentationSize); - if (!generate) compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, node.body.end)); - - if (!generateObjJ) - compiler.jsBuffer.concat("\n"); - } else { // It is a interface or protocol declatartion and we don't have a method implementation - if (generateObjJ) - compiler.jsBuffer.concat(";"); - else - compiler.jsBuffer.concat("Nil\n"); - } - - if (!generateObjJ) { - if (compiler.options.includeMethodArgumentTypeSignatures) - compiler.jsBuffer.concat(","+JSON.stringify(types)); - compiler.jsBuffer.concat(")"); - compiler.jsBuffer = saveJSBuffer; - } - - if (!generate) compiler.lastPos = node.end; - - // Add the method to the class or protocol definition - var def = st.classDef, - alreadyDeclared; - - // But first, if it is a class definition check if it is declared in superclass or interface declaration - if (def) - alreadyDeclared = isInstanceMethodType ? def.getInstanceMethod(selector) : def.getClassMethod(selector); - else - def = st.protocolDef; - - if (!def) - throw "InternalError: MethodDeclaration without ClassDeclaration or ProtocolDeclaration at line: " + acorn.getLineInfo(compiler.source, node.start).line; - - // Create warnings if types does not corresponds to method declaration in superclass or interface declarations - // If we don't find the method in superclass or interface declarations above or if it is a protocol - // declaration, try to find it in any of the conforming protocols - if (!alreadyDeclared) { - var protocols = def.protocols; - - if (protocols) for (var i = 0, size = protocols.length; i < size; i++) { - var protocol = protocols[i], - alreadyDeclared = isInstanceMethodType ? protocol.getInstanceMethod(selector) : protocol.getClassMethod(selector); - - if (alreadyDeclared) - break; - } - } - - if (alreadyDeclared) { - var declaredTypes = alreadyDeclared.types; - - if (declaredTypes) { - var typeSize = declaredTypes.length; - if (typeSize > 0) { - // First type is return type - var declaredReturnType = declaredTypes[0]; - - // Create warning if return types is not the same. It is ok if superclass has 'id' and subclass has a class type - if (declaredReturnType !== types[0] && !(declaredReturnType === 'id' && returnType && returnType.typeisclass)) - compiler.addWarning(createMessage("Conflicting return type in implementation of '" + selector + "': '" + declaredReturnType + "' vs '" + types[0] + "'", returnType || node.action || selectors[0], compiler.source)); - - // Check the parameter types. The size of the two type arrays should be the same as they have the same selector. - for (var i = 1; i < typeSize; i++) { - var parameterType = declaredTypes[i]; - - if (parameterType !== types[i] && !(parameterType === 'id' && nodeArguments[i - 1].type.typeisclass)) - compiler.addWarning(createMessage("Conflicting parameter types in implementation of '" + selector + "': '" + parameterType + "' vs '" + types[i] + "'", nodeArguments[i - 1].type || nodeArguments[i - 1].identifier, compiler.source)); - } - } - } - } - - // Now we add it - var methodDef = new MethodDef(selector, types); - - if (isInstanceMethodType) - def.addInstanceMethod(methodDef); - else - def.addClassMethod(methodDef); -}, -MessageSendExpression: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - inlineMsgSend = compiler.options.inlineMsgSendFunctions, - buffer = compiler.jsBuffer, - nodeObject = node.object, - selectors = node.selectors, - nodeArguments = node.arguments, - argumentsLength = nodeArguments.length, - firstSelector = selectors[0], - selector = firstSelector ? firstSelector.name : "", // There is always at least one selector - parameters = node.parameters, - options = compiler.options, - generateObjJ = options.generateObjJ; - - // Put together the selector. Maybe this should be done in the parser... - for (var i = 0; i < argumentsLength; i++) { - if (i !== 0) { - var nextSelector = selectors[i]; - if (nextSelector) - selector += nextSelector.name; - } - selector += ":"; - } - - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = nodeObject ? nodeObject.start : node.arguments.length ? node.arguments[0].start : node.end; - } else if (!inlineMsgSend) { - // Find out the total number of arguments so we can choose appropriate msgSend function. Only needed if call the function and not inline it - var totalNoOfParameters = argumentsLength; - - if (parameters) - totalNoOfParameters += parameters.length; - } - if (node.superObject) - { - if (!generate) buffer.concat(" "); // Add an extra space if it looks something like this: "return()". No space between return and expression. - if (generateObjJ) { - buffer.concat("[super "); - } else { - if (inlineMsgSend) { - buffer.concat("(", node); - buffer.concat(st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass); - buffer.concat(".method_dtable[\"", node); - buffer.concat(selector); - buffer.concat("\"] || _objj_forward)(self", node); - } else { - buffer.concat("objj_msgSendSuper", node); - if (totalNoOfParameters < 4) { - buffer.concat("" + totalNoOfParameters); - } - buffer.concat("({ receiver:self, super_class:" + (st.currentMethodType() === "+" ? compiler.currentSuperMetaClass : compiler.currentSuperClass ) + " }", node); - } - } - } - else - { - if (generate) { - // If the recevier is not an identifier or an ivar that should have 'self.' infront we need to assign it to a temporary variable - // If it is 'self' we assume it will never be nil and remove that test - var receiverIsIdentifier = nodeObject.type === "Identifier" && !(st.currentMethodType() === "-" && compiler.getIvarForClass(nodeObject.name, st) && !st.getLvar(nodeObject.name, true)), - selfLvar, - receiverIsNotSelf; - - if (receiverIsIdentifier) { - var name = nodeObject.name, - selfLvar = st.getLvar(name); - - if (name === "self") { - receiverIsNotSelf = !selfLvar || !selfLvar.scope || selfLvar.scope.assignmentToSelf; - } else { - receiverIsNotSelf = !!selfLvar || !compiler.getClassDef(name); - } - - if (receiverIsNotSelf) { - buffer.concat("(", node); - c(nodeObject, st, "Expression"); - buffer.concat(" == null ? ", node); - c(nodeObject, st, "Expression"); - buffer.concat(" : ", node); - } - if (inlineMsgSend) - buffer.concat("(", node); - c(nodeObject, st, "Expression"); - } else { - receiverIsNotSelf = true; - if (!st.receiverLevel) st.receiverLevel = 0; - buffer.concat("((___r" + ++st.receiverLevel, node); - buffer.concat(" = ", node); - c(nodeObject, st, "Expression"); - buffer.concat(")", node); - buffer.concat(", ___r" + st.receiverLevel, node); - buffer.concat(" == null ? ", node); - buffer.concat("___r" + st.receiverLevel, node); - buffer.concat(" : ", node); - if (inlineMsgSend) - buffer.concat("(", node); - buffer.concat("___r" + st.receiverLevel, node); - if (!(st.maxReceiverLevel >= st.receiverLevel)) - st.maxReceiverLevel = st.receiverLevel; - } - if (inlineMsgSend) { - buffer.concat(".isa.method_msgSend[\"", node); - buffer.concat(selector, node); - buffer.concat("\"] || _objj_forward)", node); - } else { - buffer.concat(".isa.objj_msgSend", node); - } - } else { - buffer.concat(" "); // Add an extra space if it looks something like this: "return()". No space between return and expression. - buffer.concat("objj_msgSend("); - buffer.concat(compiler.source.substring(compiler.lastPos, nodeObject.end)); - } - } - - if (generateObjJ) { - for (var i = 0; i < argumentsLength || (argumentsLength === 0 && i === 0); i++) { - var selector = selectors[i]; - - buffer.concat(" "); - buffer.concat(selector ? selector.name : ""); - - if (argumentsLength > 0) { - var argument = nodeArguments[i]; - - buffer.concat(":"); - c(argument, st, "Expression"); - } - } - - if (parameters) for (var i = 0, size = parameters.length; i < size; ++i) - { - var parameter = parameters[i]; - - buffer.concat(", "); - c(parameter, st, "Expression"); - } - buffer.concat("]"); - } else { - var selectorJSPath; - - if (generate && !node.superObject) { - if (!inlineMsgSend) { - if (totalNoOfParameters < 4) { - buffer.concat("" + totalNoOfParameters, node); - } - } - - if (receiverIsIdentifier) { - buffer.concat("(", node); - c(nodeObject, st, "Expression"); - } else { - buffer.concat("(___r" + st.receiverLevel, node); - } - - // Only do this if source map is enabled and we have an identifier - if (options.sourceMap && nodeObject.type === "Identifier") { - // Get target expression for sourcemap to allow hovering selector to show method function. Create new buffer to write in. - compiler.jsBuffer = new StringBuffer(); - c(nodeObject, st, "Expression"); - var aTarget = compiler.jsBuffer.toString(); - selectorJSPath = aTarget + ".isa.method_dtable[\"" + selector + "\"]" - // Restored buffer so everything will continue as usually. - compiler.jsBuffer = buffer; - } - } - - buffer.concat(", ", node); - if (selectorJSPath) { - buffer.concat("(", node); - for (var i = 0; i < selectors.length; i++) { - var nextSelector = selectors[i]; - if (nextSelector) { - buffer.concat(selectorJSPath, nextSelector); - buffer.concat(", ", node); - } - } - } - buffer.concat("\"", node); - - buffer.concat(selector, node); // FIXME: sel_getUid(selector + "") ? This FIXME is from the old preprocessor compiler - buffer.concat(selectorJSPath ? "\")" : "\"", node); - - if (nodeArguments) for (var i = 0; i < nodeArguments.length; i++) - { - var argument = nodeArguments[i]; - - buffer.concat(", ", node); - if (!generate) - compiler.lastPos = argument.start; - c(argument, st, "Expression"); - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, argument.end)); - compiler.lastPos = argument.end; - } - } - - if (parameters) for (var i = 0; i < parameters.length; ++i) - { - var parameter = parameters[i]; - - buffer.concat(", ", node); - if (!generate) - compiler.lastPos = parameter.start; - c(parameter, st, "Expression"); - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, parameter.end)); - compiler.lastPos = parameter.end; - } - } - - if (generate && !node.superObject) { - if (receiverIsNotSelf) - buffer.concat(")", node); - if (!receiverIsIdentifier) - st.receiverLevel--; - } - - buffer.concat(")", node); - } - - if (!generate) compiler.lastPos = node.end; -}, -SelectorLiteralExpression: function(node, st, c) { - var compiler = st.compiler, - buffer = compiler.jsBuffer, - generate = compiler.generate, - generateObjJ = compiler.options.generateObjJ; - - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - buffer.concat(" "); // Add an extra space if it looks something like this: "return(@selector(a:))". No space between return and expression. - } - - buffer.concat(generateObjJ ? "@selector(" : "sel_getUid(\"", node); - buffer.concat(node.selector); - buffer.concat(generateObjJ ? ")" : "\")"); - - if (!generate) compiler.lastPos = node.end; -}, -ProtocolLiteralExpression: function(node, st, c) { - var compiler = st.compiler, - buffer = compiler.jsBuffer, - generate = compiler.generate, - generateObjJ = compiler.options.generateObjJ; - - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - buffer.concat(" "); // Add an extra space if it looks something like this: "return(@protocol(a))". No space between return and expression. - } - buffer.concat(generateObjJ ? "@protocol(" : "objj_getProtocol(\"", node); - c(node.id, st, "IdentifierName"); - buffer.concat(generateObjJ ? ")" : "\")"); - if (!generate) compiler.lastPos = node.end; -}, -Reference: function(node, st, c) { - var compiler = st.compiler, - buffer = compiler.jsBuffer, - generate = compiler.generate, - generateObjJ = compiler.options.generateObjJ; - - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - buffer.concat(" "); // Add an extra space if it looks something like this: "return()". No space between return and expression. - } - if (generateObjJ) { - buffer.concat("@ref(", node); - buffer.concat(node.element.name, node.element); - buffer.concat(")", node); - } else { - buffer.concat("function(__input) { if (arguments.length) return ", node); - c(node.element, st, "Expression"); - buffer.concat(" = __input; return "); - c(node.element, st, "Expression"); - buffer.concat("; }"); - } - - if (!generate) compiler.lastPos = node.end; -}, -Dereference: function(node, st, c) { - var compiler = st.compiler, - buffer = compiler.jsBuffer, - generate = compiler.generate, - generateObjJ = compiler.options.generateObjJ; - - checkCanDereference(st, node.expr); - - // @deref(y) -> y() - // @deref(@deref(y)) -> y()() - if (!generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = node.expr.start; - } - if (generateObjJ) - buffer.concat("@deref("); - c(node.expr, st, "Expression"); - if (!generate) buffer.concat(compiler.source.substring(compiler.lastPos, node.expr.end)); - if (generateObjJ) - buffer.concat(")"); - else - buffer.concat("()"); - if (!generate) compiler.lastPos = node.end; -}, -ClassStatement: function(node, st, c) { - var compiler = st.compiler, - buffer = compiler.jsBuffer, - generateObjJ = compiler.options.generateObjJ; - if (!compiler.generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = node.start; - buffer.concat("//"); - } - if (generateObjJ) { - buffer.concat("@class "); - c(node.id, st, "IdentifierName"); - } - var className = node.id.name; - - if (compiler.getTypeDef(className)) - throw compiler.error_message(className + " is already declared as a type", node.id); - - if (!compiler.getClassDef(className)) { - compiler.classDefs[className] = new ClassDef(false, className); - } - st.vars[node.id.name] = {type: "class", node: node.id}; -}, -GlobalStatement: function(node, st, c) { - var compiler = st.compiler, - buffer = compiler.jsBuffer, - generateObjJ = compiler.options.generateObjJ; - if (!compiler.generate) { - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = node.start; - buffer.concat("//"); - } - if (generateObjJ) { - buffer.concat("@global "); - c(node.id, st, "IdentifierName"); - } - st.rootScope().vars[node.id.name] = {type: "global", node: node.id}; -}, -PreprocessStatement: function(node, st, c) { - var compiler = st.compiler; - if (!compiler.generate) { - compiler.jsBuffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - compiler.lastPos = node.start; - compiler.jsBuffer.concat("//"); - } -}, -TypeDefStatement: function(node, st, c) { - var compiler = st.compiler, - generate = compiler.generate, - buffer = compiler.jsBuffer, - typeDefName = node.typedefname.name, - typeDef = compiler.getTypeDef(typeDefName), - typeDefScope = new Scope(st); - - if (typeDef) - throw compiler.error_message("Duplicate type definition " + typeDefName, node.typedefname); - - if (compiler.getClassDef(typeDefName)) - throw compiler.error_message(typeDefName + " is already declared as class", node.typedefname); - - if (!generate) - buffer.concat(compiler.source.substring(compiler.lastPos, node.start)); - - buffer.concat("{var the_typedef = objj_allocateTypeDef(\"" + typeDefName + "\");", node); - - typeDef = new TypeDef(typeDefName); - compiler.typeDefs[typeDefName] = typeDef; - typeDefScope.typeDef = typeDef; - - buffer.concat("\nobjj_registerTypeDef(the_typedef);\n"); - - buffer.concat("}"); - - // Skip to the end - if (!generate) - compiler.lastPos = node.end; -} -}); - -}); diff --git a/Objective-J/acorn.js b/Objective-J/acorn.js deleted file mode 100644 index aec95c368..000000000 --- a/Objective-J/acorn.js +++ /dev/null @@ -1,3885 +0,0 @@ -// Acorn is a tiny, fast JavaScript parser written in JavaScript. -// -// Acorn was written by Marijn Haverbeke and released under an MIT -// license. The Unicode regexps (for identifiers and whitespace) were -// taken from [Esprima](http://esprima.org) by Ariya Hidayat. -// -// Git repositories for Acorn are available at -// -// http://marijnhaverbeke.nl/git/acorn -// https://github.com/marijnh/acorn.git -// -// Please use the [github bug tracker][ghbt] to report issues. -// -// [ghbt]: https://github.com/marijnh/acorn/issues -// -// Objective-J extensions made by Martin Carlberg -// -// Git repositories for Acorn with Objective-J extension is available at -// -// https://github.com/mrcarlberg/acorn.git -// -// This file defines the main parser interface. The library also comes -// with a [error-tolerant parser][dammit] and an -// [abstract syntax tree walker][walk], defined in other files. -// -// [dammit]: acorn_loose.js -// [walk]: util/walk.js - - -(function(exports, walk) { - "use strict"; - - exports.version = "0.3.3-objj-3"; - - // The main exported interface (under `self.acorn` when in the - // browser) is a `parse` function that takes a code string and - // returns an abstract syntax tree as specified by [Mozilla parser - // API][api], with the caveat that the SpiderMonkey-specific syntax - // (`let`, `yield`, inline XML, etc) is not recognized. - // - // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API - - var options, input, inputLen, sourceFile; - - exports.parse = function(inpt, opts) { - input = String(inpt); inputLen = input.length; - setOptions(opts); - initPreprocessorState(); - if (options.macros) - defineMacros(options.macros); - initTokenState(); - return parseTopLevel(options.program); - }; - - // A second optional argument can be given to further configure - // the parser process. These options are recognized: - - var defaultOptions = exports.defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3 or 5. This - // influences support for strict mode, the set of reserved words, and - // support for getters and setter. - ecmaVersion: 5, - // Turn on `strictSemicolons` to prevent the parser from doing - // automatic semicolon insertion. - strictSemicolons: false, - // When `allowTrailingCommas` is false, the parser will not allow - // trailing commas in array and object literals. - allowTrailingCommas: true, - // By default, reserved words are not enforced. Enable - // `forbidReserved` to enforce them. - forbidReserved: false, - // When `trackComments` is turned on, the parser will attach - // `commentsBefore` and `commentsAfter` properties to AST nodes - // holding arrays of strings. A single comment may appear in both - // a `commentsBefore` and `commentsAfter` array (of the nodes - // after and before it), but never twice in the before (or after) - // array of different nodes. - trackComments: false, - // When `trackCommentsIncludeLineBreak` is turned on, the parser will - // include, if present, the line break before the comment and all - // the whitespace in between. - trackCommentsIncludeLineBreak: false, - // When `trackSpaces` is turned on, the parser will attach - // `spacesBefore` and `spacesAfter` properties to AST nodes - // holding arrays of strings. The same spaces may appear in both - // a `spacesBefore` and `spacesAfter` array (of the nodes - // after and before it), but never twice in the before (or after) - // array of different nodes. - trackSpaces: false, - // When `locations` is on, `loc` properties holding objects with - // `start` and `end` properties in `{line, column}` form (with - // line being 1-based and column 0-based) will be attached to the - // nodes. - locations: false, - // A function can be passed as `onComment` option, which will - // cause Acorn to call that function with `(block, text, start, - // end)` parameters whenever a comment is skipped. `block` is a - // boolean indicating whether this is a block (`/* */`) comment, - // `text` is the content of the comment, and `start` and `end` are - // character offsets that denote the start and end of the comment. - // When the `locations` option is on, two more parameters are - // passed, the full `{line, column}` locations of the start and - // end of the comments. - onComment: null, - // Nodes have their start and end characters offsets recorded in - // `start` and `end` properties (directly on the node, rather than - // the `loc` object, which holds line/column data. To also add a - // [semi-standardized][range] `range` property holding a `[start, - // end]` array with the same numbers, set the `ranges` option to - // `true`. - // - // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - ranges: false, - // It is possible to parse multiple files into a single AST by - // passing the tree produced by parsing the first file as - // `program` option in subsequent parses. This will add the - // toplevel forms of the parsed file to the `Program` (top) node - // of an existing parse tree. - program: null, - // When `location` is on, you can pass this to record the source - // file in every node's `loc` object. - sourceFile: null, - // Turn on objj to allow Objective-J syntax - objj: true, - // Turn on preprocess to allow C preprocess derectives. - // #define macro1 - // #define macro2 console.log("Hello") - // #define macro3(x,y,z) if (x > y && y > z) console.log("Touchdown!!!") - // #if macro1 - // #else - // #endif - // etc... - preprocess: true, - // Preprocess 'get include file' function. It should return an object with two attributes - // 'include': a string with the file to be included - // 'sourceFile': is optional and should be a string with the filename. It will - // be included in the locations property as 'source' - // Return null if file can't be found. The parser will raise an exception - preprocessGetIncludeFile: defaultGetIncludeFile, - // Preprocess add macro function - preprocessAddMacro: defaultAddMacro, - // Preprocess get macro function - preprocessGetMacro: defaultGetMacro, - // Preprocess undefine macro function. To delete a macro - preprocessUndefineMacro: defaultUndefineMacro, - // Preprocess is macro function - preprocessIsMacro: defaultIsMacro, - // An array of macro objects and/or text definitions may be passed in. - // Definitions may be in one of two forms: - // macro - // macro=body - macros: null, - // Turn off lineNoInErrorMessage to exclude line number in error messages - // Needs to be on to run test cases - lineNoInErrorMessage: true, - // Array of files to parse before parsing the main file. Each item is an - // object containing the properties 'include' and 'sourceFile'. 'include' - // has the content from the file and 'sourceFile' has the file path. - // The preprocess options must be turn on for this. - preIncludeFiles: null - }; - - function setOptions(opts) { - options = opts || {}; - for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt)) - options[opt] = defaultOptions[opt]; - sourceFile = options.sourceFile || null; - } - - var macros; - var macrosIsPredicate; - - var macrosMakeBuiltin = function(name, macro, endPos) {return new Macro(name, macro, null, endPos - name.length)} - - var macrosBuiltinMacros = { - __OBJJ__: function() {return macrosMakeBuiltin("__OBJJ__", options.objj ? "1" : null, tokPos)} - } - - macrosBuiltinMacros["__" + "BROWSER" + "__"] = function() {return macrosMakeBuiltin("__BROWSER__", typeof(window) !== "undefined" ? "1" : null, tokPos)}; - macrosBuiltinMacros["__" + "LINE" + "__"] = function() {return macrosMakeBuiltin("__LINE__", String(options.locations ? tokCurLine : getLineInfo(input, tokPos).line), tokPos)}; - macrosBuiltinMacros["__" + "DATE" + "__"] = function() {var date, day; return macrosMakeBuiltin("__DATE__", (date = new Date(), day = String(date.getDate()), ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()] + (day.length > 1 ? " " : " ") + day + " " + date.getFullYear()), tokPos)}; - macrosBuiltinMacros["__" + "TIME" + "__"] = function() {var date; return macrosMakeBuiltin("__TIME__", (date = new Date(), ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2) + ":" + ("0" + date.getSeconds()).slice(-2)), tokPos)}; - - function defaultGetIncludeFile(filename) { - return {include: "#define FOO(x) x\n", sourceFile: filename}; - } - - function defaultAddMacro(macro) { - macros[macro.identifier] = macro; - macrosIsPredicate = null; - } - - function defaultGetMacro(macroIdentifier) { - return macros[macroIdentifier]; - } - - function defaultUndefineMacro(macroIdentifier) { - delete macros[macroIdentifier]; - macrosIsPredicate = null; - } - - function defaultIsMacro(macroIdentifier) { - return (macrosIsPredicate || (macrosIsPredicate = makePredicate(Object.keys(macros).concat(Object.keys(macrosBuiltinMacros).filter(function(key) {return this[key]().macro != null}, macrosBuiltinMacros)).join(" "))))(macroIdentifier); - } - - function preprocessBuiltinMacro(macroIdentifier) { - var builtinMacro = macrosBuiltinMacros[macroIdentifier]; - return builtinMacro ? builtinMacro() : null; - } - - function defineMacros(macroArray) { - for (var i = 0, size = macroArray.length; i < size; i++) { - var savedInput = input; - var macroDefinition = macroArray[i].trim(); - var pos = macroDefinition.indexOf("="); - if (pos === 0) - raise(0, "Invalid macro definition: '" + macroDefinition + "'"); - // If there is no macro body, define the name with the value 1 - var name, body; - if (pos > 0) { - name = macroDefinition.slice(0, pos); - body = macroDefinition.slice(pos + 1); - } - else { - name = macroDefinition; - } - if (macrosBuiltinMacros.hasOwnProperty(name)) - raise(0, "'" + name + "' is a predefined macro name"); - - input = name + (body != null ? " " + body : ""); - inputLen = input.length; - initTokenState(); - preprocessParseDefine(); - input = savedInput; - inputLen = input.length; - } - } - - // The `getLineInfo` function is mostly useful when the - // `locations` option is off (for performance reasons) and you - // want to find the line/column position for a given character - // offset. `input` should be the code string that the offset refers - // into. - - var getLineInfo = exports.getLineInfo = function(input, offset) { - for (var line = 1, cur = 0;;) { - lineBreak.lastIndex = cur; - var match = lineBreak.exec(input); - if (match && match.index < offset) { - ++line; - cur = match.index + match[0].length; - } else break; - } - return {line: line, column: offset - cur, lineStart: cur, lineEnd: (match ? match.index + match[0].length : input.length)}; - }; - - // Acorn is organized as a tokenizer and a recursive-descent parser. - // The `tokenize` export provides an interface to the tokenizer. - // Because the tokenizer is optimized for being efficiently used by - // the Acorn parser itself, this interface is somewhat crude and not - // very modular. Performing another parse or call to `tokenize` will - // reset the internal state, and invalidate existing tokenizers. - - exports.tokenize = function(inpt, opts) { - input = String(inpt); inputLen = input.length; - setOptions(opts); - initTokenState(); - initPreprocessorState(); - - var t = {}; - function getToken(forceRegexp) { - readToken(forceRegexp); - t.start = tokStart; t.end = tokEnd; - t.startLoc = tokStartLoc; t.endLoc = tokEndLoc; - t.type = tokType; t.value = tokVal; - return t; - } - getToken.jumpTo = function(pos, reAllowed) { - tokPos = pos; - if (options.locations) { - tokCurLine = 1; - tokLineStart = lineBreak.lastIndex = 0; - var match; - while ((match = lineBreak.exec(input)) && match.index < pos) { - ++tokCurLine; - tokLineStart = match.index + match[0].length; - } - } - tokRegexpAllowed = reAllowed; - skipSpace(); - }; - return getToken; - }; - - // State is kept in (closure-)global variables. We already saw the - // `options`, `input`, and `inputLen` variables above. - - // The current position of the tokenizer in the input. - - var tokPos; - - // The start and end offsets of the current token. - // First tokstart is the same as tokStart except when the preprocessor finds a macro. - // Then the tokFirstStart points to the start of the token that will be replaced by the macro. - // tokStart then points at the macros first - // tokMacroOffset is the offset to the current macro for the current token - // tokPosMacroOffset is the offset to the current macro for the current tokPos - - var tokFirstStart, firstTokEnd, tokStart, tokEnd, tokMacroOffset, tokPosMacroOffset, lastTokMacroOffset; - - // This is the end position for the last token in the current `input` buffer. Both regular and preprocess - // tokens count. It is '0' when entering a new buffer. It is used to determinate if a preprocess (#if) token - // is at the begining of a line - - var localLastEnd; - - // Is null except when a macro has ended and then contains the position of the last position in the tokens macro. - // `lastEndOfFile` contains this value for the last token. It is used to allow a semicolon to be inserted at the - // end of a macro. You can say an end of file is equivalent to a new line. - - var firstEndOfFile, lastEndOfFile; - - // When `options.locations` is true, these hold objects - // containing the tokens start and end line/column pairs. - - var tokStartLoc, tokEndLoc; - - // The type and value of the current token. Token types are objects, - // named by variables against which they can be compared, and - // holding properties that describe them (indicating, for example, - // the precedence of an infix operator, and the original name of a - // keyword token). The kind of value that's held in `tokVal` depends - // on the type of the token. For literals, it is the literal value, - // for operators, the operator name, and so on. - - var tokType, tokVal; - - // These are used to hold arrays of comments when - // `options.trackComments` is true. - - var tokCommentsBefore, tokCommentsAfter, lastTokCommentsAfter; - - // These are used to hold arrays of spaces when - // `options.trackSpaces` is true. - - var tokSpacesBefore, tokSpacesAfter, lastTokSpacesAfter; - - // Interal state for the tokenizer. To distinguish between division - // operators and regular expressions, it remembers whether the last - // token was one that is allowed to be followed by an expression. - // (If it is, a slash is probably a regexp, if it isn't it's a - // division operator. See the `parseStatement` function for a - // caveat.) - - var tokRegexpAllowed, tokComments, tokSpaces; - - // When `options.locations` is true, these are used to keep - // track of the current line, and know when a new line has been - // entered. - - var tokCurLine, tokLineStart; - - // Same as input but for the current token. If options.preprocess is used - // this can differ due to macros. - - var tokInput, preTokInput, lastEndInput; - - // These store the position of the previous token, which is useful - // when finishing a node and assigning its `end` position. - - var lastStart, lastEnd, lastEndLoc; - - // This is the tokenizer's state for Objective-J. 'nodeMessageSendObjectExpression' - // is used to store the expression that is already parsed when a subscript was - // not really a subscript. - - var nodeMessageSendObjectExpression; - - // This is the parser's state. `inFunction` is used to reject - // `return` statements outside of functions, `labels` to verify that - // `break` and `continue` have somewhere to jump to, and `strict` - // indicates whether strict mode is on. - - var inFunction, labels, strict; - - // These are used by the preprocess tokenizer. - - var preTokType, preTokVal, preTokStart, preTokEnd; - var preLastStart, preLastEnd; - var preprocessStack; - var preprocessStackLastItem; - var preprocessOnlyTransformArgumentsForLastToken; - var preprocessMacroParameterListMode; - var preprocessIsParsingPreprocess; - var preprocessParameterScope; - var preTokParameterScope; - var preprocessOverrideTokEndLoc; - var preprocessDontConcatenate; // Don't concatenate tokens when finishing preprocess tokens - - // True if we are concatenating two tokens. This is needed to handle when the second part is an empty macro - // This is also used when stingifying tokens to get an empty macro - - var preConcatenating; - - // True if we are skipping token when finding #else or #endif after and #if - - var preNotSkipping; - var preIfLevel; - - // This function is used to raise exceptions on parse errors. It - // takes either a `{line, column}` object or an offset integer (into - // the current `input`) as `pos` argument. It attaches the position - // to the end of the error message, and then raises a `SyntaxError` - // with that message. - - function raise(pos, message) { - if (typeof pos == "number") pos = getLineInfo(input, pos); - if (options.lineNoInErrorMessage) - message += " (" + pos.line + ":" + pos.column + ")"; - var syntaxError = new SyntaxError(message); - syntaxError.messageOnLine = pos.line; - syntaxError.messageOnColumn = pos.column; - syntaxError.lineStart = pos.lineStart; - syntaxError.lineEnd = pos.lineEnd; - syntaxError.fileName = sourceFile; - - throw syntaxError; - } - - // Reused empty array added for node fields that are always empty. - - var empty = []; - - // ## Token types - - // The assignment of fine-grained, information-carrying type objects - // allows the tokenizer to store the information it has about a - // token in a way that is very cheap for the parser to look up. - - // All token type variables start with an underscore, to make them - // easy to recognize. - - // These are the general types. The `type` property is only used to - // make them recognizeable when debugging. - - var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"}; - var _name = {type: "name"}, _eof = {type: "eof"}, _eol = {type: "eol"}; - - // Keyword tokens. The `keyword` property (also used in keyword-like - // operators) indicates that the token originated from an - // identifier-like word, which is used when parsing property names. - // - // The `beforeExpr` property is used to disambiguate between regular - // expressions and divisions. It is set on all token types that can - // be followed by an expression (thus, a slash after them would be a - // regular expression). - // - // `isLoop` marks a keyword as starting a loop, which is important - // to know when parsing a label, in order to allow or disallow - // continue jumps to that label. - - var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"}; - var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"}; - var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true}; - var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"}; - var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"}; - var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"}; - var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true}; - var _this = {keyword: "this"}; - var _void = {keyword: "void", prefix: true, beforeExpr: true}; - - // The keywords that denote values. - - var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true}; - var _false = {keyword: "false", atomValue: false}; - - // Some keywords are treated as regular operators. `in` sometimes - // (when parsing `for`) needs to be tested against specifically, so - // we assign a variable name to it for quick comparing. - - var _in = {keyword: "in", binop: 7, beforeExpr: true}; - - // Objective-J @ keywords - - var _implementation = {keyword: "implementation"}, _outlet = {keyword: "outlet"}, _accessors = {keyword: "accessors"}; - var _end = {keyword: "end"}, _import = {keyword: "import"}; - var _action = {keyword: "action"}, _selector = {keyword: "selector"}, _class = {keyword: "class"}, _global = {keyword: "global"}; - var _dictionaryLiteral = {keyword: "{"}, _arrayLiteral = {keyword: "["}; - var _ref = {keyword: "ref"}, _deref = {keyword: "deref"}; - var _protocol = {keyword: "protocol"}, _optional = {keyword: "optional"}, _required = {keyword: "required"}; - var _interface = {keyword: "interface"}; - var _typedef = {keyword: "typedef"}; - - // Objective-J keywords - - var _filename = {keyword: "filename"}, _unsigned = {keyword: "unsigned", okAsIdent: true}, _signed = {keyword: "signed", okAsIdent: true}; - var _byte = {keyword: "byte", okAsIdent: true}, _char = {keyword: "char", okAsIdent: true}, _short = {keyword: "short", okAsIdent: true}; - var _int = {keyword: "int", okAsIdent: true}, _long = {keyword: "long", okAsIdent: true}, _id = {keyword: "id", okAsIdent: true}; - var _boolean = {keyword: "BOOL", okAsIdent: true}, _SEL = {keyword: "SEL", okAsIdent: true}, _float = {keyword: "float", okAsIdent: true}; - var _double = {keyword: "double", okAsIdent: true}; - var _preprocess = {keyword: "#"}; - - // Preprocessor keywords - - var _preDefine = {keyword: "define"}; - var _preUndef = {keyword: "undef"}; - var _preIfdef = {keyword: "ifdef"}; - var _preIfndef = {keyword: "ifndef"}; - var _preIf = {keyword: "if"}; - var _preElse = {keyword: "else"}; - var _preEndif = {keyword: "endif"}; - var _preElseIf = {keyword: "elif"}; - var _preElseIfTrue = {keyword: "elif (True)"}; - var _preElseIfFalse = {keyword: "elif (false)"}; - var _prePragma = {keyword: "pragma"}; - var _preDefined = {keyword: "defined"}; - var _preBackslash = {keyword: "\\"} - var _preError = {keyword: "error"}; - var _preWarning = {keyword: "warning"}; - var _preprocessParamItem = {type: "preprocessParamItem"} - var _preprocessSkipLine = {type: "skipLine"} - var _preInclude = {keyword: "include"}; - - // Map keyword names to token types. - - var keywordTypes = {"break": _break, "case": _case, "catch": _catch, - "continue": _continue, "debugger": _debugger, "default": _default, - "do": _do, "else": _else, "finally": _finally, "for": _for, - "function": _function, "if": _if, "return": _return, "switch": _switch, - "throw": _throw, "try": _try, "var": _var, "while": _while, "with": _with, - "null": _null, "true": _true, "false": _false, "new": _new, "in": _in, - "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, - "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, - "void": _void, - "delete": {keyword: "delete", prefix: true, beforeExpr: true} }; - - // Map Objective-J keyword names to token types. - - var keywordTypesObjJ = {"IBAction": _action, "IBOutlet": _outlet, "unsigned": _unsigned, "signed": _signed, "byte": _byte, "char": _char, - "short": _short, "int": _int, "long": _long, "id": _id, "float": _float, "BOOL": _boolean, "SEL": _SEL, - "double": _double}; - - // Map Objective-J "@" keyword names to token types. - - var objJAtKeywordTypes = {"implementation": _implementation, "outlet": _outlet, "accessors": _accessors, "end": _end, - "import": _import, "action": _action, "selector": _selector, "class": _class, "global": _global, - "ref": _ref, "deref": _deref, "protocol": _protocol, "optional": _optional, "required": _required, - "interface": _interface, "typedef": _typedef}; - - // Map Preprocessor keyword names to token types. - - var keywordTypesPreprocessor = {"define": _preDefine, "pragma": _prePragma, "ifdef": _preIfdef, "ifndef": _preIfndef, - "undef": _preUndef, "if": _preIf, "endif": _preEndif, "else": _preElse, "elif": _preElseIf, - "defined": _preDefined, "warning": _preWarning, "error": _preError, "include": _preInclude}; - - // Punctuation token types. Again, the `type` property is purely for debugging. - - var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true}; - var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"}; - var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true}; - var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _question = {type: "?", beforeExpr: true}; - - // Objective-J token types - - var _dotdotdot = {type: "..."}; - - // Operators. These carry several kinds of properties to help the - // parser use them properly (the presence of these properties is - // what categorizes them as operators). - // - // `binop`, when present, specifies that this operator is a binary - // operator, and will refer to its precedence. - // - // `prefix` and `postfix` mark the operator as a prefix or postfix - // unary operator. `isUpdate` specifies that the node produced by - // the operator should be of type UpdateExpression rather than - // simply UnaryExpression (`++` and `--`). - // - // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as - // binary operators with a very low precedence, that should result - // in AssignmentExpression nodes. - - var _slash = {binop: 10, beforeExpr: true, preprocess: true}, _eq = {isAssign: true, beforeExpr: true, preprocess: true}; - var _assign = {isAssign: true, beforeExpr: true}, _plusmin = {binop: 9, prefix: true, beforeExpr: true, preprocess: true}; - var _incdec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true, preprocess: true}; - var _bin1 = {binop: 1, beforeExpr: true, preprocess: true}, _bin2 = {binop: 2, beforeExpr: true, preprocess: true}; - var _bin3 = {binop: 3, beforeExpr: true, preprocess: true}, _bin4 = {binop: 4, beforeExpr: true, preprocess: true}; - var _bin5 = {binop: 5, beforeExpr: true, preprocess: true}, _bin6 = {binop: 6, beforeExpr: true, preprocess: true}; - var _bin7 = {binop: 7, beforeExpr: true, preprocess: true}, _bin8 = {binop: 8, beforeExpr: true, preprocess: true}; - var _bin10 = {binop: 10, beforeExpr: true, preprocess: true}; - - // Provide access to the token types for external users of the - // tokenizer. - - exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR, - parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, - dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof, - num: _num, regexp: _regexp, string: _string}; - for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; - - // This is a trick taken from Esprima. It turns out that, on - // non-Chrome browsers, to check whether a string is in a set, a - // predicate containing a big ugly `switch` statement is faster than - // a regular expression, and on Chrome the two are about on par. - // This function uses `eval` (non-lexical) to produce such a - // predicate from a space-separated string of words. - // - // It starts by sorting the words by length. - - function makePredicate(words) { - words = words.split(" "); - var f = "", cats = []; - out: for (var i = 0; i < words.length; ++i) { - for (var j = 0; j < cats.length; ++j) - if (cats[j][0].length == words[i].length) { - cats[j].push(words[i]); - continue out; - } - cats.push([words[i]]); - } - function compareTo(arr) { - if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; - f += "switch(str){"; - for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; - f += "return true}return false;"; - } - - // When there are more than three length categories, an outer - // switch first dispatches on the lengths, to save on comparisons. - - if (cats.length > 3) { - cats.sort(function(a, b) {return b.length - a.length;}); - f += "switch(str.length){"; - for (var i = 0; i < cats.length; ++i) { - var cat = cats[i]; - f += "case " + cat[0].length + ":"; - compareTo(cat); - } - f += "}"; - - // Otherwise, simply generate a flat `switch` statement. - - } else { - compareTo(words); - } - return new Function("str", f); - } - - exports.makePredicate = makePredicate; - - // The ECMAScript 3 reserved word list. - - var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"); - - // ECMAScript 5 reserved words. - - var isReservedWord5 = makePredicate("class enum extends super const export import"); - - // The additional reserved words in strict mode. - - var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield"); - - // The forbidden variable names in strict mode. - - var isStrictBadIdWord = makePredicate("eval arguments"); - - // And the keywords. - - var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"); - - // The Objective-J keywords. - - var isKeywordObjJ = makePredicate("IBAction IBOutlet byte char short int long float unsigned signed id BOOL SEL double"); - - // The preprocessor keywords. - - var isKeywordPreprocessor = makePredicate("define undef pragma if ifdef ifndef else elif endif defined error warning include"); - - // ## Character categories - - // Big ugly regular expressions that match characters in the - // whitespace, identifier, and identifier-start categories. These - // are only applied when a character is found to actually have a - // code point above 128. - - var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/; - var nonASCIIwhitespaceNoNewLine = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; - var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; - var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; - var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); - var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); - - // Whether a single character denotes a newline. - - var newline = /[\n\r\u2028\u2029]/; - - // Matches a whole line break (where CRLF is considered a single - // line break). Used to count lines. - - var lineBreak = /\r\n|[\n\r\u2028\u2029]/g; - - // Test whether a given character code starts an identifier. - - var isIdentifierStart = exports.isIdentifierStart = function(code) { - if (code < 65) return code === 36; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123)return true; - return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); - }; - - // Test whether a given character is part of an identifier. - - var isIdentifierChar = exports.isIdentifierChar = function(code) { - if (code < 48) return code === 36; - if (code < 58) return true; - if (code < 65) return false; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123)return true; - return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); - }; - - // ## Tokenizer - - // These are used when `options.locations` is on, for the - // `tokStartLoc` and `tokEndLoc` properties. - - function line_loc_t() { - this.line = tokCurLine; - this.column = tokPos - tokLineStart; - if (preprocessStackLastItem) { - var macro = preprocessStackLastItem.macro; - var locationOffset = macro.locationOffset; - if (locationOffset) { - var macroCurrentLine = locationOffset.line; - if (macroCurrentLine) this.line += macroCurrentLine; - var macroCurrentLineStart = locationOffset.column; - // Only add column offset if we are on the first line - if (macroCurrentLineStart) this.column += tokPosMacroOffset - (tokCurLine === 1 ? macroCurrentLineStart : 0); - } - } - } - - function PositionOffset(line, column) { - this.line = line - 1; // Line start on one so we have to convert it to an offset - this.column = column; - if (preprocessStackLastItem) { - var macro = preprocessStackLastItem.macro; - var locationOffset = macro.locationOffset; - if (locationOffset) { - var macroCurrentLine = locationOffset.line; - if (macroCurrentLine) this.line += macroCurrentLine; - var macroCurrentLineStart = locationOffset.column; - if (macroCurrentLineStart) this.column += macroCurrentLineStart; - } - } - } - - // Reset the token state. Used at the start of a parse. - - function initTokenState() { - tokCurLine = 1; - tokPos = tokLineStart = lastTokMacroOffset = tokMacroOffset = tokPosMacroOffset = 0; - tokRegexpAllowed = true; - tokComments = null; - tokSpaces = null; - skipSpace(); - } - - // Reset the token state. Used at the start of a parse. - - function initPreprocessorState() { - macros = Object.create(null); - macrosIsPredicate = null; - preprocessParameterScope = null; - preTokParameterScope = null; - preprocessMacroParameterListMode = false; - preprocessIsParsingPreprocess = false; - preprocessStack = []; - preprocessStackLastItem = null; - preprocessOnlyTransformArgumentsForLastToken = null; - preprocessDontConcatenate = false; - preNotSkipping = true; - preConcatenating = false; - preIfLevel = []; - } - - // Called at the end of every token. Sets `tokEnd`, `tokVal`, - // `tokCommentsAfter`, `tokSpacesAfter`, and `tokRegexpAllowed`, and skips the space - // after the token, so that the next one's `tokStart` will point at - // the right position. - - function finishToken(type, val, overrideTokEnd) { - if (overrideTokEnd) { - firstTokEnd = tokEnd = overrideTokEnd; - if (options.locations) tokEndLoc = preprocessOverrideTokLoc; - } else { - firstTokEnd = tokEnd = tokPos; - if (options.locations) tokEndLoc = new line_loc_t; - } - tokType = type; - var ch = skipSpace(); - if (ch === 35 && options.preprocess && input.charCodeAt(tokPos + 1) === 35) { // '##' - var val1 = val != null ? val : type.keyword || type.type; - tokPos += 2; - if (val1 != null) { - // Save current line and current line start. This is needed when option.locations is true - var positionOffset = options.locations && new PositionOffset(tokCurLine, tokLineStart); - // Save positions on first token to get start and end correct on node if cancatenated token is invalid - var saveTokInput = tokInput, saveTokEnd = tokEnd, saveTokStart = tokStart, start = tokStart + tokMacroOffset, variadicName = preprocessStackLastItem && preprocessStackLastItem.macro && preprocessStackLastItem.macro.variadicName; - skipSpace(); - if (variadicName && variadicName === input.slice(tokPos, tokPos + variadicName.length)) var isVariadic = true; - preConcatenating = true; - readToken(null, 2); // Don't transform macros - preConcatenating = false; - var val2 = tokVal != null ? tokVal : tokType.keyword || tokType.type; - if (val2 != null) { - // Skip token if it is a ',' concatenated with an empty variadic parameter - if (isVariadic && val1 === "," && val2 === "") return readToken(); - var concat = "" + val1 + val2, val2TokStart = tokStart + tokPosMacroOffset; - // If the macro defines anything add it to the preprocess input stack - var concatMacro = new Macro(null, concat, null, start, false, null, false, positionOffset); - var r = readTokenFromMacro(concatMacro, tokPosMacroOffset, preprocessStackLastItem ? preprocessStackLastItem.parameterDict : null, null, tokPos, next, null); - // Consumed the whole macro in one bite? If not the tokenizer can't create a single token from the two concatenated tokens - if (preprocessStackLastItem && preprocessStackLastItem.macro === concatMacro) { - tokType = type; - tokStart = saveTokStart; - tokEnd = saveTokEnd; - tokInput = saveTokInput; - tokPosMacroOffset = val2TokStart - val1.length; // reset the macro offset to the second token to get start and end correct on node - if (!isVariadic) /*raise(tokStart,*/console.log("Warning: pasting formed '" + concat + "', an invalid preprocessing token"); - } else return r; - } - } - } - tokVal = val; - lastTokCommentsAfter = tokCommentsAfter; - lastTokSpacesAfter = tokSpacesAfter; - tokCommentsAfter = tokComments; - tokSpacesAfter = tokSpaces; - tokRegexpAllowed = type.beforeExpr; - } - - function skipBlockComment(lastIsNewlinePos, dontTrack) { - var startLoc = options.onComment && options.locations && new line_loc_t; - var start = tokPos, end = input.indexOf("*/", tokPos += 2); - if (end === -1) raise(tokPos - 2, "Unterminated comment"); - tokPos = end + 2; - if (options.locations) { - lineBreak.lastIndex = start; - var match; - while ((match = lineBreak.exec(input)) && match.index < tokPos) { - ++tokCurLine; - tokLineStart = match.index + match[0].length; - } - } - if (!dontTrack) { - if (options.onComment) - options.onComment(true, input.slice(start + 2, end), start, tokPos, - startLoc, options.locations && new line_loc_t); - if (options.trackComments) - (tokComments || (tokComments = [])).push(input.slice(lastIsNewlinePos != null && options.trackCommentsIncludeLineBreak ? lastIsNewlinePos : start, tokPos)); - } - } - - function skipLineComment(lastIsNewlinePos, dontTrack) { - var start = tokPos; - var startLoc = options.onComment && options.locations && new line_loc_t; - var ch = input.charCodeAt(tokPos+=2); - while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { - ++tokPos; - ch = input.charCodeAt(tokPos); - } - if (!dontTrack) { - if (options.onComment) - options.onComment(false, input.slice(start + 2, tokPos), start, tokPos, - startLoc, options.locations && new line_loc_t); - if (options.trackComments) - (tokComments || (tokComments = [])).push(input.slice(lastIsNewlinePos != null && options.trackCommentsIncludeLineBreak ? lastIsNewlinePos : start, tokPos)); - } - } - - function preprocesSkipRestOfLine() { - var ch = input.charCodeAt(tokPos); - var last; - // If the last none whitespace character is a '\' the line will continue on the the next line. - // Here we break the way gcc works as it joins the lines first and then tokenize it. Because of - // this we can't have a newline in the middle of a word. - while (tokPos < inputLen && ((ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) || last === 92)) { // White space and '\' - if (ch != 32 && ch != 9 && ch != 160 && (ch < 5760 || !nonASCIIwhitespaceNoNewLine.test(String.fromCharCode(ch)))) - last = ch; - ch = input.charCodeAt(++tokPos); - } - } - - // Called at the start of the parse and after every token. Skips - // whitespace and comments, and, if `options.trackComments` is on, - // will store all skipped comments in `tokComments`. If - // `options.trackSpaces` is on, will store the last skipped spaces in - // `tokSpaces`. - // Returns the char code of the first none whitespace or comment - - function skipSpace() { - tokComments = null; - tokSpaces = null; - return onlySkipSpace(); - } - - // Returns the char code of the first none whitespace or comment - - function onlySkipSpace(dontSkipEOL, dontSkipMacroBoundary, dontSkipComments) { - var spaceStart = tokPos, - lastIsNewlinePos, - ch; - for(;;) { - ch = input.charCodeAt(tokPos); - if (ch === 32) { // ' ' - ++tokPos; - } else if (ch === 13) { - if (dontSkipEOL) break; - lastIsNewlinePos = tokPos; - ++tokPos; - var next = input.charCodeAt(tokPos); - if (next === 10) { - ++tokPos; - } - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } else if (ch === 10) { - if (dontSkipEOL) break; - lastIsNewlinePos = tokPos; - ++tokPos; - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } else if (ch === 9) { - ++tokPos; - } else if (ch === 47) { // '/' - if (dontSkipComments) break; - var next = input.charCodeAt(tokPos+1); - if (next === 42) { // '*' - if (options.trackSpaces) - (tokSpaces || (tokSpaces = [])).push(input.slice(spaceStart, tokPos)); - skipBlockComment(lastIsNewlinePos); - spaceStart = tokPos; - } else if (next === 47) { // '/' - if (options.trackSpaces) - (tokSpaces || (tokSpaces = [])).push(input.slice(spaceStart, tokPos)); - skipLineComment(lastIsNewlinePos); - spaceStart = tokPos; - } else break; - } else if (ch === 160 || ch === 11 || ch === 12 || (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch)))) { // '\xa0', VT, FF, Unicode whitespaces - ++tokPos; - } else if (tokPos >= inputLen) { - if (options.preprocess) { - if (dontSkipMacroBoundary) return true; - if (!preprocessStack.length) break; - // If this is the first end of file after the token save to position to allow a semicolon to be inserted - // the end of file, if needed. - if (firstEndOfFile == null) firstEndOfFile = tokPos; - // If we are at the end of the input inside a macro continue at last position - var lastItem = preprocessStack.pop(); - tokPos = lastItem.end; - input = lastItem.input; - inputLen = lastItem.inputLen; - tokCurLine = lastItem.currentLine; - tokLineStart = lastItem.currentLineStart; - preprocessOnlyTransformArgumentsForLastToken = lastItem.onlyTransformArgumentsForLastToken; - preprocessParameterScope = lastItem.parameterScope; - tokPosMacroOffset = lastItem.macroOffset; - sourceFile = lastItem.sourceFile; - firstTokEnd = lastItem.lastEnd; - - // Set the last item - var lastIndex = preprocessStack.length; - preprocessStackLastItem = lastIndex ? preprocessStack[lastIndex - 1] : null; - return onlySkipSpace(dontSkipEOL); - } else { - break; - } - } else if (ch === 92) { // '\' - if (!options.preprocess) break; - // Check if we have an escaped newline. We are using a relaxed treatment of escaped newlines like gcc. - // We allow spaces, horizontal and vertical tabs, and form feeds between the backslash and the subsequent newline - var pos = tokPos + 1; - ch = input.charCodeAt(pos); - while (pos < inputLen && (ch === 32 || ch === 9 || ch === 11 || ch === 12 || (ch >= 5760 && nonASCIIwhitespaceNoNewLine.test(String.fromCharCode(ch))))) - ch = input.charCodeAt(++pos); - lineBreak.lastIndex = 0; - var match = lineBreak.exec(input.slice(pos, pos + 2)); - if (match && match.index === 0) { - tokPos = pos + match[0].length; - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } else { - break; - } - } else { - break; - } - } - return ch; - } - - // ### Token reading - - // This is the function that is called to fetch the next token. It - // is somewhat obscure, because it works in character codes rather - // than characters, and because operator parsing has been inlined - // into it. - // - // All in the name of speed. - // - // The `forceRegexp` parameter is used in the one case where the - // `tokRegexpAllowed` trick does not work. See `parseStatement`. - - function readToken_dot(code, finisher) { - var next = input.charCodeAt(tokPos+1); - if (next >= 48 && next <= 57) return readNumber(String.fromCharCode(code), finisher); - if (next === 46 && options.objj && input.charCodeAt(tokPos+2) === 46) { //'.' - tokPos += 3; - return finisher(_dotdotdot); - } - ++tokPos; - return finisher(_dot); - } - - function readToken_slash(finisher) { // '/' - var next = input.charCodeAt(tokPos+1); - if (tokRegexpAllowed) {++tokPos; return readRegexp();} - if (next === 61) return finishOp(_assign, 2, finisher); - return finishOp(_slash, 1, finisher); - } - - function readToken_mult_modulo(finisher) { // '%*' - var next = input.charCodeAt(tokPos+1); - if (next === 61) return finishOp(_assign, 2, finisher); - return finishOp(_bin10, 1, finisher); - } - - function readToken_pipe_amp(code, finisher) { // '|&' - var next = input.charCodeAt(tokPos+1); - if (next === code) return finishOp(code === 124 ? _bin1 : _bin2, 2, finisher); - if (next === 61) return finishOp(_assign, 2, finisher); - return finishOp(code === 124 ? _bin3 : _bin5, 1, finisher); - } - - function readToken_caret(finisher) { // '^' - var next = input.charCodeAt(tokPos+1); - if (next === 61) return finishOp(_assign, 2, finisher); - return finishOp(_bin4, 1, finisher); - } - - function readToken_plus_min(code, finisher) { // '+-' - var next = input.charCodeAt(tokPos+1); - if (next === code) return finishOp(_incdec, 2, finisher); - if (next === 61) return finishOp(_assign, 2, finisher); - return finishOp(_plusmin, 1, finisher); - } - - function readToken_lt_gt(code, finisher) { // '<>' - if (code === 60 && (tokType === _import || preTokType === _preInclude) && options.objj) { // '<' - for (var start = tokPos + 1;;) { - var ch = input.charCodeAt(++tokPos); - if (ch === 62) // '>' - return finisher(_filename, input.slice(start, tokPos++)); - if (tokPos >= inputLen || ch === 13 || ch === 10 || ch === 8232 || ch === 8233) - raise(tokStart, "Unterminated import statement"); - } - } - var next = input.charCodeAt(tokPos+1); - var size = 1; - if (next === code) { - size = code === 62 && input.charCodeAt(tokPos+2) === 62 ? 3 : 2; - if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1, finisher); - return finishOp(_bin8, size, finisher); - } - if (next === 61) - size = input.charCodeAt(tokPos+2) === 61 ? 3 : 2; - return finishOp(_bin7, size, finisher); - } - - function readToken_eq_excl(code, finisher) { // '=!' - var next = input.charCodeAt(tokPos+1); - if (next === 61) return finishOp(_bin6, input.charCodeAt(tokPos+2) === 61 ? 3 : 2, finisher); - return finishOp(code === 61 ? _eq : _prefix, 1, finisher); - } - - function readToken_at(code, finisher) { // '@' - var next = input.charCodeAt(++tokPos); - if (next === 34 || next === 39) // Read string if "'" or '"' - return readString(next, finisher); - if (next === 123) // Read dictionary literal if "{" - return finisher(_dictionaryLiteral); - if (next === 91) // Read array literal if "[" - return finisher(_arrayLiteral); - - var word = readWord1(), - token = objJAtKeywordTypes[word]; - if (!token) raise(tokStart, "Unrecognized Objective-J keyword '@" + word + "'"); - return finisher(token); - } - - function readToken_preprocess(finisher) { // '#' - ++tokPos; - preprocessSkipSpace(); - preprocessReadToken(false, true); // Dont track and it is a preprocessToken - switch (preTokType) { - case _preDefine: - if (preNotSkipping) { - preprocessParseDefine(); - } else { - return finisher(_preDefine); - } - break; - - case _preUndef: - preprocessReadToken(); - options.preprocessUndefineMacro(preprocessGetIdent()); - break; - - case _preIf: - if (preNotSkipping) { - // We dont't allow regex when parsing preprocess expression - var saveTokRegexpAllowed = tokRegexpAllowed; - tokRegexpAllowed = false; - preIfLevel.push(_preIf); - preprocessReadToken(false, false, true); - var expr = preprocessParseExpression(true); // Process macros - var test = preprocessEvalExpression(expr); - if (!test) { - preNotSkipping = false; - preprocessSkipToElseOrEndif(); - } - tokRegexpAllowed = saveTokRegexpAllowed; - } else { - return finisher(_preIf); - } - break; - - case _preIfdef: - if (preNotSkipping) { - preIfLevel.push(_preIf); - preprocessReadToken(); - var ident = preprocessGetIdent(); - var test = options.preprocessIsMacro(ident); - if (!test) { - preNotSkipping = false - preprocessSkipToElseOrEndif(); - } - } else { - return finisher(_preIfdef); - } - break; - - case _preIfndef: - if (preNotSkipping) { - preIfLevel.push(_preIf); - preprocessReadToken(); - var ident = preprocessGetIdent(); - var test = options.preprocessIsMacro(ident); - if (test) { - preNotSkipping = false - preprocessSkipToElseOrEndif(); - } - } else { - //preprocesSkipRestOfLine(); - return finisher(_preIfndef); - } - break; - - case _preElse: - if (preIfLevel.length) { - if (preNotSkipping) { - if(preIfLevel[preIfLevel.length - 1] === _preIf) { - preIfLevel[preIfLevel.length - 1] = _preElse; - preNotSkipping = false; - finisher(_preElse); - preprocessReadToken(); - preprocessSkipToElseOrEndif(true); // no else - } else - raise(preTokStart, "#else after #else"); - } else { - preIfLevel[preIfLevel.length - 1] = _preElse; - return finisher(_preElse); - } - } else - raise(preTokStart, "#else without #if"); - break; - - case _preElseIf: - if (preIfLevel.length) { - if (preNotSkipping) { - if(preIfLevel[preIfLevel.length - 1] === _preIf) { - preNotSkipping = false; - finisher(_preElseIf); - preprocessReadToken(); - preprocessSkipToElseOrEndif(true); // no else - } else - raise(preTokStart, "#elsif after #else"); - } else { - // We dont't allow regex when parsing preprocess expression - var saveTokRegexpAllowed = tokRegexpAllowed; - tokRegexpAllowed = false; - preNotSkipping = true; - preprocessReadToken(false, false, true); - var expr = preprocessParseExpression(true); - preNotSkipping = false; - tokRegexpAllowed = saveTokRegexpAllowed; - var test = preprocessEvalExpression(expr); - return finisher(test ? _preElseIfTrue : _preElseIfFalse); - } - } else - raise(preTokStart, "#elif without #if"); - break; - - case _preEndif: - if (preIfLevel.length) { - if (preNotSkipping) { - preIfLevel.pop(); - break; - } - } else { - raise(preTokStart, "#endif without #if"); - } - return finisher(_preEndif); - break; - - case _prePragma: - preprocesSkipRestOfLine(); - break; - - case _prefix: - preprocesSkipRestOfLine(); - break; - - case _preWarning: - preprocessReadToken(false, false, true); - var expr = preprocessParseExpression(); - console.log("Warning: " + String(preprocessEvalExpression(expr))); - break; - - case _preError: - var start = preTokStart; - preprocessReadToken(false, false, true); - var expr = preprocessParseExpression(); - raise(start, "Error: " + String(preprocessEvalExpression(expr))); - break; - - case _preInclude: - if (!preNotSkipping) { - return finisher(_preInclude); - } - preprocessReadToken(); - if (preTokType === _string) - var localfilepath = true; - else if (preTokType ===_filename) - var localfilepath = false; - else - raise(preTokStart, "Expected \"FILENAME\" or : " + (preTokType.keyword || preTokType.type)); - - var theFileName = preTokVal; - var includeDict = options.preprocessGetIncludeFile(preTokVal, localfilepath) || raise(preTokStart, "'" + theFileName + "' file not found"); - var includeString = includeDict.include; - var includeMacro = new Macro(null, includeString, null, 0, false, null, false, null, includeDict.sourceFile); - preprocessFinishToken(_preprocess, null, null, true); // skipEOL - pushMacroToStack(includeMacro, includeMacro.macro, tokPosMacroOffset, null, null, tokPos, null, true); // isIncludeFile - skipSpace(); - readToken(null, null, true); // Stealth - return; - - break; - - default: - if (preprocessStackLastItem) { - // If the current macro has parameters check if this word is one of them and should be stringifyed - if (preprocessStackLastItem.parameterDict && preprocessStackLastItem.macro.isParameterFunction()(preTokVal)) { - var macro = preprocessStackLastItem.parameterDict[preTokVal]; - if (macro) { - return finishToken(_string, macro.macro); - } - } - } - raise(preTokStart, "Invalid preprocessing directive"); - preprocesSkipRestOfLine(); - // Return the complete line as a token to make it possible to create a PreProcessStatement if we are between two statements - return finisher(_preprocess); - //raise(tokPos, "Invalid preprocessing directive '" + (preTokType.keyword || preTokVal) + "' " + input.slice(tokStart, tokPos)); - } - // Drop the regular token as this was a preprocess token and then read next token - //tokPos = preTokStart; - if (preTokType === _eol && options.trackSpaces) { - if (tokSpaces && tokSpaces.length) - tokSpaces.push("\n" + tokSpaces.pop()); - else - tokSpaces = ["\n"]; - } - preprocessFinishToken(preTokType, null, null, true); // skipEOL - return next(true) // Stealth - } - - function preprocessParseDefine() { - preprocessIsParsingPreprocess = true; - preprocessReadToken(); - var macroIdentifierEnd = preTokEnd; - - // We don't want to concatenate tokens when creating macros - preprocessDontConcatenate = true; - - // Get position offset now as ´tokCurLine´ and ´tokLineStart´ points to next token. - var positionOffset = options.locations && new PositionOffset(tokCurLine, tokLineStart); - var macroIdentifier = preprocessGetIdent(); - // '(' Must follow directly after identifier to be a valid macro with parameters - if (input.charCodeAt(macroIdentifierEnd) === 40) { // '(' - preprocessExpect(_parenL); - var parameters = []; - var variadic = false; - var first = true; - while (!preprocessEat(_parenR)) { - if (variadic) raise(preTokStart, "Variadic parameter must be last"); - if (!first) preprocessExpect(_comma, "Expected ',' between macro parameters"); else first = false; - parameters.push(preprocessEat(_dotdotdot) ? variadic = true && "__VA_ARGS__" : preprocessGetIdent()); - if (preprocessEat(_dotdotdot)) variadic = true; - // Get a new position offset as macro has parameters. This is needed if line has escaped (backslash) newline - positionOffset = options.locations && new PositionOffset(tokCurLine, tokLineStart); - } - } - var start = preTokStart; - - while(preTokType !== _eol && preTokType !== _eof) - preprocessReadToken(); - - preprocessDontConcatenate = false; - var macroString = preTokInput.slice(start, preTokStart); - macroString = macroString.replace(/\\/g, " "); - // If variadic get the last parameter for the variadic parameter name - options.preprocessAddMacro(new Macro(macroIdentifier, macroString, parameters, start, false, null, variadic && parameters[parameters.length - 1], positionOffset)); - preprocessIsParsingPreprocess = false; - } - - function preprocessEvalExpression(expr) { - return walk.recursive(expr, {}, { - LogicalExpression: function(node, st, c) { - var left = node.left, right = node.right; - switch (node.operator) { - case "||": - return c(left, st) || c(right, st); - case "&&": - return c(left, st) && c(right, st); - } - }, - BinaryExpression: function(node, st, c) { - var left = node.left, right = node.right; - switch(node.operator) { - case "+": - return c(left, st) + c(right, st); - case "-": - return c(left, st) - c(right, st); - case "*": - return c(left, st) * c(right, st); - case "/": - return c(left, st) / c(right, st); - case "%": - return c(left, st) % c(right, st); - case "<": - return c(left, st) < c(right, st); - case ">": - return c(left, st) > c(right, st); - case "^": - return c(left, st) ^ c(right, st); - case "&": - return c(left, st) & c(right, st); - case "|": - return c(left, st) | c(right, st); - case "==": - return c(left, st) == c(right, st); - case "===": - return c(left, st) === c(right, st); - case "!=": - return c(left, st) != c(right, st); - case "!==": - return c(left, st) !== c(right, st); - case "<=": - return c(left, st) <= c(right, st); - case ">=": - return c(left, st) >= c(right, st); - case ">>": - return c(left, st) >> c(right, st); - case ">>>": - return c(left, st) >>> c(right, st); - case "<<": - return c(left, st) << c(right, st); - } - }, - UnaryExpression: function(node, st, c) { - var arg = node.argument; - switch (node.operator) { - case "-": - return -c(arg, st); - case "+": - return +c(arg, st); - case "!": - return !c(arg, st); - case "~": - return ~c(arg, st); - } - }, - Literal: function(node, st, c) { - return node.value; - }, - Identifier: function(node, st, c) { - // If it is not macro expanded it should be counted as a zero - return 0; - }, - DefinedExpression: function(node, st, c) { - var objectNode = node.object; - if (objectNode.type === "Identifier") { - // If the macro has parameters it will not expand and we have to check here if it exists - var name = objectNode.name, - macro = options.preprocessGetMacro(name) || preprocessBuiltinMacro(name); - return macro || 0; - } else { - return c(objectNode, st); - } - } - }, {}); - } - - function getTokenFromCode(code, finisher, allowEndOfLineToken) { - switch(code) { - // The interpretation of a dot depends on whether it is followed - // by a digit. - case 46: // '.' - return readToken_dot(code, finisher); - - // Punctuation tokens. - case 40: ++tokPos; return finisher(_parenL); - case 41: ++tokPos; return finisher(_parenR); - case 59: ++tokPos; return finisher(_semi); - case 44: ++tokPos; return finisher(_comma); - case 91: ++tokPos; return finisher(_bracketL); - case 93: ++tokPos; return finisher(_bracketR); - case 123: ++tokPos; return finisher(_braceL); - case 125: ++tokPos; return finisher(_braceR); - case 58: ++tokPos; return finisher(_colon); - case 63: ++tokPos; return finisher(_question); - - // '0x' is a hexadecimal number. - case 48: // '0' - var next = input.charCodeAt(tokPos+1); - if (next === 120 || next === 88) return readHexNumber(finisher); - // Anything else beginning with a digit is an integer, octal - // number, or float. - case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 - return readNumber(false, finisher); - - // Quotes produce strings. - case 34: case 39: // '"', "'" - return readString(code, finisher); - - // Operators are parsed inline in tiny state machines. '=' (61) is - // often referred to. `finishOp` simply skips the amount of - // characters it is given as second argument, and returns a token - // of the type given by its first argument. - - case 47: // '/' - return readToken_slash(finisher); - - case 37: case 42: // '%*' - return readToken_mult_modulo(finisher); - - case 124: case 38: // '|&' - return readToken_pipe_amp(code, finisher); - - case 94: // '^' - return readToken_caret(finisher); - - case 43: case 45: // '+-' - return readToken_plus_min(code, finisher); - - case 60: case 62: // '<>' - return readToken_lt_gt(code, finisher); - - case 61: case 33: // '=!' - return readToken_eq_excl(code, finisher); - - case 126: // '~' - return finishOp(_prefix, 1, finisher); - - case 64: // '@' - if (options.objj) - return readToken_at(code, finisher); - return false; - - case 35: // '#' - if (options.preprocess) { - if (preprocessIsParsingPreprocess) { - ++tokPos; - return finisher(_preprocess); - } - // Check if it is the first token on the line - lineBreak.lastIndex = 0; - var match = lineBreak.exec(input.slice(localLastEnd, tokPos)); - if (lastEnd !== 0 && lastEnd !== tokPos && !match && ((preprocessStackLastItem && !preprocessStackLastItem.isIncludeFile) || tokPos !== 0)) { - if (preprocessStackLastItem) { - // Stringify next token - return preprocessStringify(); - } else { - raise(tokPos, "Preprocessor directives may only be used at the beginning of a line"); - } - } - - return readToken_preprocess(finisher); - } - return false; - - case 92: // '\' - if (options.preprocess) { - return finishOp(_preBackslash, 1, finisher); - } - return false; - } - - if (allowEndOfLineToken) { - if (code === 13 || code === 10 || code === 8232 || code === 8233) { - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - return finishOp(_eol, (code === 13 && input.charCodeAt(tokPos+1) === 10) ? 2 : 1, finisher); - } - } - - return false; - } - - // Stringify next token and return with it as a literal string. - - function preprocessStringify() { - var saveStackLength = preprocessStack.length, saveLastItem = preprocessStackLastItem; - tokPos++; // Skip '#' - preConcatenating = true; // To get empty sting if macro is empty - next(false, 2); // Don't prescan arguments - preConcatenating = false; - var start = tokStart + tokMacroOffset; - var positionOffset = options.locations && new PositionOffset(tokCurLine, tokLineStart); - var string; - if (tokType === _string) { - var quote = tokInput.slice(tokStart, tokStart + 1); - var escapedQuote = quote === '"' ? '\\"' : "'"; - string = escapedQuote; - string += preprocessStringifyEscape(tokVal); - string += escapedQuote; - } else { - string = tokVal != null ? tokVal : tokType.keyword || tokType.type; - } - while (preprocessStack.length > saveStackLength && saveLastItem === preprocessStack[saveStackLength - 1]) { - preConcatenating = true; // To get empty sting if macro is empty - next(false, 2); // Don't prescan arguments - preConcatenating = false; - // Add a space if there is one or more withespaces - if (lastEnd !== tokStart) string += " "; - if (tokType === _string) { - var quote = tokInput.slice(tokStart, tokStart + 1); - var escapedQuote = quote === '"' ? '\\"' : "'"; - string += escapedQuote; - string += preprocessStringifyEscape(tokVal); - string += escapedQuote; - } else { - string += tokVal != null ? tokVal : tokType.keyword || tokType.type; - } - } - var stringifyMacro = new Macro(null, '"' + string + '"', null, start, false, null, false, positionOffset); - return readTokenFromMacro(stringifyMacro, tokPosMacroOffset, null, null, tokPos, next); - } - - // Escape characters in stringify string. - - function preprocessStringifyEscape(aString) { - for (var escaped = "", pos = 0, size = aString.length, ch = aString.charCodeAt(pos); pos < size; ch = aString.charCodeAt(++pos)) { - switch (ch) { - case 34: escaped += '\\\\\\"'; break; // " - case 10: escaped += "\\\\n"; break; // LF (\n) - case 13: escaped += "\\\\r"; break; // CR (\r) - case 9: escaped += "\\\\t"; break; // TAB (\t) - case 8: escaped += "\\\\b"; break; // BS (\b) - case 11: escaped += "\\\\v"; break; // VT (\v) - case 0x00A0: escaped += "\\\\u00A0"; break; // CR (\r) - case 0x2028: escaped += "\\\\u2028"; break; // LINE SEPARATOR - case 0x2029: escaped += "\\\\u2029"; break; // PARAGRAPH SEPARATOR - case 92: escaped += "\\\\"; break; // BACKSLASH - default: escaped += aString.charAt(pos); break; - } - } - return escaped; - } - - // Skip whitespaces sometimes without line breaks - // Returns true if it stops at a line break. - - function preprocessSkipSpace(dontSkipComments, skipEOL) { - var ch = onlySkipSpace(!skipEOL, false, dontSkipComments); - // Can't see that this line break test is used anymore - //lineBreak.lastIndex = 0; - //var match = lineBreak.exec(input.slice(tokPos, tokPos + 2)); - //return (match && match.index === 0); - return ch; - } - - function preprocessSkipToElseOrEndif(skipElse) { - var ifLevel = []; - while (ifLevel.length > 0 || (preTokType !== _preEndif && ((preTokType !== _preElse && preTokType !== _preElseIfTrue) || skipElse))) { - switch (preTokType) { - case _preIf: - case _preIfdef: - case _preIfndef: - ifLevel.push(_preIf); - break; - - case _preElse: - if (ifLevel[ifLevel.length - 1] !== _preIf) - raise(preTokStart, "#else after #else"); - else - ifLevel[ifLevel.length - 1] = _preElse; - break; - - case _preElseIf: - if (ifLevel[ifLevel.length - 1] !== _preIf) - raise(preTokStart, "#elif after #else"); - break; - - case _preEndif: - ifLevel.pop(); - break; - - case _eof: - preNotSkipping = true; - raise(preTokStart, "Missing #endif"); - } - preprocessReadToken(true); - } - preNotSkipping = true; - if (preTokType === _preEndif) - preIfLevel.pop(); - } - -// preprocessToken is used to cancel preNotSkipping when calling from readToken_preprocess. -// FIXME: Refactor to not use this parameter preprocessToken. It is kind of confusing and it should be possible to do in another way - function preprocessReadToken(skipComments, preprocessToken, processMacros, onlyTransformMacroArguments) { - preTokStart = tokPos; - preTokInput = input; - preTokParameterScope = preprocessParameterScope; - if (tokPos >= inputLen) return preprocessFinishToken(_eof); - var code = input.charCodeAt(tokPos); - if (!preprocessToken && !preNotSkipping && code !== 35) { // '#' - // If we are skipping take the whole line if the token does not start with '#' (preprocess tokens) - preprocesSkipRestOfLine(); - preprocessFinishToken(_preprocessSkipLine, input.slice(preTokStart, tokPos)); - preprocessSkipSpace(true, true); // Don't skip comments and skip EOL - return; - } else if (preprocessMacroParameterListMode && code !== 41 && code !== 44) { // ')', ',' - var parenLevel = 0; - // If we are parsing a macro parameter list parentheses within each argument must balance - while(tokPos < inputLen && (parenLevel || (code !== 41 && code !== 44))) { // ')', ',' - if (code === 40) // '(' - parenLevel++; - if (code === 41) // ')' - parenLevel--; - if (code === 34 || code === 39) {// '"' "'" We have a quote so go all the way to the end of the quote - var quote = code; - code = input.charCodeAt(++tokPos); - while(tokPos < inputLen && code !== quote) { - if (code === 92) { // '\' - code = input.charCodeAt(++tokPos); - if (code !== quote) continue; - } - code = input.charCodeAt(++tokPos); - } - } - code = input.charCodeAt(++tokPos); - } - return preprocessFinishToken(_preprocessParamItem, input.slice(preTokStart, tokPos)); - } - if (isIdentifierStart(code) || (code === 92 /* '\' */ && input.charCodeAt(tokPos +1) === 117 /* 'u' */)) return preprocessReadWord(processMacros); - if (getTokenFromCode(code, skipComments ? preprocessFinishTokenSkipComments : preprocessFinishToken, true) === false) { // Allow _eol token - // If we are here, we either found a non-ASCII identifier - // character, or something that's entirely disallowed. - var ch = String.fromCharCode(code); - if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return preprocessReadWord(processMacros); - raise(tokPos, "Unexpected character '" + ch + "'"); - } - } - - function preprocessReadWord(processMacros, onlyTransformMacroArguments) { - var word = readWord1(); - var type = _name; - if (processMacros && options.preprocess) { - var readMacroWordReturn = readMacroWord(word, preprocessNext, onlyTransformMacroArguments); - if (readMacroWordReturn === true) - return true; - } - - if (!containsEsc && isKeywordPreprocessor(word)) type = keywordTypesPreprocessor[word]; - preprocessFinishToken(type, word, readMacroWordReturn, false, processMacros); // If readMacroWord returns anything except 'true' it is the real tokEndPos - } - - function preprocessFinishToken(type, val, overrideTokEnd, skipEOL, processMacros) { - preTokType = type; - preTokVal = val; - preTokEnd = overrideTokEnd || tokPos; - if (type !== _eol) firstTokEnd = preTokEnd; - //tokRegexpAllowed = type.beforeExpr; - var ch = preprocessSkipSpace(false, skipEOL); // Skip comments - if (ch === 35 && options.preprocess && !preprocessDontConcatenate && input.charCodeAt(tokPos + 1) === 35) { // '##' - var val1 = val != null ? val : type.keyword || type.type; - tokPos += 2; - if (val1 != null) { - // Save current line and current line start. This is needed when option.locations is true - var positionOffset = options.locations && new PositionOffset(tokCurLine, tokLineStart); - // Save positions on first token to get start and end correct on node if cancatenated token is invalid - var saveTokInput = tokInput, saveTokEnd = preTokEnd, saveTokStart = preTokStart, start = preTokStart + tokMacroOffset, variadicName = preprocessStackLastItem && preprocessStackLastItem.macro && preprocessStackLastItem.macro.variadicName; - skipSpace(); - if (variadicName && variadicName === input.slice(tokPos, tokPos + variadicName.length)) var isVariadic = true; - preConcatenating = true; - preprocessReadToken(null, null, processMacros, 2); // 2 = Don't transform macros only arguments - preConcatenating = false; - var val2 = preTokVal != null ? preTokVal : preTokType.keyword || preTokType.type; - if (val2 != null) { - // Skip token if it is a ',' concatenated with an empty variadic parameter - if (isVariadic && val1 === "," && val2 === "") return preprocessReadToken(); - var concat = "" + val1 + val2, val2TokStart = preTokStart + tokPosMacroOffset; - // If the macro defines anything add it to the preprocess input stack - var concatMacro = new Macro(null, concat, null, start, false, null, false, positionOffset); - var r = readTokenFromMacro(concatMacro, tokPosMacroOffset, preprocessStackLastItem ? preprocessStackLastItem.parameterDict : null, null, tokPos, preprocessNext, null); - // Consumed the whole macro in one bite? If not the tokenizer can't create a single token from the two concatenated tokens - if (preprocessStackLastItem && preprocessStackLastItem.macro === concatMacro) { - // FIXME: Should change this to 'preTokType' and friends - preTokType = type; - preTokStart = saveTokStart; - preTokEnd = saveTokEnd; - tokInput = saveTokInput; - tokPosMacroOffset = val2TokStart - val1.length; // reset the macro offset to the second token to get start and end correct on node - if (!isVariadic) /*raise(tokStart,*/console.log("Warning: pasting formed '" + concat + "', an invalid preprocessing token"); - } else return r; - } - } - } - } - -// FIXME: Find out if this is really used? - function preprocessFinishTokenSkipComments(type, val) { - preTokType = type; - preTokVal = val; - firstTokEnd = preTokEnd = tokPos; - preprocessSkipSpace(true); // 'true' for don't skip comments - } - - // Continue to the next token. - - function preprocessNext(stealth, onlyTransformArguments, forceRegexp, processMacros) { - if (!stealth) { - preLastStart = preTokStart; - preLastEnd = preTokEnd; - } - localLastEnd = firstTokEnd; - return preprocessReadToken(false, false, processMacros, onlyTransformArguments); - } - - // Predicate that tests whether the next token is of the given - // type, and if yes, consumes it as a side effect. - - function preprocessEat(type, processMacros) { - if (preTokType === type) { - preprocessNext(false, false, null, processMacros); - return true; - } - } - - // Expect a token of a given type. If found, consume it, otherwise, - // raise with errorMessage or an unexpected token error. - - function preprocessExpect(type, errorMessage, processMacros) { - if (preTokType === type) preprocessNext(false, undefined, null, processMacros); - else raise(preTokStart, errorMessage || "Unexpected token"); - } - - function debug() { - // debugger; - } - function preprocessGetIdent(processMacros) { - var ident = preTokType === _name ? preTokVal : ((!options.forbidReserved || preTokType.okAsIdent) && preTokType.keyword) || debug(); //raise(preTokStart, "Expected Macro identifier"); - //tokRegexpAllowed = false; - preprocessNext(false, false, null, processMacros); - return ident; - } - - function preprocessParseIdent(processMacros) { - var node = startNode(); - node.name = preprocessGetIdent(processMacros); - return preprocessFinishNode(node, "Identifier"); - } - - // Parse an expression — either a single token that is an - // expression, an expression started by a keyword like `defined`, - // or an expression wrapped in punctuation like `()`. - // When `processMacros` is true any macros will we transformed to its definition - - function preprocessParseExpression(processMacros) { - return preprocessParseExprOps(processMacros); - } - - // Start the precedence parser. - - function preprocessParseExprOps(processMacros) { - return preprocessParseExprOp(preprocessParseMaybeUnary(processMacros), -1, processMacros); - } - - // Parse binary operators with the operator precedence parsing - // algorithm. `left` is the left-hand side of the operator. - // `minPrec` provides context that allows the function to stop and - // defer further parser to one of its callers when it encounters an - // operator that has a lower precedence than the set it is parsing. - - function preprocessParseExprOp(left, minPrec, processMacros) { - var prec = preTokType.binop; - if (prec) { - if (!preTokType.preprocess) raise(preTokStart, "Unsupported macro operator"); - if (prec > minPrec) { - var node = startNodeFrom(left); - node.left = left; - node.operator = preTokVal; - preprocessNext(false, false, null, processMacros); - node.right = preprocessParseExprOp(preprocessParseMaybeUnary(processMacros), prec, processMacros); - var node = preprocessFinishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression"); - return preprocessParseExprOp(node, minPrec, processMacros); - } - } - return left; - } - - // Parse an unary expression if possible - - function preprocessParseMaybeUnary(processMacros) { - if (preTokType.preprocess && preTokType.prefix) { - var node = startNode(); - node.operator = preTokVal; - node.prefix = true; - preprocessNext(false, false, null, processMacros); - node.argument = preprocessParseMaybeUnary(processMacros); - return preprocessFinishNode(node, "UnaryExpression"); - } - return preprocessParseExprAtom(processMacros); - } - - // Parse an atomic macro expression — either a single token that is an - // expression, an expression started by a keyword like `defined`, - // or an expression wrapped in punctuation like `()`. - - function preprocessParseExprAtom(processMacros) { - switch (preTokType) { - case _name: - return preprocessParseIdent(processMacros); - - case _num: case _string: - return preprocessParseStringNumLiteral(processMacros); - - case _parenL: - var tokStart1 = preTokStart; - preprocessNext(false, false, null, processMacros); - var val = preprocessParseExpression(processMacros); - val.start = tokStart1; - val.end = preTokEnd; - preprocessExpect(_parenR, "Expected closing ')' in macro expression", processMacros); - return val; - - case _preDefined: - var node = startNode(); - preprocessNext(false, false, null, processMacros); - node.object = preprocessParseDefinedExpression(processMacros); - return preprocessFinishNode(node, "DefinedExpression"); - - default: - unexpected(); - } - } - - // Parse an 'Defined' macro expression — either a single token that is an - // identifier, number, string or an expression wrapped in punctuation like `()`. - - function preprocessParseDefinedExpression(processMacros) { - switch (preTokType) { - case _name: - return preprocessParseIdent(processMacros); - - case _num: case _string: - return preprocessParseStringNumLiteral(processMacros); - - case _parenL: - var tokStart1 = preTokStart; - preprocessNext(false, false, null, processMacros); - var val = preprocessParseDefinedExpression(processMacros); - val.start = tokStart1; - val.end = preTokEnd; - preprocessExpect(_parenR, "Expected closing ')' in macro expression", processMacros); - return val; - - default: - unexpected(); - } - } - - function preprocessParseStringNumLiteral(processMacros) { - var node = startNode(); - node.value = preTokVal; - node.raw = preTokInput.slice(preTokStart, preTokEnd); - preprocessNext(false, false, null, processMacros); - return preprocessFinishNode(node, "Literal"); - } - - function preprocessFinishNode(node, type) { - node.type = type; - node.end = preLastEnd; - return node; - } - - function readToken(forceRegexp, onlyTransformMacroArguments, stealth) { - tokCommentsBefore = tokComments; - tokSpacesBefore = tokSpaces; - if (!forceRegexp) tokStart = tokPos; - else tokPos = tokStart + 1; - if (!stealth) { - tokFirstStart = tokStart; - //tokFirstInput = input; - } - tokInput = input; - tokMacroOffset = tokPosMacroOffset; - preTokParameterScope = preprocessParameterScope; - if (options.locations) tokStartLoc = new line_loc_t; - if (forceRegexp) return readRegexp(); - if (tokPos >= inputLen) return finishToken(_eof); - - var code = input.charCodeAt(tokPos); - // Identifier or keyword. '\uXXXX' sequences are allowed in - // identifiers, so '\' also dispatches to that. - if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord(null, onlyTransformMacroArguments, forceRegexp); - - var tok = getTokenFromCode(code, finishToken); - - if (tok === false) { - // If we are here, we either found a non-ASCII identifier - // character, or something that's entirely disallowed. - var ch = String.fromCharCode(code); - if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord(null, onlyTransformMacroArguments, forceRegexp); - raise(tokPos, "Unexpected character '" + ch + "'"); - } - return tok; - } - - function finishOp(type, size, finisher) { - var str = input.slice(tokPos, tokPos + size); - tokPos += size; - finisher(type, str); - } - - // Parse a regular expression. Some context-awareness is necessary, - // since a '/' inside a '[]' set does not end the expression. - - function readRegexp() { - var content = "", escaped, inClass, start = tokPos; - for (;;) { - if (tokPos >= inputLen) raise(start, "Unterminated regular expression"); - var ch = input.charAt(tokPos); - if (newline.test(ch)) raise(start, "Unterminated regular expression"); - if (!escaped) { - if (ch === "[") inClass = true; - else if (ch === "]" && inClass) inClass = false; - else if (ch === "/" && !inClass) break; - escaped = ch === "\\"; - } else escaped = false; - ++tokPos; - } - var content = input.slice(start, tokPos); - ++tokPos; - // Need to use `readWord1` because '\uXXXX' sequences are allowed - // here (don't ask). - var mods = readWord1(); - if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regexp flag"); - return finishToken(_regexp, new RegExp(content, mods)); - } - - // Read an integer in the given radix. Return null if zero digits - // were read, the integer value otherwise. When `len` is given, this - // will return `null` unless the integer has exactly `len` digits. - - function readInt(radix, len) { - var start = tokPos, total = 0; - for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { - var code = input.charCodeAt(tokPos), val; - if (code >= 97) val = code - 97 + 10; // a - else if (code >= 65) val = code - 65 + 10; // A - else if (code >= 48 && code <= 57) val = code - 48; // 0-9 - else val = Infinity; - if (val >= radix) break; - ++tokPos; - total = total * radix + val; - } - if (tokPos === start || len != null && tokPos - start !== len) return null; - - return total; - } - - function readHexNumber(finisher) { - tokPos += 2; // 0x - var val = readInt(16); - if (val == null) raise(tokStart + 2, "Expected hexadecimal number"); - if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number"); - return finisher(_num, val); - } - - // Read an integer, octal integer, or floating-point number. - - function readNumber(startsWithDot, finisher) { - var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48; - if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number"); - if (input.charCodeAt(tokPos) === 46) { - ++tokPos; - readInt(10); - isFloat = true; - } - var next = input.charCodeAt(tokPos); - if (next === 69 || next === 101) { // 'eE' - next = input.charCodeAt(++tokPos); - if (next === 43 || next === 45) ++tokPos; // '+-' - if (readInt(10) === null) raise(start, "Invalid number"); - isFloat = true; - } - if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number"); - - var str = input.slice(start, tokPos), val; - if (isFloat) val = parseFloat(str); - else if (!octal || str.length === 1) val = parseInt(str, 10); - else if (/[89]/.test(str) || strict) raise(start, "Invalid number"); - else val = parseInt(str, 8); - return finisher(_num, val); - } - - // Read a string value, interpreting backslash-escapes. - - function readString(quote, finisher) { - tokPos++; - var out = ""; - for (;;) { - if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant"); - var ch = input.charCodeAt(tokPos); - if (ch === quote) { - ++tokPos; - return finisher(_string, out); - } - if (ch === 92) { // '\' - ch = input.charCodeAt(++tokPos); - var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3)); - if (octal) octal = octal[0]; - while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, octal.length - 1); - if (octal === "0") octal = null; - ++tokPos; - if (octal) { - if (strict) raise(tokPos - 2, "Octal literal in strict mode"); - out += String.fromCharCode(parseInt(octal, 8)); - tokPos += octal.length - 1; - } else { - switch (ch) { - case 110: out += "\n"; break; // 'n' -> '\n' - case 114: out += "\r"; break; // 'r' -> '\r' - case 120: out += String.fromCharCode(readHexChar(2)); break; // 'x' - case 117: out += String.fromCharCode(readHexChar(4)); break; // 'u' - case 85: out += String.fromCharCode(readHexChar(8)); break; // 'U' - case 116: out += "\t"; break; // 't' -> '\t' - case 98: out += "\b"; break; // 'b' -> '\b' - case 118: out += "\u000b"; break; // 'v' -> '\u000b' - case 102: out += "\f"; break; // 'f' -> '\f' - case 48: out += "\0"; break; // 0 -> '\0' - case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n' - case 10: // ' \n' - if (options.locations) { tokLineStart = tokPos; ++tokCurLine; } - break; - default: out += String.fromCharCode(ch); break; - } - } - } else { - if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, "Unterminated string constant"); - out += String.fromCharCode(ch); // '\' - ++tokPos; - } - } - } - - // Used to read character escape sequences ('\x', '\u', '\U'). - - function readHexChar(len) { - var n = readInt(16, len); - if (n === null) raise(tokStart, "Bad character escape sequence"); - return n; - } - - // Used to signal to callers of `readWord1` whether the word - // contained any escape sequences. This is needed because words with - // escape sequences must not be interpreted as keywords. - - var containsEsc; - - // Read an identifier, and return it as a string. Sets `containsEsc` - // to whether the word contained a '\u' escape. - // - // Only builds up the word character-by-character when it actually - // containeds an escape, as a micro-optimization. - - function readWord1() { - containsEsc = false; - var word, first = true, start = tokPos; - for (;;) { - var ch = input.charCodeAt(tokPos); - if (isIdentifierChar(ch)) { - if (containsEsc) word += input.charAt(tokPos); - ++tokPos; - } else if (ch === 92) { // "\" - if (!containsEsc) word = input.slice(start, tokPos); - containsEsc = true; - if (input.charCodeAt(++tokPos) != 117) // "u" - raise(tokPos, "Expecting Unicode escape sequence \\uXXXX"); - ++tokPos; - var esc = readHexChar(4); - var escStr = String.fromCharCode(esc); - if (!escStr) raise(tokPos - 1, "Invalid Unicode escape"); - if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc))) - raise(tokPos - 4, "Invalid Unicode escape"); - word += escStr; - } else { - break; - } - first = false; - } - return containsEsc ? word : input.slice(start, tokPos); - } - - // Read an identifier or keyword token. Will check for reserved - // words when necessary. Argument preReadWord is used to concatenate - // The word is then passed in from caller. - - function readWord(preReadWord, onlyTransformMacroArguments, forceRegexp) { - var word = preReadWord || readWord1(); - var type = _name; - if (options.preprocess) { - var readMacroWordReturn = readMacroWord(word, next, onlyTransformMacroArguments, forceRegexp); - if (readMacroWordReturn === true) - return true; - } - - if (!containsEsc) { - if (isKeyword(word)) type = keywordTypes[word]; - else if (options.objj && isKeywordObjJ(word)) type = keywordTypesObjJ[word]; - else if (options.forbidReserved && - (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(word) || - strict && isStrictReservedWord(word)) - raise(tokStart, "The keyword '" + word + "' is reserved"); - } - return finishToken(type, word, readMacroWordReturn); // If readMacroWord returns anything except 'true' it is the real tokEndPos - } - - // If the word is a macro return true as the token is already finished. If not just return 'undefined'. - - function readMacroWord(word, nextFinisher, onlyTransformArguments, forceRegexp) { - var macro, - lastStackItem = preprocessStackLastItem, - oldParameterScope = preprocessParameterScope; - if (lastStackItem) { - var scope = preTokParameterScope || preprocessStackLastItem; - // If the current macro has parameters check if this word is one of them and should be translated - if (scope.parameterDict && scope.macro.isParameterFunction()(word)) { - macro = scope.parameterDict[word]; - // If it is a variadic macro and we can't find anything in the variadic parameter just get next token - if (!macro && scope.macro.variadicName === word) { - // Don't do this if we are stringifying or concatenating as we then want an empty string - if (preConcatenating) { - finishToken(_name, ""); - return true; - } else { - onlySkipSpace(); - nextFinisher(true, onlyTransformArguments, forceRegexp, true); // Stealth and Preprocess macros. - } - return true; - } - // Lets look ahead to find out if we find a '##' for token concatenate - // We don't want to prescan spaces across macro boundary as the macro stack will fall apart - // So we do a special prescan if we have to cross a boundary all in the name of speed - if (onlySkipSpace(true, true) === true) { // don't skip EOL and don't skip macro boundary. - if (preprocessPrescanFor(35, 35)) // Prescan across boundary for '##' as we crossed a boundary - onlyTransformArguments = 2; - } else if (input.charCodeAt(tokPos) === 35 && input.charCodeAt(tokPos + 1) === 35) { // '##' - onlyTransformArguments = 2; - } - preprocessParameterScope = macro && macro.parameterScope; - onlyTransformArguments--; - } - } - // Does the word match against any of the known macro names - // Don't match if: - // 1. We already has found a argument macro - // 2. We are doing concatenating. Here it is only valid for the last token. - if (!macro && (!onlyTransformArguments && !preprocessOnlyTransformArgumentsForLastToken || tokPos < inputLen) && options.preprocessIsMacro(word)) { - preprocessParameterScope = null; - macro = options.preprocessGetMacro(word); - if (macro) { - // Check if this macro is already referenced by looking in the stack - // Don't do it if the input in the stack is an argument. We want to simulate 'expand arguments first' - if (!preprocessStackLastItem || !preprocessStackLastItem.macro.isArgument) { - var i = preprocessStack.length, - lastMacroItem; - while (i > 0) { - var item = preprocessStack[--i], - macroItem = item.macro; - if (macroItem.identifier === word && !(lastMacroItem && lastMacroItem.isArgument)) { - macro = null; - } - lastMacroItem = macroItem; - } - } - } else { - macro = preprocessBuiltinMacro(word); - } - } - if (macro) { - var parameters; - var hasParameters = macro.parameters; - var nextIsParenL; - if (hasParameters) { - // Ok, we should have parameters for the macro. Lets look ahead to find out if we find a '(' - // First save current position and loc for tokEndPos - var pos = tokPos; - var loc; - if (options.locations) loc = new line_loc_t; - if ((onlySkipSpace(true, true) === true && preprocessPrescanFor(40)) || input.charCodeAt(tokPos) === 40) { // '(' - nextIsParenL = true; - } else { - // We didn't find a '(' so don't transform to the macro. Return the real tokEndPos so we get correct token end values. - preprocessOverrideTokEndLoc = loc; - return pos; - } - } - if (!hasParameters || nextIsParenL) { - // Now we know that we have a matching macro. Get parameters if needed - if (nextIsParenL) { - var variadicName = macro.variadicName; - var first = true; - var noParams = 0; - parameters = Object.create(null); - onlySkipSpace(true); - //preprocessReadToken(); - //preprocessMacroParameterListMode = true; - //preprocessExpect(_parenL); - //lastTokPos = tokPos; - if (input.charCodeAt(tokPos++) !== 40) raise(tokPos - 1, "Expected '(' before macro prarameters"); - onlySkipSpace(true, true, true); - var code = input.charCodeAt(tokPos++); - while (tokPos < inputLen && code !== 41) { - if (first) - first = false; - else - if (code === 44) { // ',' - onlySkipSpace(true, true, true); - code = input.charCodeAt(tokPos++); - } else - raise(tokPos - 1, "Expected ',' between macro parameters"); - var ident = hasParameters[noParams++]; - var variadicAndLastParameter = variadicName && hasParameters.length === noParams; - var paramStart = tokPos - 1, parenLevel = 0; - // Calculate current line and current line start. - var positionOffset = options.locations && new PositionOffset(tokCurLine, tokLineStart); - // When parsing a macro parameter list parentheses within each argument must balance - // If it is variadic and we are on the last paramter collect all the rest of the parameters - while(tokPos < inputLen && (parenLevel || (code !== 41 && (code !== 44 || variadicAndLastParameter)))) { // ')', ',' - if (code === 40) // '(' - parenLevel++; - if (code === 41) // ')' - parenLevel--; - if (code === 34 || code === 39) {// '"' "'" We have a quote so go all the way to the end of the quote - var quote = code; - code = input.charCodeAt(tokPos++); - while(tokPos < inputLen && code !== quote) { - if (code === 92) { // '\' - code = input.charCodeAt(tokPos++); - if (code !== quote) continue; - } - code = input.charCodeAt(tokPos++); - } - } - code = input.charCodeAt(tokPos++); - } - var val = input.slice(paramStart, tokPos - 1); - //var val = preTokType === _preprocessParamItem ? preTokVal : ""; - parameters[ident] = new Macro(ident, val, null, paramStart + tokMacroOffset, true, preTokParameterScope || preprocessStackLastItem, false, positionOffset); // true = 'Is argument', false = 'Not varadic' - } - if (code !== 41) raise(tokPos, "Expected ')' after macro prarameters"); - onlySkipSpace(true, true); // Don't skip EOL and don't skip macro boundary - //preprocessMacroParameterListMode = false; - //preprocessExpect(_parenR); - } - // If the macro defines anything add it to the preprocess input stack - return readTokenFromMacro(macro, tokPosMacroOffset, parameters, oldParameterScope, tokPos, nextFinisher, onlyTransformArguments, forceRegexp); - } - } - } - - // Here we pre scan for first and second character. - // The first thing should be to skip spaces and comments - // Return true if the first characters after spaces are first and second - // This is very simular to the function onlySkipSpace. Maybe the same - // function can be used with some refactoring? - function preprocessPrescanFor(first, second) { - var i = preprocessStack.length; - stackloop: - while (i-- > 0) { - var stackItem = preprocessStack[i], - scanPos = stackItem.end, - scanInput = stackItem.input, - scanInputLen = stackItem.inputLen; - - for(;;) { - var ch = scanInput.charCodeAt(scanPos); - if (ch === 32) { // ' ' - ++scanPos; - } else if (ch === 13) { - ++scanPos; - var next = scanInput.charCodeAt(scanPos); - if (next === 10) { - ++scanPos; - } - } else if (ch === 10) { - ++scanPos; - } else if (ch === 9) { - ++scanPos; - } else if (ch === 47) { // '/' - var next = scanInput.charCodeAt(scanPos+1); - if (next === 42) { // '*' - var end = scanInput.indexOf("*/", scanPos += 2); - if (end === -1) raise(scanPos - 2, "Unterminated comment"); - scanPos = end + 2; - } else if (next === 47) { // '/' - ch = scanInput.charCodeAt(scanPos += 2); - while (scanPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { - ++scanPos; - ch = scanInput.charCodeAt(scanPos); - } - } else break stackloop; - } else if (ch === 160 || ch === 11 || ch === 12 || (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch)))) { // '\xa0', VT, FF, Unicode whitespaces - ++scanPos; - } else if (scanPos >= scanInputLen) { - continue stackloop; - } else if (ch === 92) { // '\' - // Check if we have an escaped newline. We are using a relaxed treatment of escaped newlines like gcc. - // We allow spaces, horizontal and vertical tabs, and form feeds between the backslash and the subsequent newline - var pos = scanPos + 1; - ch = scanInput.charCodeAt(pos); - while (pos < scanInputLen && (ch === 32 || ch === 9 || ch === 11 || ch === 12 || (ch >= 5760 && nonASCIIwhitespaceNoNewLine.test(String.fromCharCode(ch))))) - ch = scanInput.charCodeAt(++pos); - lineBreak.lastIndex = 0; - var match = lineBreak.exec(scanInput.slice(pos, pos + 2)); - if (match && match.index === 0) { - scanPos = pos + match[0].length; - } else { - break stackloop; - } - } else { - break stackloop; - } - } - } - return scanInput && scanInput.charCodeAt(scanPos) === first && (second == null || scanInput.charCodeAt(scanPos + 1) === second); - } - - // Push macro to stack and start read from it. - // Just read next token if the macro is empty - function readTokenFromMacro(macro, macroOffset, parameters, parameterScope, end, nextFinisher, onlyTransformArguments, forceRegexp) { - var macroString = macro.macro; - // If we are evaluation a macro expresion an empty macro definition means true or '1' - if(!macroString && nextFinisher === preprocessNext) macroString = "1"; - if (macroString) { - pushMacroToStack(macro, macroString, macroOffset, parameters, parameterScope, end, onlyTransformArguments); - } else if (preConcatenating) { - // If we are concatenating or stringifying and the macro is empty just make an empty string. - (nextFinisher === next ? finishToken : preprocessFinishToken)(_name, ""); - return true; - } - // Now read the next token - onlySkipSpace(); - nextFinisher(true, onlyTransformArguments, forceRegexp, true); // Stealth and Preprocess macros - return true; - } - - // Push macro to stack and reset tokPos etc. - // macroString is the string from the macro. It is usually 'macro.macro' but the caller can modify it if needed - // includeFile is true if the macro should be treated as a regular file. In other words don't stringify words after '#' - function pushMacroToStack(macro, macroString, macroOffset, parameters, parameterScope, end, onlyTransformArguments, isIncludeFile) { - preprocessStackLastItem = {macro: macro, macroOffset: macroOffset, parameterDict: parameters, /*start: macroStart,*/ end:end, lastEnd: localLastEnd, inputLen: inputLen, tokStart: tokStart, onlyTransformArgumentsForLastToken: preprocessOnlyTransformArgumentsForLastToken, currentLine: tokCurLine, currentLineStart: tokLineStart, sourceFile: sourceFile}; - if (parameterScope) preprocessStackLastItem.parameterScope = parameterScope; - if (isIncludeFile) preprocessStackLastItem.isIncludeFile = isIncludeFile; - preprocessStackLastItem.input = input; - preprocessStack.push(preprocessStackLastItem); - preprocessOnlyTransformArgumentsForLastToken = onlyTransformArguments; - input = macroString; - inputLen = macroString.length; - tokPosMacroOffset = macro.start; - tokPos = 0; - tokCurLine = 1; - tokLineStart = 0; - firstTokEnd = 0; - localLastEnd = 0; - if (macro.sourceFile) sourceFile = macro.sourceFile; - } - - // ident is the identifier name for the macro - // macro is the macro string - // parameters is an array with the parameters for the macro - // start is the offset to where the macro is defined - // isArgument is true if the macro is a parameter - // parameterScope is the parameter scope - // varadicName is the name of the varadic parameter if it is a varadic macro - // locationOffset is the current line that the macro starts at and the position on the line - var Macro = exports.Macro = function Macro(ident, macro, parameters, start, isArgument, parameterScope, variadicName, locationOffset, aSourceFile) { - this.identifier = ident; - if (macro != null) this.macro = macro; - if (parameters) this.parameters = parameters; - if (start != null) this.start = start; - if (isArgument) this.isArgument = true; - if (parameterScope) this.parameterScope = parameterScope; - if (variadicName) this.variadicName = variadicName; - if (locationOffset) this.locationOffset = locationOffset; - if (aSourceFile) this.sourceFile = aSourceFile; - } - - Macro.prototype.isParameterFunction = function() { - return this.isParameterFunctionVar || (this.isParameterFunctionVar = makePredicate((this.parameters || []).join(" "))); - } - - // ## Parser - - // A recursive descent parser operates by defining functions for all - // syntactic elements, and recursively calling those, each function - // advancing the input stream and returning an AST node. Precedence - // of constructs (for example, the fact that `!x[1]` means `!(x[1])` - // instead of `(!x)[1]` is handled by the fact that the parser - // function that parses unary prefix operators is called first, and - // in turn calls the function that parses `[]` subscripts — that - // way, it'll receive the node for `x[1]` already parsed, and wraps - // *that* in the unary operator node. - // - // Acorn uses an [operator precedence parser][opp] to handle binary - // operator precedence, because it is much more compact than using - // the technique outlined above, which uses different, nesting - // functions to specify precedence, for all of the ten binary - // precedence levels that JavaScript defines. - // - // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser - - // ### Parser utilities - - // Continue to the next token. - // Stealth is to preserve lastEnd etc to get correct end positions on nodes when the - // preprocessor needs to drop one token and read next - - function next(stealth, onlyTransformArguments, forceRegexp) { - if (!stealth) { - lastStart = tokStart; - lastEnd = tokEnd; - lastEndInput = tokInput; - lastEndOfFile = firstEndOfFile; - lastEndLoc = tokEndLoc; - lastTokMacroOffset = tokMacroOffset; - } - localLastEnd = firstTokEnd; - firstEndOfFile = nodeMessageSendObjectExpression = null; - return readToken(forceRegexp, onlyTransformArguments, stealth); - } - - // Enter strict mode. Re-reads the next token to please pedantic - // tests ("use strict"; 010; -- should fail). - - function setStrict(strct) { - strict = strct; - tokPos = lastEnd; - while (tokPos < tokLineStart) { - tokLineStart = input.lastIndexOf("\n", tokLineStart - 2) + 1; - --tokCurLine; - } - skipSpace(); - readToken(); - } - - // Start an AST node, attaching a start offset and optionally a - // `commentsBefore` property to it. - - function node_t() { - this.type = null; - this.start = tokStart + tokMacroOffset; - this.end = null; - } - - function node_loc_t() { - this.start = tokStartLoc; - this.end = null; - if (sourceFile != null) this.source = sourceFile; - } - - function startNode() { - var node = new node_t(); - if (options.trackComments && tokCommentsBefore) { - node.commentsBefore = tokCommentsBefore; - tokCommentsBefore = null; - } - if (options.trackSpaces && tokSpacesBefore) { - node.spacesBefore = tokSpacesBefore; - tokSpacesBefore = null; - } - if (options.locations) - node.loc = new node_loc_t(); - if (options.ranges) - node.range = [tokStart, 0]; - return node; - } - - // Start a node whose start offset/comments information should be - // based on the start of another node. For example, a binary - // operator node is only started after its left-hand side has - // already been parsed. - - function startNodeFrom(other) { - var node = new node_t(); - node.start = other.start; - if (other.commentsBefore) { - node.commentsBefore = other.commentsBefore; - delete other.commentsBefore; - } - if (other.spacesBefore) { - node.spacesBefore = other.spacesBefore; - delete other.spacesBefore; - } - if (options.locations) { - node.loc = new node_loc_t(); - node.loc.start = other.loc.start; - } - if (options.ranges) - node.range = [other.range[0], 0]; - - return node; - } - - // Finish an AST node, adding `type`, `end`, and `commentsAfter` - // properties. - // - // We keep track of the last node that we finished, in order - // 'bubble' `commentsAfter` properties up to the biggest node. I.e. - // in '`1 + 1 // foo', the comment should be attached to the binary - // operator node, not the second literal node. The same is done on - // `spacesAfter` - - var lastFinishedNode; - - function finishNode(node, type) { - var nodeEnd = lastEnd + lastTokMacroOffset; - node.type = type; - node.end = nodeEnd; - if (options.trackComments) { - if (lastTokCommentsAfter) { - node.commentsAfter = lastTokCommentsAfter; - lastTokCommentsAfter = null; - } else if (lastFinishedNode && lastFinishedNode.end === lastEnd && - lastFinishedNode.commentsAfter) { - node.commentsAfter = lastFinishedNode.commentsAfter; - delete lastFinishedNode.commentsAfter; - } - if (!options.trackSpaces) - lastFinishedNode = node; - } - if (options.trackSpaces) { - if (lastTokSpacesAfter) { - node.spacesAfter = lastTokSpacesAfter; - lastTokSpacesAfter = null; - } else if (lastFinishedNode && lastFinishedNode.end === lastEnd && - lastFinishedNode.spacesAfter) { - node.spacesAfter = lastFinishedNode.spacesAfter; - delete lastFinishedNode.spacesAfter; - } - lastFinishedNode = node; - } - if (options.locations) - node.loc.end = lastEndLoc; - if (options.ranges) - node.range[1] = nodeEnd; - return node; - } - - // Test whether a statement node is the string literal `"use strict"`. - - function isUseStrict(stmt) { - return options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && - stmt.expression.type === "Literal" && stmt.expression.value === "use strict"; - } - - // Predicate that tests whether the next token is of the given - // type, and if yes, consumes it as a side effect. - - function eat(type) { - if (tokType === type) { - next(); - return true; - } - } - - // Test whether a semicolon can be inserted at the current position. - - function canInsertSemicolon() { - return !options.strictSemicolons && - (tokType === _eof || tokType === _braceR || newline.test(lastEndInput.slice(lastEnd, lastEndOfFile || tokFirstStart)) || - (nodeMessageSendObjectExpression && options.objj) || lastEndOfFile != null); - } - - // Consume a semicolon, or, failing that, see if we are allowed to - // pretend that there is a semicolon at this position. - - function semicolon() { - if (!eat(_semi) && !canInsertSemicolon()) raise(tokStart, "Expected a semicolon"); - } - - // Expect a token of a given type. If found, consume it, otherwise, - // raise with errorMessage or an unexpected token error. - - function expect(type, errorMessage) { - if (tokType === type) next(); - else errorMessage ? raise(tokStart, errorMessage) : unexpected(); - } - - // Raise an unexpected token error. - - function unexpected() { - raise(tokStart, "Unexpected token"); - } - - // Verify that a node is an lval — something that can be assigned - // to. - - function checkLVal(expr) { - if (expr.type !== "Identifier" && expr.type !== "MemberExpression" && expr.type !== "Dereference") - raise(expr.start, "Assigning to rvalue"); - if (strict && expr.type === "Identifier" && isStrictBadIdWord(expr.name)) - raise(expr.start, "Assigning to " + expr.name + " in strict mode"); - } - - // ### Statement parsing - - // Parse a program. Initializes the parser, reads any number of - // statements, and wraps them in a Program node. Optionally takes a - // `program` argument. If present, the statements will be appended - // to its body instead of creating a new node. - // If there are any pre include files they will be pushed onto the macro stack - - function parseTopLevel(program) { - lastStart = localLastEnd = lastEnd = 0; - - if (options.preprocess) { - var preIncludeFiles = options.preIncludeFiles; - if (preIncludeFiles && preIncludeFiles.length) for (var i = preIncludeFiles.length - 1; i >= 0; i--) { - var preIncludeFile = preIncludeFiles[i]; - - var preIncludeMacro = new Macro(null, preIncludeFile.include, null, 0, false, null, false, null, preIncludeFile.sourceFile); - pushMacroToStack(preIncludeMacro, preIncludeMacro.macro, 0, null, null, tokPos, null, true); // isIncludeFile - skipSpace(); - } - } - - if (options.locations) lastEndLoc = new line_loc_t; - inFunction = strict = null; - labels = []; - readToken(); - - var node = program || startNode(), first = true; - if (!program) node.body = []; - while (tokType !== _eof) { - var stmt = parseStatement(); - node.body.push(stmt); - if (first && isUseStrict(stmt)) setStrict(true); - first = false; - } - return finishNode(node, "Program"); - } - - var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; - - // Parse a single statement. - // - // If expecting a statement and finding a slash operator, parse a - // regular expression literal. This is to handle cases like - // `if (foo) /blah/.exec(foo);`, where looking at the previous token - // does not help. - - function parseStatement() { - if (tokType === _slash || tokType === _assign && tokVal == "/=") - readToken(true); - - var starttype = tokType, node = startNode(); - - // This is a special case when trying figure out if this is a subscript to the former line or a new send message statement on this line... - if (nodeMessageSendObjectExpression) { - node.expression = parseMessageSendExpression(nodeMessageSendObjectExpression, nodeMessageSendObjectExpression.object); - semicolon(); - return finishNode(node, "ExpressionStatement"); - } - - // Most types of statements are recognized by the keyword they - // start with. Many are trivial to parse, some require a bit of - // complexity. - - switch (starttype) { - case _break: case _continue: - next(); - var isBreak = starttype === _break; - if (eat(_semi) || canInsertSemicolon()) node.label = null; - else if (tokType !== _name) unexpected(); - else { - node.label = parseIdent(); - semicolon(); - } - - // Verify that there is an actual destination to break or - // continue to. - for (var i = 0; i < labels.length; ++i) { - var lab = labels[i]; - if (node.label == null || lab.name === node.label.name) { - if (lab.kind != null && (isBreak || lab.kind === "loop")) break; - if (node.label && isBreak) break; - } - } - if (i === labels.length) raise(node.start, "Unsyntactic " + starttype.keyword); - return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); - - case _debugger: - next(); - semicolon(); - return finishNode(node, "DebuggerStatement"); - - case _do: - next(); - labels.push(loopLabel); - node.body = parseStatement(); - labels.pop(); - expect(_while, "Expected 'while' at end of do statement"); - node.test = parseParenExpression(); - semicolon(); - return finishNode(node, "DoWhileStatement"); - - // Disambiguating between a `for` and a `for`/`in` loop is - // non-trivial. Basically, we have to parse the init `var` - // statement or expression, disallowing the `in` operator (see - // the second parameter to `parseExpression`), and then check - // whether the next token is `in`. When there is no init part - // (semicolon immediately after the opening parenthesis), it is - // a regular `for` loop. - - case _for: - next(); - labels.push(loopLabel); - expect(_parenL, "Expected '(' after 'for'"); - if (tokType === _semi) return parseFor(node, null); - if (tokType === _var) { - var init = startNode(); - next(); - parseVar(init, true); - if (init.declarations.length === 1 && eat(_in)) - return parseForIn(node, init); - return parseFor(node, init); - } - var init = parseExpression(false, true); - if (eat(_in)) {checkLVal(init); return parseForIn(node, init);} - return parseFor(node, init); - - case _function: - next(); - return parseFunction(node, true); - - case _if: - next(); - node.test = parseParenExpression(); - node.consequent = parseStatement(); - node.alternate = eat(_else) ? parseStatement() : null; - return finishNode(node, "IfStatement"); - - case _return: - if (!inFunction) raise(tokStart, "'return' outside of function"); - next(); - - // In `return` (and `break`/`continue`), the keywords with - // optional arguments, we eagerly look for a semicolon or the - // possibility to insert one. - - if (eat(_semi) || canInsertSemicolon()) node.argument = null; - else { node.argument = parseExpression(); semicolon(); } - return finishNode(node, "ReturnStatement"); - - case _switch: - next(); - node.discriminant = parseParenExpression(); - node.cases = []; - expect(_braceL, "Expected '{' in switch statement"); - labels.push(switchLabel); - - // Statements under must be grouped (by label) in SwitchCase - // nodes. `cur` is used to keep the node that we are currently - // adding statements to. - - for (var cur, sawDefault; tokType != _braceR;) { - if (tokType === _case || tokType === _default) { - var isCase = tokType === _case; - if (cur) finishNode(cur, "SwitchCase"); - node.cases.push(cur = startNode()); - cur.consequent = []; - next(); - if (isCase) cur.test = parseExpression(); - else { - if (sawDefault) raise(lastStart, "Multiple default clauses"); sawDefault = true; - cur.test = null; - } - expect(_colon, "Expected ':' after case clause"); - } else { - if (!cur) unexpected(); - cur.consequent.push(parseStatement()); - } - } - if (cur) finishNode(cur, "SwitchCase"); - next(); // Closing brace - labels.pop(); - return finishNode(node, "SwitchStatement"); - - case _throw: - next(); - if (newline.test(tokInput.slice(lastEnd, tokStart))) - raise(lastEnd, "Illegal newline after throw"); - node.argument = parseExpression(); - semicolon(); - return finishNode(node, "ThrowStatement"); - - case _try: - next(); - node.block = parseBlock(); - node.handler = null; - if (tokType === _catch) { - var clause = startNode(); - next(); - expect(_parenL, "Expected '(' after 'catch'"); - clause.param = parseIdent(); - if (strict && isStrictBadIdWord(clause.param.name)) - raise(clause.param.start, "Binding " + clause.param.name + " in strict mode"); - expect(_parenR, "Expected closing ')' after catch"); - clause.guard = null; - clause.body = parseBlock(); - node.handler = finishNode(clause, "CatchClause"); - } - node.guardedHandlers = empty; - node.finalizer = eat(_finally) ? parseBlock() : null; - if (!node.handler && !node.finalizer) - raise(node.start, "Missing catch or finally clause"); - return finishNode(node, "TryStatement"); - - case _var: - next(); - node = parseVar(node); - semicolon(); - return node; - - case _while: - next(); - node.test = parseParenExpression(); - labels.push(loopLabel); - node.body = parseStatement(); - labels.pop(); - return finishNode(node, "WhileStatement"); - - case _with: - if (strict) raise(tokStart, "'with' in strict mode"); - next(); - node.object = parseParenExpression(); - node.body = parseStatement(); - return finishNode(node, "WithStatement"); - - case _braceL: - return parseBlock(); - - case _semi: - next(); - return finishNode(node, "EmptyStatement"); - - // Objective-J - case _interface: - if (options.objj) { - next(); - node.classname = parseIdent(true); - if (eat(_colon)) - node.superclassname = parseIdent(true); - else if (eat(_parenL)) { - node.categoryname = parseIdent(true); - expect(_parenR, "Expected closing ')' after category name"); - } - if (tokVal === '<') { - next(); - var protocols = [], - first = true; - node.protocols = protocols; - while (tokVal !== '>') { - if (!first) - expect(_comma, "Expected ',' between protocol names"); - else first = false; - protocols.push(parseIdent(true)); - } - next(); - } - if (eat(_braceL)) { - node.ivardeclarations = []; - for (;;) { - if (eat(_braceR)) break; - parseIvarDeclaration(node); - } - node.endOfIvars = tokStart; - } - node.body = []; - while(!eat(_end)) { - if (tokType === _eof) raise(tokPos, "Expected '@end' after '@interface'"); - node.body.push(parseClassElement()); - } - return finishNode(node, "InterfaceDeclarationStatement"); - } - break; - - // Objective-J - case _implementation: - if (options.objj) { - next(); - node.classname = parseIdent(true); - if (eat(_colon)) - node.superclassname = parseIdent(true); - else if (eat(_parenL)) { - node.categoryname = parseIdent(true); - expect(_parenR, "Expected closing ')' after category name"); - } - if (tokVal === '<') { - next(); - var protocols = [], - first = true; - node.protocols = protocols; - while (tokVal !== '>') { - if (!first) - expect(_comma, "Expected ',' between protocol names"); - else first = false; - protocols.push(parseIdent(true)); - } - next(); - } - if (eat(_braceL)) { - node.ivardeclarations = []; - for (;;) { - if (eat(_braceR)) break; - parseIvarDeclaration(node); - } - node.endOfIvars = tokStart; - } - node.body = []; - while(!eat(_end)) { - if (tokType === _eof) raise(tokPos, "Expected '@end' after '@implementation'"); - node.body.push(parseClassElement()); - } - return finishNode(node, "ClassDeclarationStatement"); - } - break; - - // Objective-J - case _protocol: - // If next token is a left parenthesis it is a ProtocolLiteral expression so bail out - if (options.objj && input.charCodeAt(tokPos) !== 40) { // '(' - next(); - node.protocolname = parseIdent(true); - if (tokVal === '<') { - next(); - var protocols = [], - first = true; - node.protocols = protocols; - while (tokVal !== '>') { - if (!first) - expect(_comma, "Expected ',' between protocol names"); - else first = false; - protocols.push(parseIdent(true)); - } - next(); - } - while(!eat(_end)) { - if (tokType === _eof) raise(tokPos, "Expected '@end' after '@protocol'"); - if (eat(_required)) continue; - if (eat(_optional)) { - while(!eat(_required) && tokType !== _end) { - (node.optional || (node.optional = [])).push(parseProtocolClassElement()); - } - } else { - (node.required || (node.required = [])).push(parseProtocolClassElement()); - } - } - return finishNode(node, "ProtocolDeclarationStatement"); - } - break; - - // Objective-J - case _import: - if (options.objj) { - next(); - if (tokType === _string) - node.localfilepath = true; - else if (tokType ===_filename) - node.localfilepath = false; - else - unexpected(); - - node.filename = parseStringNumRegExpLiteral(); - return finishNode(node, "ImportStatement"); - } - break; - - // Objective-J - case _preprocess: - if (options.objj) { - next(); - return finishNode(node, "PreprocessStatement"); - } - break; - - // Objective-J - case _class: - if (options.objj) { - next(); - node.id = parseIdent(false); - return finishNode(node, "ClassStatement"); - } - break; - - // Objective-J - case _global: - if (options.objj) { - next(); - node.id = parseIdent(false); - return finishNode(node, "GlobalStatement"); - } - break; - - // This is a Objective-J statement - case _typedef: - if (options.objj) { - next(); - node.typedefname = parseIdent(true); - return finishNode(node, "TypeDefStatement"); - } - break; - } - - // The indentation is one step to the right here to make sure it - // is the same as in the original acorn parser. Easier merge - - // If the statement does not start with a statement keyword or a - // brace, it's an ExpressionStatement or LabeledStatement. We - // simply start parsing an expression, and afterwards, if the - // next token is a colon and the expression was a simple - // Identifier node, we switch to interpreting it as a label. - - var maybeName = tokVal, expr = parseExpression(); - if (starttype === _name && expr.type === "Identifier" && eat(_colon)) { - for (var i = 0; i < labels.length; ++i) - if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared"); - var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null; - labels.push({name: maybeName, kind: kind}); - node.body = parseStatement(); - labels.pop(); - node.label = expr; - return finishNode(node, "LabeledStatement"); - } else { - node.expression = expr; - semicolon(); - return finishNode(node, "ExpressionStatement"); - } - } - - function parseIvarDeclaration(node) { - var outlet; - if (eat(_outlet)) - outlet = true; - var type = parseObjectiveJType(); - if (strict && isStrictBadIdWord(type.name)) - raise(type.start, "Binding " + type.name + " in strict mode"); - for (;;) { - var decl = startNode(); - if (outlet) - decl.outlet = outlet; - decl.ivartype = type; - decl.id = parseIdent(); - if (strict && isStrictBadIdWord(decl.id.name)) - raise(decl.id.start, "Binding " + decl.id.name + " in strict mode"); - if (eat(_accessors)) { - decl.accessors = {}; - if (eat(_parenL)) { - if (!eat(_parenR)) { - for (;;) { - var config = parseIdent(true); - switch(config.name) { - case "property": - case "getter": - expect(_eq, "Expected '=' after 'getter' accessor attribute"); - decl.accessors[config.name] = parseIdent(true); - break; - - case "setter": - expect(_eq, "Expected '=' after 'setter' accessor attribute"); - var setter = parseIdent(true); - decl.accessors[config.name] = setter; - if (eat(_colon)) - setter.end = tokStart; - setter.name += ":" - break; - - case "readwrite": - case "readonly": - case "copy": - decl.accessors[config.name] = true; - break; - - default: - raise(config.start, "Unknown accessors attribute '" + config.name + "'"); - } - if (!eat(_comma)) break; - } - expect(_parenR, "Expected closing ')' after accessor attributes"); - } - } - } - finishNode(decl, "IvarDeclaration") - node.ivardeclarations.push(decl); - if (!eat(_comma)) break; - } - semicolon(); - } - - function parseMethodDeclaration(node) { - node.methodtype = tokVal; - expect(_plusmin, "Method declaration must start with '+' or '-'"); - // If we find a '(' we have a return type to parse - if (eat(_parenL)) { - var typeNode = startNode(); - if (eat(_action)) { - node.action = finishNode(typeNode, "ObjectiveJActionType"); - typeNode = startNode(); - } - if (!eat(_parenR)) { - node.returntype = parseObjectiveJType(typeNode); - expect(_parenR, "Expected closing ')' after method return type"); - } - } - // Now we parse the selector - var first = true, - selectors = [], - args = []; - node.selectors = selectors; - node.arguments = args; - for (;;) { - if (tokType !== _colon) { - selectors.push(parseIdent(true)); - if (first && tokType !== _colon) break; - } else - selectors.push(null); - expect(_colon, "Expected ':' in selector"); - var argument = {}; - args.push(argument); - if (eat(_parenL)) { - argument.type = parseObjectiveJType(); - expect(_parenR, "Expected closing ')' after method argument type"); - } - argument.identifier = parseIdent(false); - if (tokType === _braceL || tokType === _semi) break; - if (eat(_comma)) { - expect(_dotdotdot, "Expected '...' after ',' in method declaration"); - node.parameters = true; - break; - } - first = false; - } - } - - function parseClassElement() { - var element = startNode(); - if (tokVal === '+' || tokVal === '-') { - parseMethodDeclaration(element); - eat(_semi); - element.startOfBody = lastEnd; - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). - var oldInFunc = inFunction, oldLabels = labels; - inFunction = true; labels = []; - element.body = parseBlock(true); - inFunction = oldInFunc; labels = oldLabels; - return finishNode(element, "MethodDeclarationStatement"); - } else - return parseStatement(); - } - - function parseProtocolClassElement() { - var element = startNode(); - parseMethodDeclaration(element); - - semicolon(); - return finishNode(element, "MethodDeclarationStatement"); - } - - // Used for constructs like `switch` and `if` that insist on - // parentheses around their expression. - - function parseParenExpression() { - expect(_parenL, "Expected '(' before expression"); - var val = parseExpression(); - expect(_parenR, "Expected closing ')' after expression"); - return val; - } - - // Parse a semicolon-enclosed block of statements, handling `"use - // strict"` declarations when `allowStrict` is true (used for - // function bodies). - - function parseBlock(allowStrict) { - var node = startNode(), first = true, strict = false, oldStrict; - node.body = []; - expect(_braceL, "Expected '{' before block"); - while (!eat(_braceR)) { - var stmt = parseStatement(); - node.body.push(stmt); - if (first && allowStrict && isUseStrict(stmt)) { - oldStrict = strict; - setStrict(strict = true); - } - first = false; - } - if (strict && !oldStrict) setStrict(false); - return finishNode(node, "BlockStatement"); - } - - // Parse a regular `for` loop. The disambiguation code in - // `parseStatement` will already have parsed the init statement or - // expression. - - function parseFor(node, init) { - node.init = init; - expect(_semi, "Expected ';' in for statement"); - node.test = tokType === _semi ? null : parseExpression(); - expect(_semi, "Expected ';' in for statement"); - node.update = tokType === _parenR ? null : parseExpression(); - expect(_parenR, "Expected closing ')' in for statement"); - node.body = parseStatement(); - labels.pop(); - return finishNode(node, "ForStatement"); - } - - // Parse a `for`/`in` loop. - - function parseForIn(node, init) { - node.left = init; - node.right = parseExpression(); - expect(_parenR, "Expected closing ')' in for statement"); - node.body = parseStatement(); - labels.pop(); - return finishNode(node, "ForInStatement"); - } - - // Parse a list of variable declarations. - - function parseVar(node, noIn) { - node.declarations = []; - node.kind = "var"; - for (;;) { - var decl = startNode(); - decl.id = parseIdent(); - if (strict && isStrictBadIdWord(decl.id.name)) - raise(decl.id.start, "Binding " + decl.id.name + " in strict mode"); - decl.init = eat(_eq) ? parseExpression(true, noIn) : null; - node.declarations.push(finishNode(decl, "VariableDeclarator")); - if (!eat(_comma)) break; - } - return finishNode(node, "VariableDeclaration"); - } - - // ### Expression parsing - - // These nest, from the most general expression type at the top to - // 'atomic', nondivisible expression types at the bottom. Most of - // the functions will simply let the function(s) below them parse, - // and, *if* the syntactic construct they handle is present, wrap - // the AST node that the inner parser gave them in another node. - - // Parse a full expression. The arguments are used to forbid comma - // sequences (in argument lists, array literals, or object literals) - // or the `in` operator (in for loops initalization expressions). - - function parseExpression(noComma, noIn) { - var expr = parseMaybeAssign(noIn); - if (!noComma && tokType === _comma) { - var node = startNodeFrom(expr); - node.expressions = [expr]; - while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn)); - return finishNode(node, "SequenceExpression"); - } - return expr; - } - - // Parse an assignment expression. This includes applications of - // operators like `+=`. - - function parseMaybeAssign(noIn) { - var left = parseMaybeConditional(noIn); - if (tokType.isAssign) { - var node = startNodeFrom(left); - node.operator = tokVal; - node.left = left; - next(); - node.right = parseMaybeAssign(noIn); - checkLVal(left); - return finishNode(node, "AssignmentExpression"); - } - return left; - } - - // Parse a ternary conditional (`?:`) operator. - - function parseMaybeConditional(noIn) { - var expr = parseExprOps(noIn); - if (eat(_question)) { - var node = startNodeFrom(expr); - node.test = expr; - node.consequent = parseExpression(true); - expect(_colon, "Expected ':' in conditional expression"); - node.alternate = parseExpression(true, noIn); - return finishNode(node, "ConditionalExpression"); - } - return expr; - } - - // Start the precedence parser. - - function parseExprOps(noIn) { - return parseExprOp(parseMaybeUnary(), -1, noIn); - } - - // Parse binary operators with the operator precedence parsing - // algorithm. `left` is the left-hand side of the operator. - // `minPrec` provides context that allows the function to stop and - // defer further parser to one of its callers when it encounters an - // operator that has a lower precedence than the set it is parsing. - - function parseExprOp(left, minPrec, noIn) { - var prec = tokType.binop; - if (prec != null && (!noIn || tokType !== _in)) { - if (prec > minPrec) { - var node = startNodeFrom(left); - node.left = left; - node.operator = tokVal; - next(); - node.right = parseExprOp(parseMaybeUnary(), prec, noIn); - var node = finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression"); - return parseExprOp(node, minPrec, noIn); - } - } - return left; - } - - // Parse unary operators, both prefix and postfix. - - function parseMaybeUnary() { - if (tokType.prefix) { - var node = startNode(), update = tokType.isUpdate; - node.operator = tokVal; - node.prefix = true; - tokRegexpAllowed = true; - next(); - node.argument = parseMaybeUnary(); - if (update) checkLVal(node.argument); - else if (strict && node.operator === "delete" && - node.argument.type === "Identifier") - raise(node.start, "Deleting local variable in strict mode"); - return finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } - var expr = parseExprSubscripts(); - while (tokType.postfix && !canInsertSemicolon()) { - var node = startNodeFrom(expr); - node.operator = tokVal; - node.prefix = false; - node.argument = expr; - checkLVal(expr); - next(); - expr = finishNode(node, "UpdateExpression"); - } - return expr; - } - - // Parse call, dot, and `[]`-subscript expressions. - - function parseExprSubscripts() { - return parseSubscripts(parseExprAtom()); - } - - function parseSubscripts(base, noCalls) { - if (eat(_dot)) { - var node = startNodeFrom(base); - node.object = base; - node.property = parseIdent(true); - node.computed = false; - return parseSubscripts(finishNode(node, "MemberExpression"), noCalls); - } else { - if (options.objj) var messageSendNode = startNode(); - if (eat(_bracketL)) { - var expr = parseExpression(); - if (options.objj && tokType !== _bracketR) { - messageSendNode.object = expr; - nodeMessageSendObjectExpression = messageSendNode; - return base; - } - var node = startNodeFrom(base); - node.object = base; - node.property = expr; - node.computed = true; - expect(_bracketR, "Expected closing ']' in subscript"); - return parseSubscripts(finishNode(node, "MemberExpression"), noCalls); - } else if (!noCalls && eat(_parenL)) { - var node = startNodeFrom(base); - node.callee = base; - node.arguments = parseExprList(_parenR, tokType === _parenR ? null : parseExpression(true), false); - return parseSubscripts(finishNode(node, "CallExpression"), noCalls); - } - } - return base; - } - - // Parse an atomic expression — either a single token that is an - // expression, an expression started by a keyword like `function` or - // `new`, or an expression wrapped in punctuation like `()`, `[]`, - // or `{}`. - - function parseExprAtom() { - switch (tokType) { - case _this: - var node = startNode(); - next(); - return finishNode(node, "ThisExpression"); - case _name: - return parseIdent(); - case _num: case _string: case _regexp: - return parseStringNumRegExpLiteral(); - - case _null: case _true: case _false: - var node = startNode(); - node.value = tokType.atomValue; - node.raw = tokType.keyword; - next(); - return finishNode(node, "Literal"); - - case _parenL: - var tokStartLoc1 = tokStartLoc, macroOffset = tokMacroOffset, tokStart1 = tokStart + macroOffset; - next(); - var val = parseExpression(); - val.start = tokStart1; - val.end = tokEnd + macroOffset; - if (options.locations) { - val.loc.start = tokStartLoc1; - val.loc.end = tokEndLoc; - } - if (options.ranges) - val.range = [tokStart1, tokEnd + lastTokMacroOffset]; - expect(_parenR, "Expected closing ')' in expression"); - return val; - - case _arrayLiteral: - var node = startNode(), - firstExpr = null; - - next(); - expect(_bracketL, "Expected '[' at beginning of array literal"); - - if (tokType !== _bracketR) - firstExpr = parseExpression(true, true); - - node.elements = parseExprList(_bracketR, firstExpr, true, true); - return finishNode(node, "ArrayLiteral"); - - case _bracketL: - var node = startNode(), - firstExpr = null; - next(); - if (tokType !== _comma && tokType !== _bracketR) { - firstExpr = parseExpression(true, true); - if (tokType !== _comma && tokType !== _bracketR) - return parseMessageSendExpression(node, firstExpr); - } - node.elements = parseExprList(_bracketR, firstExpr, true, true); - return finishNode(node, "ArrayExpression"); - - case _dictionaryLiteral: - var node = startNode(); - next(); - - var r = parseDictionary(); - node.keys = r[0]; - node.values = r[1]; - return finishNode(node, "DictionaryLiteral"); - - case _braceL: - return parseObj(); - - case _function: - var node = startNode(); - next(); - return parseFunction(node, false); - - case _new: - return parseNew(); - - case _selector: - var node = startNode(); - next(); - expect(_parenL, "Expected '(' after '@selector'"); - parseSelector(node, _parenR); - expect(_parenR, "Expected closing ')' after selector"); - return finishNode(node, "SelectorLiteralExpression"); - - case _protocol: - var node = startNode(); - next(); - expect(_parenL, "Expected '(' after '@protocol'"); - node.id = parseIdent(true); - expect(_parenR, "Expected closing ')' after protocol name"); - return finishNode(node, "ProtocolLiteralExpression"); - - case _ref: - var node = startNode(); - next(); - expect(_parenL, "Expected '(' after '@ref'"); - node.element = parseIdent(node, _parenR); - expect(_parenR, "Expected closing ')' after ref"); - return finishNode(node, "Reference"); - - case _deref: - var node = startNode(); - next(); - expect(_parenL, "Expected '(' after '@deref'"); - node.expr = parseExpression(true, true); - expect(_parenR, "Expected closing ')' after deref"); - return finishNode(node, "Dereference"); - - default: - if (tokType.okAsIdent) - return parseIdent(); - - unexpected(); - } - } - - function parseMessageSendExpression(node, firstExpr) { - parseSelectorWithArguments(node, _bracketR); - if (firstExpr.type === "Identifier" && firstExpr.name === "super") - node.superObject = true; - else - node.object = firstExpr; - return finishNode(node, "MessageSendExpression"); - } - - function parseSelector(node, close) { - var first = true, - selectors = []; - for (;;) { - if (tokType !== _colon) { - selectors.push(parseIdent(true).name); - if (first && tokType === close) break; - } - expect(_colon, "Expected ':' in selector"); - selectors.push(":"); - if (tokType === close) break; - first = false; - } - node.selector = selectors.join(""); - } - - function parseSelectorWithArguments(node, close) { - var first = true, - selectors = [], - args = [], - parameters = []; - node.selectors = selectors; - node.arguments = args; - for (;;) { - if (tokType !== _colon) { - selectors.push(parseIdent(true)); - if (first && eat(close)) - break; - } else { - selectors.push(null); - } - expect(_colon, "Expected ':' in selector"); - args.push(parseExpression(true, true)); - if (eat(close)) - break; - if (tokType === _comma) { - node.parameters = []; - while(eat(_comma)) { - node.parameters.push(parseExpression(true, true)); - } - eat(close); - break; - } - first = false; - } - } - - // New's precedence is slightly tricky. It must allow its argument - // to be a `[]` or dot subscript expression, but not a call — at - // least, not without wrapping it in parentheses. Thus, it uses the - - function parseNew() { - var node = startNode(); - next(); - node.callee = parseSubscripts(parseExprAtom(false), true); - if (eat(_parenL)) - node.arguments = parseExprList(_parenR, tokType === _parenR ? null : parseExpression(true), false); - else node.arguments = empty; - return finishNode(node, "NewExpression"); - } - - // Parse an object literal. - - function parseObj() { - var node = startNode(), first = true, sawGetSet = false; - node.properties = []; - next(); - while (!eat(_braceR)) { - if (!first) { - expect(_comma, "Expected ',' in object literal"); - if (options.allowTrailingCommas && eat(_braceR)) break; - } else first = false; - - var prop = {key: parsePropertyName()}, isGetSet = false, kind; - if (eat(_colon)) { - prop.value = parseExpression(true); - kind = prop.kind = "init"; - } else if (options.ecmaVersion >= 5 && prop.key.type === "Identifier" && - (prop.key.name === "get" || prop.key.name === "set")) { - isGetSet = sawGetSet = true; - kind = prop.kind = prop.key.name; - prop.key = parsePropertyName(); - if (tokType !== _parenL) unexpected(); - prop.value = parseFunction(startNode(), false); - } else unexpected(); - - // getters and setters are not allowed to clash — either with - // each other or with an init property — and in strict mode, - // init properties are also not allowed to be repeated. - - if (prop.key.type === "Identifier" && (strict || sawGetSet)) { - for (var i = 0; i < node.properties.length; ++i) { - var other = node.properties[i]; - if (other.key.name === prop.key.name) { - var conflict = kind == other.kind || isGetSet && other.kind === "init" || - kind === "init" && (other.kind === "get" || other.kind === "set"); - if (conflict && !strict && kind === "init" && other.kind === "init") conflict = false; - if (conflict) raise(prop.key.start, "Redefinition of property"); - } - } - } - node.properties.push(prop); - } - return finishNode(node, "ObjectExpression"); - } - - function parsePropertyName() { - if (tokType === _num || tokType === _string) return parseExprAtom(); - return parseIdent(true); - } - - // Parse a function declaration or literal (depending on the - // `isStatement` parameter). - - function parseFunction(node, isStatement) { - if (tokType === _name) node.id = parseIdent(); - else if (isStatement) unexpected(); - else node.id = null; - node.params = []; - var first = true; - expect(_parenL, "Expected '(' before function parameters"); - while (!eat(_parenR)) { - if (!first) expect(_comma, "Expected ',' between function parameters"); else first = false; - node.params.push(parseIdent()); - } - - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). - var oldInFunc = inFunction, oldLabels = labels; - inFunction = true; labels = []; - node.body = parseBlock(true); - inFunction = oldInFunc; labels = oldLabels; - - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - if (strict || node.body.body.length && isUseStrict(node.body.body[0])) { - for (var i = node.id ? -1 : 0; i < node.params.length; ++i) { - var id = i < 0 ? node.id : node.params[i]; - if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name)) - raise(id.start, "Defining '" + id.name + "' in strict mode"); - if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name) - raise(id.start, "Argument name clash in strict mode"); - } - } - - return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); - } - - // Parses a comma-separated list of expressions, and returns them as - // an array. `close` is the token type that ends the list, and - // `allowEmpty` can be turned on to allow subsequent commas with - // nothing in between them to be parsed as `null` (which is needed - // for array literals). - // This function is modified so the first expression is passed as a - // parameter. This is nessesary cause we need to check if it is a Objective-J - // message send expression ([expr mySelector:param1 withSecondParam:param2]) - - function parseExprList(close, firstExpr, allowTrailingComma, allowEmpty) { - if (firstExpr && eat(close)) - return [firstExpr]; - var elts = [], first = true; - while (!eat(close)) { - if (first) { - first = false; - if (allowEmpty && tokType === _comma && !firstExpr) elts.push(null); - else elts.push(firstExpr); - } else { - expect(_comma, "Expected ',' between expressions"); - if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break; - if (allowEmpty && tokType === _comma) elts.push(null); - else elts.push(parseExpression(true)); - } - } - return elts; - } - - // Parses a comma-separated list of : pairs and returns them as - // [arrayOfKeyExpressions, arrayOfValueExpressions]. - function parseDictionary() { - expect(_braceL, "Expected '{' before dictionary"); - - var keys = [], values = [], first = true; - while (!eat(_braceR)) { - if (!first) { - expect(_comma, "Expected ',' between expressions"); - if (options.allowTrailingCommas && eat(_braceR)) break; - } - - keys.push(parseExpression(true, true)); - expect(_colon, "Expected ':' between dictionary key and value"); - values.push(parseExpression(true, true)); - first = false; - } - return [keys, values]; - } - - // Parse the next token as an identifier. If `liberal` is true (used - // when parsing properties), it will also convert keywords into - // identifiers. - - function parseIdent(liberal) { - var node = startNode(); - node.name = tokType === _name ? tokVal : (((liberal && !options.forbidReserved) || tokType.okAsIdent) && tokType.keyword) || unexpected(); - tokRegexpAllowed = false; - next(); - return finishNode(node, "Identifier"); - } - - function parseStringNumRegExpLiteral() { - var node = startNode(); - node.value = tokVal; - node.raw = tokInput.slice(tokStart, tokEnd); - next(); - return finishNode(node, "Literal"); - } - - // Parse the next token as an Objective-J typ. - // It can be 'id' followed by a optional protocol '' - // It can be 'void' or 'id' - // It can be 'signed' or 'unsigned' followed by an optional 'char', 'byte', 'short', 'int' or 'long' - // It can be 'char', 'byte', 'short', 'int' or 'long' - // 'int' can be followed by an optinal 'long'. 'long' can be followed by an optional extra 'long' - - function parseObjectiveJType(startFrom) { - var node = startFrom ? startNodeFrom(startFrom) : startNode(), allowProtocol = false; - if (tokType === _name) { - // It should be a class name - node.name = tokVal; - node.typeisclass = true; - allowProtocol = true; - next(); - } else { - node.typeisclass = false; - node.name = tokType.keyword; - // Do nothing more if it is 'void' - if (!eat(_void)) { - if (eat(_id)) { - allowProtocol = true; - } else { - // Now check if it is some basic type or an approved combination of basic types - var nextKeyWord; - if (eat(_float) || eat(_boolean) || eat(_SEL) || eat(_double)) - { - nextKeyWord = tokType.keyword; - } - else { - if (eat(_signed) || eat(_unsigned)) - nextKeyWord = tokType.keyword || true; - if (eat(_char) || eat(_byte) || eat(_short)) { - if (nextKeyWord) - node.name += " " + nextKeyWord; - nextKeyWord = tokType.keyword || true; - } else { - if (eat(_int)) { - if (nextKeyWord) - node.name += " " + nextKeyWord; - nextKeyWord = tokType.keyword || true; - } - if (eat(_long)) { - if (nextKeyWord) - node.name += " " + nextKeyWord; - nextKeyWord = tokType.keyword || true; - if (eat(_long)) { - node.name += " " + nextKeyWord; - } - } - } - if (!nextKeyWord) { - // It must be a class name if it was not a basic type. // FIXME: This is not true - node.name = (!options.forbidReserved && tokType.keyword) || unexpected(); - node.typeisclass = true; - allowProtocol = true; - next(); - } - } - } - } - } - if (allowProtocol) { - // Is it 'id' or classname followed by a '<' then parse protocols. - if (tokVal === '<') { - var first = true, - protocols = []; - node.protocols = protocols; - do { - next(); - if (first) - first = false; - else - eat(_comma); - protocols.push(parseIdent(true)); - } while (tokVal !== '>'); - next(); - } - } - return finishNode(node, "ObjectiveJType"); - } - -})(exports.acorn || (exports.acorn = {}), exports.acorn.walk || (exports.acorn.walk = (typeof acorn !== 'undefined') && acorn.walk) || (exports.acorn.walk = {})); diff --git a/Objective-J/acornLICENSE b/Objective-J/acornLICENSE deleted file mode 100644 index 3916e96b2..000000000 --- a/Objective-J/acornLICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (C) 2012 by Marijn Haverbeke - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Please note that some subdirectories of the CodeMirror distribution -include their own LICENSE files, and are released under different -licences. diff --git a/Objective-J/acornwalk.js b/Objective-J/acornwalk.js deleted file mode 100644 index 456fec8a4..000000000 --- a/Objective-J/acornwalk.js +++ /dev/null @@ -1,285 +0,0 @@ -// AST walker module for Mozilla Parser API compatible trees - -if (!exports.acorn) { - exports.acorn = {}; - exports.acorn.walk = {}; -} - -(function(exports) { - "use strict"; - - // A simple walk is one where you simply specify callbacks to be - // called on specific nodes. The last two arguments are optional. A - // simple use would be - // - // walk.simple(myTree, { - // Expression: function(node) { ... } - // }); - // - // to do something with all expressions. All Parser API node types - // can be used to identify node types, as well as Expression, - // Statement, and ScopeBody, which denote categories of nodes. - // - // The base argument can be used to pass a custom (recursive) - // walker, and state can be used to give this walked an initial - // state. - exports.simple = function(node, visitors, base, state) { - if (!base) base = exports; - function c(node, st, override) { - var type = override || node.type, found = visitors[type]; - if (found) found(node, st); - base[type](node, st, c); - } - c(node, state); - }; - - // A recursive walk is one where your functions override the default - // walkers. They can modify and replace the state parameter that's - // threaded through the walk, and can opt how and whether to walk - // their child nodes (by calling their third argument on these - // nodes). - exports.recursive = function(node, state, funcs, base) { - var visitor = exports.make(funcs, base); - function c(node, st, override) { - return visitor[override || node.type](node, st, c); - } - return c(node, state); - }; - - // Used to create a custom walker. Will fill in all missing node - // type properties with the defaults. - exports.make = function(funcs, base) { - if (!base) base = exports; - var visitor = {}; - for (var type in base) visitor[type] = base[type]; - for (var type in funcs) visitor[type] = funcs[type]; - return visitor; - }; - - function skipThrough(node, st, c) { c(node, st); } - function ignore(node, st, c) {} - - // Node walkers. - - exports.Program = exports.BlockStatement = function(node, st, c) { - for (var i = 0; i < node.body.length; ++i) { - c(node.body[i], st, "Statement"); - } - }; - exports.Statement = skipThrough; - exports.EmptyStatement = ignore; - exports.ExpressionStatement = function(node, st, c) { - c(node.expression, st, "Expression"); - }; - exports.IfStatement = function(node, st, c) { - c(node.test, st, "Expression"); - c(node.consequent, st, "Statement"); - if (node.alternate) c(node.alternate, st, "Statement"); - }; - exports.LabeledStatement = function(node, st, c) { - c(node.body, st, "Statement"); - }; - exports.BreakStatement = exports.ContinueStatement = ignore; - exports.WithStatement = function(node, st, c) { - c(node.object, st, "Expression"); - c(node.body, st, "Statement"); - }; - exports.SwitchStatement = function(node, st, c) { - c(node.discriminant, st, "Expression"); - for (var i = 0; i < node.cases.length; ++i) { - var cs = node.cases[i]; - if (cs.test) c(cs.test, st, "Expression"); - for (var j = 0; j < cs.consequent.length; ++j) - c(cs.consequent[j], st, "Statement"); - } - }; - exports.ReturnStatement = function(node, st, c) { - if (node.argument) c(node.argument, st, "Expression"); - }; - exports.ThrowStatement = function(node, st, c) { - c(node.argument, st, "Expression"); - }; - exports.TryStatement = function(node, st, c) { - c(node.block, st, "Statement"); - if (node.handler) c(node.handler.body, st, "ScopeBody"); - if (node.finalizer) c(node.finalizer, st, "Statement"); - }; - exports.WhileStatement = function(node, st, c) { - c(node.test, st, "Expression"); - c(node.body, st, "Statement"); - }; - exports.DoWhileStatement = function(node, st, c) { - c(node.body, st, "Statement"); - c(node.test, st, "Expression"); - }; - exports.ForStatement = function(node, st, c) { - if (node.init) c(node.init, st, "ForInit"); - if (node.test) c(node.test, st, "Expression"); - if (node.update) c(node.update, st, "Expression"); - c(node.body, st, "Statement"); - }; - exports.ForInStatement = function(node, st, c) { - c(node.left, st, "ForInit"); - c(node.right, st, "Expression"); - c(node.body, st, "Statement"); - }; - exports.ForInit = function(node, st, c) { - if (node.type == "VariableDeclaration") c(node, st); - else c(node, st, "Expression"); - }; - exports.DebuggerStatement = ignore; - - exports.FunctionDeclaration = function(node, st, c) { - c(node, st, "Function"); - }; - exports.VariableDeclaration = function(node, st, c) { - for (var i = 0; i < node.declarations.length; ++i) { - var decl = node.declarations[i]; - if (decl.init) c(decl.init, st, "Expression"); - } - }; - - exports.Function = function(node, st, c) { - c(node.body, st, "ScopeBody"); - }; - exports.ScopeBody = function(node, st, c) { - c(node, st, "Statement"); - }; - - exports.Expression = skipThrough; - exports.ThisExpression = ignore; - exports.ArrayExpression = exports.ArrayLiteral = function(node, st, c) { - for (var i = 0; i < node.elements.length; ++i) { - var elt = node.elements[i]; - if (elt) c(elt, st, "Expression"); - } - }; - exports.DictionaryLiteral = function(node, st, c) { - for (var i = 0; i < node.keys.length; i++) { - var key = node.keys[i]; - c(key, st, "Expression"); - var value = node.values[i]; - c(value, st, "Expression"); - } - }; - exports.ObjectExpression = function(node, st, c) { - for (var i = 0; i < node.properties.length; ++i) - c(node.properties[i].value, st, "Expression"); - }; - exports.FunctionExpression = exports.FunctionDeclaration; - exports.SequenceExpression = function(node, st, c) { - for (var i = 0; i < node.expressions.length; ++i) - c(node.expressions[i], st, "Expression"); - }; - exports.UnaryExpression = exports.UpdateExpression = function(node, st, c) { - c(node.argument, st, "Expression"); - }; - exports.BinaryExpression = exports.AssignmentExpression = exports.LogicalExpression = function(node, st, c) { - c(node.left, st, "Expression"); - c(node.right, st, "Expression"); - }; - exports.ConditionalExpression = function(node, st, c) { - c(node.test, st, "Expression"); - c(node.consequent, st, "Expression"); - c(node.alternate, st, "Expression"); - }; - exports.NewExpression = exports.CallExpression = function(node, st, c) { - c(node.callee, st, "Expression"); - if (node.arguments) for (var i = 0; i < node.arguments.length; ++i) - c(node.arguments[i], st, "Expression"); - }; - exports.MemberExpression = function(node, st, c) { - c(node.object, st, "Expression"); - if (node.computed) c(node.property, st, "Expression"); - }; - exports.Identifier = exports.Literal = ignore; - - exports.ClassDeclarationStatement = function(node, st, c) { - if (node.ivardeclarations) for (var i = 0; i < node.ivardeclarations.length; ++i) { - c(node.ivardeclarations[i], st, "IvarDeclaration"); - } - for (var i = 0; i < node.body.length; ++i) { - c(node.body[i], st, "Statement"); - } - } - - exports.ImportStatement = ignore; - - exports.IvarDeclaration = ignore; - - exports.PreprocessStatement = ignore; - exports.ClassStatement = ignore; - exports.GlobalStatement = ignore; - - exports.ProtocolDeclarationStatement = function(node, st, c) { - if (node.required) for (var i = 0; i < node.required.length; ++i) { - c(node.required[i], st, "Statement"); - } - if (node.optional) for (var i = 0; i < node.optional.length; ++i) { - c(node.optional[i], st, "Statement"); - } - } - - exports.TypeDefStatement = ignore; - - exports.MethodDeclarationStatement = function(node, st, c) { - var body = node.body; - if (body) - c(body, st, "Statement"); - } - - exports.MessageSendExpression = function(node, st, c) { - if (!node.superObject) c(node.object, st, "Expression"); - if (node.arguments) for (var i = 0; i < node.arguments.length; ++i) - c(node.arguments[i], st, "Expression"); - if (node.parameters) for (var i = 0; i < node.parameters.length; ++i) - c(node.parameters[i], st, "Expression"); - } - - exports.SelectorLiteralExpression = ignore; - exports.ProtocolLiteralExpression = ignore; - - exports.Reference = function(node, st, c) { - c(node.element, st, "Identifier"); - } - - exports.Dereference = function(node, st, c) { - c(node.expr, st, "Expression"); - } - - // A custom walker that keeps track of the scope chain and the - // variables defined in it. - function makeScope(prev) { - return {vars: Object.create(null), prev: prev}; - } - exports.scopeVisitor = exports.make({ - Function: function(node, scope, c) { - var inner = makeScope(scope); - for (var i = 0; i < node.params.length; ++i) - inner.vars[node.params[i].name] = {type: "argument", node: node.params[i]}; - if (node.id) { - var decl = node.type == "FunctionDeclaration"; - (decl ? scope : inner).vars[node.id.name] = - {type: decl ? "function" : "function name", node: node.id}; - } - c(node.body, inner, "ScopeBody"); - }, - TryStatement: function(node, scope, c) { - c(node.block, scope, "Statement"); - if (node.handler) { - var inner = makeScope(scope); - inner.vars[node.handler.param.name] = {type: "catch clause", node: node.handler.param}; - c(node.handler.body, inner, "ScopeBody"); - } - if (node.finalizer) c(node.finalizer, scope, "Statement"); - }, - VariableDeclaration: function(node, scope, c) { - for (var i = 0; i < node.declarations.length; ++i) { - var decl = node.declarations[i]; - scope.vars[decl.id.name] = {type: "var", node: decl.id}; - if (decl.init) c(decl.init, scope, "Expression"); - } - } - }); - -})(typeof exports == "undefined" ? acorn.walk = {} : exports.acorn.walk); diff --git a/Tests/Objective-J/CFPropertyListTest.j b/Tests/Objective-J/CFPropertyListTest.j index cadd255eb..e46acd81f 100644 --- a/Tests/Objective-J/CFPropertyListTest.j +++ b/Tests/Objective-J/CFPropertyListTest.j @@ -8,7 +8,6 @@ var fs = require("fs"), - (void)testFormatSniffing { - debugger; var XMLPropertyLists = new FileList(path.join(path.dirname(__filename), "PropertyLists", "XML-*.plist")); XMLPropertyLists.forEach(function(/*String*/ aPath) diff --git a/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j b/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j index 14efc8e2a..3492cfc3c 100644 --- a/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j +++ b/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j @@ -60,12 +60,12 @@ async function compressor(srcCode) { correctInlined = fs.existsSync(p) ? fs.readFileSync(p, {encoding: "utf8"}) : correct; // Get inlined version if it exists. Otherwise use the regular one. await [self assertNoThrow: async function() { - preprocessed = ObjectiveJ.ObjJCompiler.compile(unpreprocessed, nil, {includeMethodFunctionNames: true, includeMethodArgumentTypeSignatures: true, includeIvarTypeSignatures: true, inlineMsgSendFunctions: false, transformNamedFunctionDeclarationToAssignment: true}).jsBuffer.toString(); + preprocessed = ObjectiveJ.ObjJCompiler.compile(unpreprocessed, nil, {includeMethodFunctionNames: true, includeMethodArgumentTypeSignatures: true, includeIvarTypeSignatures: true, inlineMsgSendFunctions: false, transformNamedFunctionDeclarationToAssignment: true, acornOptions: {ecmaVersion: 2022}}).jsBuffer.toString(); preprocessed = await compressor(preprocessed); correct = await compressor(correct); // Get an Inlined version - preprocessedInlined = ObjectiveJ.ObjJCompiler.compile(unpreprocessed, nil, {includeMethodFunctionNames: true, includeMethodArgumentTypeSignatures: true, includeIvarTypeSignatures: true, inlineMsgSendFunctions: true, transformNamedFunctionDeclarationToAssignment: true}).jsBuffer.toString(); + preprocessedInlined = ObjectiveJ.ObjJCompiler.compile(unpreprocessed, nil, {includeMethodFunctionNames: true, includeMethodArgumentTypeSignatures: true, includeIvarTypeSignatures: true, inlineMsgSendFunctions: true, transformNamedFunctionDeclarationToAssignment: true, acornOptions: {ecmaVersion: 2022}}).jsBuffer.toString(); preprocessedInlined = await compressor(preprocessedInlined); correctInlined = await compressor(correctInlined); }]; diff --git a/Tools/XcodeCapp/XcodeCapp/XCCTaskLauncher.m b/Tools/XcodeCapp/XcodeCapp/XCCTaskLauncher.m index fccecd51c..c8ad64e61 100644 --- a/Tools/XcodeCapp/XcodeCapp/XCCTaskLauncher.m +++ b/Tools/XcodeCapp/XcodeCapp/XCCTaskLauncher.m @@ -40,7 +40,9 @@ self.environment[@"NARWHAL_ENGINE"] = @"jsc"; self.environment[@"CAPP_NOSUDO"] = @"1"; - self.executables = @[@"python", @"objj", @"nib2cib",@"objj2objcskeleton", @"capp_lint", @"touch"]; + //self.executables = @[@"python", @"objj", @"nib2cib",@"objj2objcskeleton", @"capp_lint", @"touch"]; + // Removed python and capp_liunt as python2 is not supported anymore. + self.executables = @[@"objj", @"nib2cib",@"objj2objcskeleton", @"touch"]; self.isValid = [self _checkExecutables]; } diff --git a/Tools/objj2objcskeleton/objj2objcskeleton b/Tools/objj2objcskeleton/objj2objcskeleton index b7972dbb3..eb342155b 100644 --- a/Tools/objj2objcskeleton/objj2objcskeleton +++ b/Tools/objj2objcskeleton/objj2objcskeleton @@ -4,14 +4,11 @@ var fs = require("fs"), acorn = require("objj-parser"), - walk = require("objj-parser/util/walk"), + walk = require("acorn-walk"), stream = ObjectiveJ.term; - debugger; - function main(args) { - debugger; args.shift(); if (args.length < 1) @@ -40,6 +37,8 @@ function raise(pos, message) throw syntaxError; } +function ignore(_node, _st, _c) {} + var errors = [], xcc = walk.make( { @@ -115,7 +114,17 @@ var errors = [], else raise(node.loc.start, "Action methods must have exactly one parameter"); } - } + }, + TypeDefStatement: ignore, + ClassStatement: ignore, + MessageSendExpression: ignore, + GlobalStatement: ignore, + ProtocolDeclarationStatement: ignore, + ArrayLiteral: ignore, + Reference: ignore, + DictionaryLiteral: ignore, + Dereference: ignore, + ImportStatement: ignore } ); @@ -154,7 +163,7 @@ function parser(args) outputHeaderURL = new CFURL([outputDirectory stringByAppendingPathComponent:baseFilenameWithNoExtension + ".h"]), outputImplementationURL = new CFURL([outputDirectory stringByAppendingPathComponent:baseFilenameWithNoExtension + ".m"]), source = fs.readFileSync(sourcePath, { encoding: "utf8" }), - tokens = acorn.parse(source, { locations:true, sourceFile:sourcePath }), + tokens = acorn.parse(source, { locations:true, sourceFile:sourcePath, ecmaVersion: 2022 }), classesInformation = [], ObjectiveCSource = "", ObjectiveCHeader = "", diff --git a/package-lock.json b/package-lock.json index 76db4912b..2effd9f00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "@objj/cappuccino", - "version": "1.2.2", + "version": "1.3.0-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@objj/cappuccino", - "version": "1.2.2", + "version": "1.3.0-2", "license": "LGPL-2.1-or-later", "dependencies": { "@objj/jake": "latest", "@objj/ojtest": "latest", - "@objj/runtime": "latest", - "terser": ">=5.7.0" + "@objj/runtime": "^1.2.1-1", + "acorn-walk": "^8.2.0", + "terser": "^5.14.2" }, "bin": { "capp": "dist/cappuccino/bin/capp", @@ -35,6 +36,58 @@ "node": ">=14.0.0" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@objj/cappuccino": { "resolved": "", "link": true @@ -62,13 +115,13 @@ } }, "node_modules/@objj/runtime": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@objj/runtime/-/runtime-1.1.14.tgz", - "integrity": "sha512-lJy+6ZfV8BLAAwNVffaOzhfBI4FnUmws5BcKHYbsQjQnpp7D7/rrihRUoYY+o8ZtkiK2H1gGcXsqA0J518XWIw==", + "version": "1.2.1-1", + "resolved": "https://registry.npmjs.org/@objj/runtime/-/runtime-1.2.1-1.tgz", + "integrity": "sha512-eq1m0TlwPo4AVAklVNXuhi+YrIJysbfdPD+MTZgcEsj452Cct/P3YWCJRfFwvUWmP4UqaJD7iddVJvWrkeZdtg==", "dependencies": { "@objj/utils": ">=1.0.23", "@xmldom/xmldom": ">=0.7.5", - "objj-transpiler": ">=0.5.6", + "objj-transpiler": "^1.0.0-1", "readline-history": ">=1.2.0", "xmlhttprequest-ssl": "^2.0.0" }, @@ -85,17 +138,36 @@ "integrity": "sha512-KzthoKXSs3LcWDWfl27p/rOCoejcxyy/4DgbacjcxiowJJXa+QMmIsjZ/fcg9lcn13jL0gB4c1x1kGPfrrsZPw==" }, "node_modules/@xmldom/xmldom": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", - "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.2.tgz", + "integrity": "sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ==", "engines": { "node": ">=10.0.0" } }, + "node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", "engines": { "node": ">=0.4.2" } @@ -111,26 +183,27 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/objj-parser": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/objj-parser/-/objj-parser-0.4.3.tgz", - "integrity": "sha512-98qHphDEAP0hfmjFTVacLPiMeOqGYOOazAQczlxqchEGPzzlyVwNnECOOMs2jCY0zQ68TPX/xYKgbsfXpHI6Mg==", + "version": "1.0.0-4", + "resolved": "https://registry.npmjs.org/objj-parser/-/objj-parser-1.0.0-4.tgz", + "integrity": "sha512-W+38550qhkTZOb6MkZBqnBwMX3PPMbVa5n2trTmWHPU4RlNgE+sV0l9CagBzcFVnXD1cmhnmTNLbF5XAg+DRKA==", "bin": { - "acorn": "bin/acorn" + "objj-parser": "bin/objj-parser" }, "engines": { - "node": ">=14.0.0" + "node": ">=1.0.0" } }, "node_modules/objj-transpiler": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/objj-transpiler/-/objj-transpiler-0.5.7.tgz", - "integrity": "sha512-9G5NOufdV3997ITROe/HU8RREmr4aEUsW52hJC7vFGQcCQAbJYrnSIYR2187bLAoOKOmW5Uj5lUYK8kdJbqzPQ==", + "version": "1.0.0-3", + "resolved": "https://registry.npmjs.org/objj-transpiler/-/objj-transpiler-1.0.0-3.tgz", + "integrity": "sha512-CGCs64MCNhXeAuWXZx7yT/UDTZO99t1Jxw/Z+Ec+8eYdzOxEsDfV+YRYrwvZ4ZIpM9uX7CuWHLhcJe2PWacX3w==", "dependencies": { - "objj-parser": ">=0.4.0", + "acorn-walk": "8.2.0", + "objj-parser": "^1.0.0-1", "source-map": "0.4.x" }, "bin": { - "objjc": "bin/objjc" + "objjc": "bin/objjc.js" }, "engines": { "node": ">=0.10.0" @@ -139,12 +212,12 @@ "node_modules/readline-history": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/readline-history/-/readline-history-1.2.0.tgz", - "integrity": "sha1-9nBUOyzpASFH/pkD+D0cGJwX0zM=" + "integrity": "sha512-8R0Vr9jhdtqYSdWGpAvkEopvuPKjAlYELIKoa7+7FO2CBN/b88rYB9r9gFSNtdCUHdAOJslj0KDG75MsiozXIQ==" }, "node_modules/source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", "dependencies": { "amdefine": ">=0.0.4" }, @@ -153,9 +226,9 @@ } }, "node_modules/source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -170,12 +243,13 @@ } }, "node_modules/terser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", - "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" }, "bin": { @@ -185,14 +259,6 @@ "node": ">=10" } }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "engines": { - "node": ">= 8" - } - }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", @@ -203,16 +269,103 @@ } }, "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@objj/cappuccino": { "version": "file:", "requires": { "@objj/cappuccino": "file:", "@objj/jake": "latest", "@objj/ojtest": "latest", - "@objj/runtime": "latest", - "terser": ">=5.7.0" + "@objj/runtime": "^1.2.1-1", + "acorn-walk": "^8.2.0", + "terser": "^5.14.2" }, "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@objj/jake": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@objj/jake/-/jake-1.1.6.tgz", @@ -227,13 +380,13 @@ "integrity": "sha512-T87JtTVJnXcxWdVHchJwrHuQPZLp0mh4MXCOpoMGffKSU2jbL7l+uxK6KPWRMW/ajjQL/aE5dJKguJohmmYtRg==" }, "@objj/runtime": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@objj/runtime/-/runtime-1.1.14.tgz", - "integrity": "sha512-lJy+6ZfV8BLAAwNVffaOzhfBI4FnUmws5BcKHYbsQjQnpp7D7/rrihRUoYY+o8ZtkiK2H1gGcXsqA0J518XWIw==", + "version": "1.2.1-1", + "resolved": "https://registry.npmjs.org/@objj/runtime/-/runtime-1.2.1-1.tgz", + "integrity": "sha512-eq1m0TlwPo4AVAklVNXuhi+YrIJysbfdPD+MTZgcEsj452Cct/P3YWCJRfFwvUWmP4UqaJD7iddVJvWrkeZdtg==", "requires": { "@objj/utils": ">=1.0.23", "@xmldom/xmldom": ">=0.7.5", - "objj-transpiler": ">=0.5.6", + "objj-transpiler": "^1.0.0-1", "readline-history": ">=1.2.0", "xmlhttprequest-ssl": "^2.0.0" } @@ -244,14 +397,24 @@ "integrity": "sha512-KzthoKXSs3LcWDWfl27p/rOCoejcxyy/4DgbacjcxiowJJXa+QMmIsjZ/fcg9lcn13jL0gB4c1x1kGPfrrsZPw==" }, "@xmldom/xmldom": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", - "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==" + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.2.tgz", + "integrity": "sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ==" + }, + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==" }, "buffer-from": { "version": "1.1.2", @@ -264,36 +427,37 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "objj-parser": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/objj-parser/-/objj-parser-0.4.3.tgz", - "integrity": "sha512-98qHphDEAP0hfmjFTVacLPiMeOqGYOOazAQczlxqchEGPzzlyVwNnECOOMs2jCY0zQ68TPX/xYKgbsfXpHI6Mg==" + "version": "1.0.0-4", + "resolved": "https://registry.npmjs.org/objj-parser/-/objj-parser-1.0.0-4.tgz", + "integrity": "sha512-W+38550qhkTZOb6MkZBqnBwMX3PPMbVa5n2trTmWHPU4RlNgE+sV0l9CagBzcFVnXD1cmhnmTNLbF5XAg+DRKA==" }, "objj-transpiler": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/objj-transpiler/-/objj-transpiler-0.5.7.tgz", - "integrity": "sha512-9G5NOufdV3997ITROe/HU8RREmr4aEUsW52hJC7vFGQcCQAbJYrnSIYR2187bLAoOKOmW5Uj5lUYK8kdJbqzPQ==", + "version": "1.0.0-3", + "resolved": "https://registry.npmjs.org/objj-transpiler/-/objj-transpiler-1.0.0-3.tgz", + "integrity": "sha512-CGCs64MCNhXeAuWXZx7yT/UDTZO99t1Jxw/Z+Ec+8eYdzOxEsDfV+YRYrwvZ4ZIpM9uX7CuWHLhcJe2PWacX3w==", "requires": { - "objj-parser": ">=0.4.0", + "acorn-walk": "8.2.0", + "objj-parser": "^1.0.0-1", "source-map": "0.4.x" } }, "readline-history": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/readline-history/-/readline-history-1.2.0.tgz", - "integrity": "sha1-9nBUOyzpASFH/pkD+D0cGJwX0zM=" + "integrity": "sha512-8R0Vr9jhdtqYSdWGpAvkEopvuPKjAlYELIKoa7+7FO2CBN/b88rYB9r9gFSNtdCUHdAOJslj0KDG75MsiozXIQ==" }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", "requires": { "amdefine": ">=0.0.4" } }, "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -307,20 +471,14 @@ } }, "terser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", - "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" - } } }, "xmlhttprequest-ssl": { @@ -344,13 +502,13 @@ "integrity": "sha512-T87JtTVJnXcxWdVHchJwrHuQPZLp0mh4MXCOpoMGffKSU2jbL7l+uxK6KPWRMW/ajjQL/aE5dJKguJohmmYtRg==" }, "@objj/runtime": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@objj/runtime/-/runtime-1.1.14.tgz", - "integrity": "sha512-lJy+6ZfV8BLAAwNVffaOzhfBI4FnUmws5BcKHYbsQjQnpp7D7/rrihRUoYY+o8ZtkiK2H1gGcXsqA0J518XWIw==", + "version": "1.2.1-1", + "resolved": "https://registry.npmjs.org/@objj/runtime/-/runtime-1.2.1-1.tgz", + "integrity": "sha512-eq1m0TlwPo4AVAklVNXuhi+YrIJysbfdPD+MTZgcEsj452Cct/P3YWCJRfFwvUWmP4UqaJD7iddVJvWrkeZdtg==", "requires": { "@objj/utils": ">=1.0.23", "@xmldom/xmldom": ">=0.7.5", - "objj-transpiler": ">=0.5.6", + "objj-transpiler": "^1.0.0-1", "readline-history": ">=1.2.0", "xmlhttprequest-ssl": "^2.0.0" } @@ -361,14 +519,24 @@ "integrity": "sha512-KzthoKXSs3LcWDWfl27p/rOCoejcxyy/4DgbacjcxiowJJXa+QMmIsjZ/fcg9lcn13jL0gB4c1x1kGPfrrsZPw==" }, "@xmldom/xmldom": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", - "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==" + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.2.tgz", + "integrity": "sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ==" + }, + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==" }, "buffer-from": { "version": "1.1.2", @@ -381,36 +549,37 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "objj-parser": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/objj-parser/-/objj-parser-0.4.3.tgz", - "integrity": "sha512-98qHphDEAP0hfmjFTVacLPiMeOqGYOOazAQczlxqchEGPzzlyVwNnECOOMs2jCY0zQ68TPX/xYKgbsfXpHI6Mg==" + "version": "1.0.0-4", + "resolved": "https://registry.npmjs.org/objj-parser/-/objj-parser-1.0.0-4.tgz", + "integrity": "sha512-W+38550qhkTZOb6MkZBqnBwMX3PPMbVa5n2trTmWHPU4RlNgE+sV0l9CagBzcFVnXD1cmhnmTNLbF5XAg+DRKA==" }, "objj-transpiler": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/objj-transpiler/-/objj-transpiler-0.5.7.tgz", - "integrity": "sha512-9G5NOufdV3997ITROe/HU8RREmr4aEUsW52hJC7vFGQcCQAbJYrnSIYR2187bLAoOKOmW5Uj5lUYK8kdJbqzPQ==", + "version": "1.0.0-3", + "resolved": "https://registry.npmjs.org/objj-transpiler/-/objj-transpiler-1.0.0-3.tgz", + "integrity": "sha512-CGCs64MCNhXeAuWXZx7yT/UDTZO99t1Jxw/Z+Ec+8eYdzOxEsDfV+YRYrwvZ4ZIpM9uX7CuWHLhcJe2PWacX3w==", "requires": { - "objj-parser": ">=0.4.0", + "acorn-walk": "8.2.0", + "objj-parser": "^1.0.0-1", "source-map": "0.4.x" } }, "readline-history": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/readline-history/-/readline-history-1.2.0.tgz", - "integrity": "sha1-9nBUOyzpASFH/pkD+D0cGJwX0zM=" + "integrity": "sha512-8R0Vr9jhdtqYSdWGpAvkEopvuPKjAlYELIKoa7+7FO2CBN/b88rYB9r9gFSNtdCUHdAOJslj0KDG75MsiozXIQ==" }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", "requires": { "amdefine": ">=0.0.4" } }, "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -424,20 +593,14 @@ } }, "terser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", - "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" - } } }, "xmlhttprequest-ssl": { diff --git a/package.json b/package.json index 12761fd53..d47e2398b 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,15 @@ { "name": "@objj/cappuccino", - "version": "1.2.2", + "version": "1.3.0-2", "devDependencies": { "@objj/cappuccino": "file:." }, "dependencies": { "@objj/jake": "latest", "@objj/ojtest": "latest", - "@objj/runtime": "latest", - "terser": ">=5.7.0" + "@objj/runtime": "^1.2.1-1", + "acorn-walk": "^8.2.0", + "terser": "^5.14.2" }, "files": [ "dist",