# 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).

