src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java

Print this page




 296 
 297         final List<Statement> stmts = body.getStatements();
 298         final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
 299         newStatements.addAll(syntheticInitializers);
 300         newStatements.addAll(stmts);
 301         return functionNode.setBody(lc, body.setStatements(lc, newStatements));
 302     }
 303 
 304     /**
 305      * Defines a new symbol in the given block.
 306      *
 307      * @param block        the block in which to define the symbol
 308      * @param name         name of symbol.
 309      * @param origin       origin node
 310      * @param symbolFlags  Symbol flags.
 311      *
 312      * @return Symbol for given name or null for redefinition.
 313      */
 314     private Symbol defineSymbol(final Block block, final String name, final Node origin, final int symbolFlags) {
 315         int    flags  = symbolFlags;
 316         final boolean isBlockScope = (flags & IS_LET) != 0 || (flags & IS_CONST) != 0;
 317         final boolean isGlobal     = (flags & KINDMASK) == IS_GLOBAL;
 318 
 319         Symbol symbol;
 320         final FunctionNode function;
 321         if (isBlockScope) {
 322             // block scoped variables always live in current block, no need to look for existing symbols in parent blocks.
 323             symbol = block.getExistingSymbol(name);
 324             function = lc.getCurrentFunction();
 325         } else {
 326             symbol = findSymbol(block, name);
 327             function = lc.getFunction(block);
 328         }
 329 
 330         // Global variables are implicitly always scope variables too.
 331         if (isGlobal) {
 332             flags |= IS_SCOPE;
 333         }
 334 
 335         if (lc.getCurrentFunction().isProgram()) {
 336             flags |= IS_PROGRAM_LEVEL;
 337         }
 338 
 339         final boolean isParam = (flags & KINDMASK) == IS_PARAM;
 340         final boolean isVar =   (flags & KINDMASK) == IS_VAR;
 341 
 342         if (symbol != null) {
 343             // Symbol was already defined. Check if it needs to be redefined.
 344             if (isParam) {
 345                 if (!isLocal(function, symbol)) {
 346                     // Not defined in this function. Create a new definition.
 347                     symbol = null;
 348                 } else if (symbol.isParam()) {
 349                     // Duplicate parameter. Null return will force an error.
 350                     throw new AssertionError("duplicate parameter");
 351                 }
 352             } else if (isVar) {
 353                 if (isBlockScope) {
 354                     // Check redeclaration in same block
 355                     if (symbol.hasBeenDeclared()) {
 356                         throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
 357                     } else {
 358                         symbol.setHasBeenDeclared();




 359                     }
 360                 } else if ((flags & IS_INTERNAL) != 0) {
 361                     // Always create a new definition.
 362                     symbol = null;
 363                 } else {
 364                     // Found LET or CONST in parent scope of same function - s SyntaxError
 365                     if (symbol.isBlockScoped() && isLocal(lc.getCurrentFunction(), symbol)) {
 366                         throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
 367                     }
 368                     // Not defined in this function. Create a new definition.
 369                     if (!isLocal(function, symbol) || symbol.less(IS_VAR)) {
 370                         symbol = null;
 371                     }
 372                 }
 373             }
 374         }
 375 
 376         if (symbol == null) {
 377             // If not found, then create a new one.
 378             final Block symbolBlock;
 379 
 380             // Determine where to create it.
 381             if (isVar && ((flags & IS_INTERNAL) != 0 || isBlockScope)) {
 382                 symbolBlock = block; //internal vars are always defined in the block closest to them
 383             } else if (isGlobal) {
 384                 symbolBlock = lc.getOutermostFunction().getBody();
 385             } else {
 386                 symbolBlock = lc.getFunctionBody(function);
 387             }
 388 
 389             // Create and add to appropriate block.
 390             symbol = createSymbol(name, flags);
 391             symbolBlock.putSymbol(lc, symbol);
 392 
 393             if ((flags & IS_SCOPE) == 0) {
 394                 // Initial assumption; symbol can lose its slot later
 395                 symbol.setNeedsSlot(true);
 396             }
 397         } else if (symbol.less(flags)) {
 398             symbol.setFlags(flags);
 399         }
 400 
 401         return symbol;


 523         // body of the declared function for self-reference.
 524         if (varNode.isFunctionDeclaration()) {
 525             defineVarIdent(varNode);
 526         }
 527         return true;
 528     }
 529 
 530     @Override
 531     public Node leaveVarNode(final VarNode varNode) {
 532         if (!varNode.isFunctionDeclaration()) {
 533             defineVarIdent(varNode);
 534         }
 535         return super.leaveVarNode(varNode);
 536     }
 537 
 538     private void defineVarIdent(final VarNode varNode) {
 539         final IdentNode ident = varNode.getName();
 540         final int flags;
 541         if (varNode.isAnonymousFunctionDeclaration()) {
 542             flags = IS_INTERNAL;
 543         } else if (lc.getCurrentFunction().isProgram()) {
 544             flags = IS_SCOPE;
 545         } else {
 546             flags = 0;
 547         }
 548         defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | flags);
 549     }
 550 
 551     private Symbol exceptionSymbol() {
 552         return newObjectInternal(EXCEPTION_PREFIX);
 553     }
 554 
 555     /**
 556      * This has to run before fix assignment types, store any type specializations for
 557      * parameters, then turn them into objects for the generic version of this method.
 558      *
 559      * @param functionNode functionNode
 560      */
 561     private FunctionNode finalizeParameters(final FunctionNode functionNode) {
 562         final List<IdentNode> newParams = new ArrayList<>();
 563         final boolean isVarArg = functionNode.isVarArg();




 296 
 297         final List<Statement> stmts = body.getStatements();
 298         final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
 299         newStatements.addAll(syntheticInitializers);
 300         newStatements.addAll(stmts);
 301         return functionNode.setBody(lc, body.setStatements(lc, newStatements));
 302     }
 303 
 304     /**
 305      * Defines a new symbol in the given block.
 306      *
 307      * @param block        the block in which to define the symbol
 308      * @param name         name of symbol.
 309      * @param origin       origin node
 310      * @param symbolFlags  Symbol flags.
 311      *
 312      * @return Symbol for given name or null for redefinition.
 313      */
 314     private Symbol defineSymbol(final Block block, final String name, final Node origin, final int symbolFlags) {
 315         int    flags  = symbolFlags;
 316         final boolean isLexicalScope = (flags & IS_LET) != 0 || (flags & IS_CONST) != 0;
 317         final boolean isGlobal     = (flags & KINDMASK) == IS_GLOBAL;
 318 
 319         Symbol symbol;
 320         final FunctionNode function;
 321         if (isLexicalScope) {
 322             // lexically scoped variables always live in current block, no need to look for existing symbols in parent blocks.
 323             symbol = block.getExistingSymbol(name);
 324             function = lc.getCurrentFunction();
 325         } else {
 326             symbol = findSymbol(block, name);
 327             function = lc.getFunction(block);
 328         }
 329 
 330         // Global variables are implicitly always scope variables too.
 331         if (isGlobal) {
 332             flags |= IS_SCOPE;
 333         }
 334 
 335         if (lc.getCurrentFunction().isProgram()) {
 336             flags |= IS_PROGRAM_LEVEL;
 337         }
 338 
 339         final boolean isParam = (flags & KINDMASK) == IS_PARAM;
 340         final boolean isVar =   (flags & KINDMASK) == IS_VAR;
 341 
 342         if (symbol != null) {
 343             // Symbol was already defined. Check if it needs to be redefined.
 344             if (isParam) {
 345                 if (!isLocal(function, symbol)) {
 346                     // Not defined in this function. Create a new definition.
 347                     symbol = null;
 348                 } else if (symbol.isParam()) {
 349                     // Duplicate parameter. Null return will force an error.
 350                     throw new AssertionError("duplicate parameter");
 351                 }
 352             } else if (isVar) {
 353                 if (isLexicalScope) {
 354                     // Check redeclaration in same block
 355                     if (symbol.hasBeenDeclared()) {
 356                         throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
 357                     } else {
 358                         symbol.setHasBeenDeclared();
 359                         // Set scope flag on top-level lexical symbols
 360                         if (function.isProgram() && function.getBody() == block) {
 361                             symbol.setIsScope();
 362                         }
 363                     }
 364                 } else if ((flags & IS_INTERNAL) != 0) {
 365                     // Always create a new definition.
 366                     symbol = null;
 367                 } else {
 368                     // Found LET or CONST in parent scope of same function - s SyntaxError
 369                     if (symbol.isBlockScoped() && isLocal(lc.getCurrentFunction(), symbol)) {
 370                         throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
 371                     }
 372                     // Not defined in this function. Create a new definition.
 373                     if (!isLocal(function, symbol) || symbol.less(IS_VAR)) {
 374                         symbol = null;
 375                     }
 376                 }
 377             }
 378         }
 379 
 380         if (symbol == null) {
 381             // If not found, then create a new one.
 382             final Block symbolBlock;
 383 
 384             // Determine where to create it.
 385             if (isVar && ((flags & IS_INTERNAL) != 0 || isLexicalScope)) {
 386                 symbolBlock = block; //internal vars are always defined in the block closest to them
 387             } else if (isGlobal) {
 388                 symbolBlock = lc.getOutermostFunction().getBody();
 389             } else {
 390                 symbolBlock = lc.getFunctionBody(function);
 391             }
 392 
 393             // Create and add to appropriate block.
 394             symbol = createSymbol(name, flags);
 395             symbolBlock.putSymbol(lc, symbol);
 396 
 397             if ((flags & IS_SCOPE) == 0) {
 398                 // Initial assumption; symbol can lose its slot later
 399                 symbol.setNeedsSlot(true);
 400             }
 401         } else if (symbol.less(flags)) {
 402             symbol.setFlags(flags);
 403         }
 404 
 405         return symbol;


 527         // body of the declared function for self-reference.
 528         if (varNode.isFunctionDeclaration()) {
 529             defineVarIdent(varNode);
 530         }
 531         return true;
 532     }
 533 
 534     @Override
 535     public Node leaveVarNode(final VarNode varNode) {
 536         if (!varNode.isFunctionDeclaration()) {
 537             defineVarIdent(varNode);
 538         }
 539         return super.leaveVarNode(varNode);
 540     }
 541 
 542     private void defineVarIdent(final VarNode varNode) {
 543         final IdentNode ident = varNode.getName();
 544         final int flags;
 545         if (varNode.isAnonymousFunctionDeclaration()) {
 546             flags = IS_INTERNAL;
 547         } else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
 548             flags = IS_SCOPE;
 549         } else {
 550             flags = 0;
 551         }
 552         defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | flags);
 553     }
 554 
 555     private Symbol exceptionSymbol() {
 556         return newObjectInternal(EXCEPTION_PREFIX);
 557     }
 558 
 559     /**
 560      * This has to run before fix assignment types, store any type specializations for
 561      * parameters, then turn them into objects for the generic version of this method.
 562      *
 563      * @param functionNode functionNode
 564      */
 565     private FunctionNode finalizeParameters(final FunctionNode functionNode) {
 566         final List<IdentNode> newParams = new ArrayList<>();
 567         final boolean isVarArg = functionNode.isVarArg();