// Evaluate a list of prose objects into a new list of prose objects. public PNode replaceWithValueAt(PNode evaluateMe, PatternMatcher match) { // If the phrase only serves to delete the pattern... if (value.Length == 0) { // PNode firstNodeAfterPattern = evaluateMe.forwardSeek(match.NumObjectsMatched); PNode firstNodeAfterPattern = match.terminatorNode; if (evaluateMe.prev != null) { evaluateMe.prev.next = firstNodeAfterPattern; } firstNodeAfterPattern.prev = evaluateMe.prev; return(firstNodeAfterPattern); } // Make a node to write and hook it up the previous part of the list. PNode prevWriteHead = evaluateMe.prev; PNode firstNodeInNewList = new PNode(); PNode writeHead = firstNodeInNewList; prevWriteHead.next = writeHead; foreach (ProseObject obj in value) { // Write a value into it // Argrefs get special treatment. if (obj is ArgRefObject) { // Look up the appropriate argument in "evaluate me" and substitute it. int idx = ((ArgRefObject)obj).reffedArgIndex; //ProseObject evaluated = evaluateMe.forwardSeek(index).value; PNode subStart, subEnd; subStart = match.getArgumentBounds(idx, out subEnd); //TODO This needs to support @prose, @text, and @string. //writeHead.value = evaluated; PNode readHead = subStart; //writeHead.initWithPNode(subStart); while (readHead != subEnd) { // Hook p into the output if (prevWriteHead != null) { prevWriteHead.next = writeHead; } writeHead.prev = prevWriteHead; writeHead.initWithPNode(readHead); // Update prevWriteHead = writeHead; readHead = readHead.next; // Get a new node for the next cycle writeHead = new PNode(); } } else { // Hook this node into the list writeHead.prev = prevWriteHead; if (prevWriteHead != null) { prevWriteHead.next = writeHead; } writeHead.value = obj; // Grab a new node prevWriteHead = writeHead; writeHead = new PNode(); } } // When we're done, tie the end of the output list back into the input list. // Note: prevWriteHead is actually the last PNode we wrote. if (prevWriteHead != null) { prevWriteHead.next = match.terminatorNode; //prevWriteHead.next = evaluateMe.forwardSeek(match.NumObjectsMatched); if (match.terminatorNode != null) { match.terminatorNode.prev = prevWriteHead; } } return(firstNodeInNewList); }
// Evaluate a list of prose objects into a new list of prose objects. public PNode replaceWithValueAt(PNode evaluateMe, PatternMatcher match) { // If the phrase only serves to delete the pattern... if (value.Length == 0) { // PNode firstNodeAfterPattern = evaluateMe.forwardSeek(match.NumObjectsMatched); PNode firstNodeAfterPattern = match.terminatorNode; if (evaluateMe.prev != null) evaluateMe.prev.next = firstNodeAfterPattern; firstNodeAfterPattern.prev = evaluateMe.prev; return firstNodeAfterPattern; } // Make a node to write and hook it up the previous part of the list. PNode prevWriteHead = evaluateMe.prev; PNode firstNodeInNewList = new PNode(); PNode writeHead = firstNodeInNewList; prevWriteHead.next = writeHead; foreach (ProseObject obj in value) { // Write a value into it // Argrefs get special treatment. if (obj is ArgRefObject) { // Look up the appropriate argument in "evaluate me" and substitute it. int idx = ((ArgRefObject) obj).reffedArgIndex; //ProseObject evaluated = evaluateMe.forwardSeek(index).value; PNode subStart, subEnd; subStart = match.getArgumentBounds(idx, out subEnd); //TODO This needs to support @prose, @text, and @string. //writeHead.value = evaluated; PNode readHead = subStart; //writeHead.initWithPNode(subStart); while (readHead != subEnd) { // Hook p into the output if (prevWriteHead != null) { prevWriteHead.next = writeHead; } writeHead.prev = prevWriteHead; writeHead.initWithPNode(readHead); // Update prevWriteHead = writeHead; readHead = readHead.next; // Get a new node for the next cycle writeHead = new PNode(); } } else { // Hook this node into the list writeHead.prev = prevWriteHead; if (prevWriteHead != null) prevWriteHead.next = writeHead; writeHead.value = obj; // Grab a new node prevWriteHead = writeHead; writeHead = new PNode(); } } // When we're done, tie the end of the output list back into the input list. // Note: prevWriteHead is actually the last PNode we wrote. if (prevWriteHead != null) { prevWriteHead.next = match.terminatorNode; //prevWriteHead.next = evaluateMe.forwardSeek(match.NumObjectsMatched); if (match.terminatorNode != null) match.terminatorNode.prev = prevWriteHead; } return firstNodeInNewList; }