/** * create a CAstNode l representing a loop that traverses the prototype chain from receiver * searching for the constant property element. update nodeMap to map root to an expression that * reads the property from the right node. * * @param root * @param receiver * @param element * @param context * @param nodeMap * @return */ private CAstNode makeConstRead( CAstNode root, CAstNode receiver, CAstNode element, RewriteContext context, Map<Pair<CAstNode, ExpanderKey>, CAstNode> nodeMap) { CAstNode get, result; String receiverTemp = TEMP_NAME + (readTempCounter++); String elt = (String) element.getValue(); if (elt.equals("prototype") || elt.equals("__proto__")) { result = Ast.makeNode( CAstNode.BLOCK_EXPR, get = Ast.makeNode(CAstNode.OBJECT_REF, receiver, Ast.makeConstant(elt))); } else { if (context.inAssignment()) { context.setAssign( Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeConstant(elt)); } result = Ast.makeNode( CAstNode.BLOCK_EXPR, // declare loop variable and initialize to the receiver Ast.makeNode( CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(receiverTemp, false, false)), receiver), Ast.makeNode( CAstNode.LOOP, // while the desired property of the loop variable is not // defined... Ast.makeNode( CAstNode.UNARY_EXPR, CAstOperator.OP_NOT, Ast.makeNode( CAstNode.IS_DEFINED_EXPR, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeConstant(elt))), // set the loop variable to be its prototype Ast.makeNode( CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeNode( CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeConstant("__proto__")))), get = Ast.makeNode( CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeConstant(elt))); } nodeMap.put(Pair.make(root, context.key()), result); nodeMap.put(Pair.make(root, ExpanderKey.EXTRA), get); return result; }
/** * similar to makeConstRead(), but desired property is some expression instead of a constant * * @see #makeConstRead(CAstNode, CAstNode, CAstNode, RewriteContext, Map) */ private CAstNode makeVarRead( CAstNode root, CAstNode receiver, CAstNode element, RewriteContext context, Map<Pair<CAstNode, ExpanderKey>, CAstNode> nodeMap) { String receiverTemp = TEMP_NAME + (readTempCounter++); String elementTemp = TEMP_NAME + (readTempCounter++); if (context.inAssignment()) { context.setAssign( Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeNode(CAstNode.VAR, Ast.makeConstant(elementTemp))); } CAstNode get; CAstNode result = Ast.makeNode( CAstNode.BLOCK_EXPR, Ast.makeNode( CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(receiverTemp, false, false)), receiver), Ast.makeNode( CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(elementTemp, false, false)), element), Ast.makeNode( CAstNode.LOOP, Ast.makeNode( CAstNode.UNARY_EXPR, CAstOperator.OP_NOT, Ast.makeNode( CAstNode.IS_DEFINED_EXPR, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeNode(CAstNode.VAR, Ast.makeConstant(elementTemp)))), Ast.makeNode( CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeNode( CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeConstant("__proto__")))), get = Ast.makeNode( CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(receiverTemp)), Ast.makeNode(CAstNode.VAR, Ast.makeConstant(elementTemp)))); nodeMap.put(Pair.make(root, context.key()), get); return result; }