# BEGIN LICENSE BLOCK # Version: CMPL 1.1 # # The contents of this file are subject to the Cisco-style Mozilla Public # License Version 1.1 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License # at www.eclipse-clp.org/license. # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. # # The Original Code is The ECLiPSe Constraint Logic Programming System. # The Initial Developer of the Original Code is Cisco Systems, Inc. # Portions created by the Initial Developer are # Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. # # Contributor(s): # # END LICENSE BLOCK Destructive assignment ---------------------- Date: 2002-06-27 Author: Joachim The builtin setarg/3 and several other destructive assignment operations use the single C function ec_assign(pword *arg, value v, tag t) which backtrackably overwrites the location arg with the new value v/t. The code uses the macros NewLocation(pword*) which means the address is younger than the most recent choicepoint NewValue(value,tag) which means the pword is younger than the most recent choicepoint (when it is a constant, it is assumed to be old) There are the following different cases. Assume the location to be assigned to is Arg, its old value Old and its new value New. 1. Simply overwrite without trailing, regardless of old or new value: ^ | Arg NewLocation(Arg) | -chp- | --- 2. Simply overwrite without trailing: ^ | New NewValue(New) | Old NewValue(Old) | -chp- | Arg !NewLocation(Arg) | --- 3. overwrite with trailing: ^ | New NewValue(New) | -chp- | Old !NewValue(Old) | Arg !NewLocation(Arg) | --- 4. Copy new value to top of stack, and assign a reference to it, instead of the new value itself (like 2) ^ | Old NewValue(Old) | -chp- | New !NewValue(New) | Arg !NewLocation(Arg) | --- This is done so that the next time an assignment is attempted, the (then old) value's address indicates how old the assignment is, and trailing can hopefully be avoided. This trick avoids the need for an explicit timestamp. 5. Copy new value to top of stack, and assign a reference to it, instead of the new value itself (like 3) ^ | -chp- | New !NewValue(New) | Old !NewValue(Old) | Arg !NewLocation(Arg) | --- See comment above. The actual ec_assign() function also checks for the New value being a variable on the local stack. Since references from global to local are not allowed, the variable gets first globalised and the result is assigned instead (leading then to case 1, 2 or 3).