package abstrasy.pcfx;
import abstrasy.Node;
/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
* http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/
public class PCFx_set_static extends PCFx {
public PCFx_set_static() {
}
protected Node eval_(Node startAt) throws Exception {
/**
* formes: (set! node) : place NOTHING... -> result
* (set! node valuable) -> result
*/
if (startAt.size() == 2) {
/**
* forme (set! node)
*/
/**
* recherche du Node au travers d'un symbole
*/
startAt.requireNodeType(1, Node.VTYPE_INDIRECTION);
Node snode = startAt.getSubNode(1,Node.VTYPE_VALUABLE);
/**
* Si la variable est finale, on ne peut pas la redéfinir...
*/
snode.requireAccessType(Node.ACCESSVTYPE_MUTABLE_WRITELOCK);
snode.setNothing();
return snode;
}
else {
/**
* forme (set! node valeur)
*/
startAt.isGoodArgsCnt(3);
/**
* recherche du Node au travers d'un symbole
*/
startAt.requireNodeType(1, Node.VTYPE_INDIRECTION);
Node snode = startAt.getSubNode(1,Node.VTYPE_VALUABLE);
/**
* Si la variable est finale, on ne peut pas la redéfinir...
*/
snode.requireAccessType(Node.ACCESSVTYPE_MUTABLE_WRITELOCK);
/**
* Créer le cast des types possibles...
*/
long cast = snode.getQType() | Node.TYPE_NOTHING;
if (snode.getQType()==Node.TYPE_NOTHING) {
cast = Node.VTYPE_VALUABLE;
}
//boolean isSymbol = startAt.isNodeType(2, Node.TYPE_SYMBOL);
Node bnode = startAt.getSubNode(2, cast);
//System.out.println("bnode-final:"+bnode.isFinalNode());
/**
* La table de vérité de set! n'a besoin que de valider la finalité de la donnée à affecter.
* Les autres paramètres n'influencent pas le choix entre le clonage et la liaison.
*
* En effet, si l'on considère (set! t s):
*
* t: ne peut être qu'un symbole non immutable
* s: peut être un symbole ou non
* s: peut être final ou non
*
* On doit aussi tenir compte que Heap.getv(immutable), implique
* un deref().setImmuatable() (sans changer le node affecté d'origine).
* Par ailleurs, set! utilise derefTo(Ns->Nt), Nt n'est donc pas remplacé,
* ces référnces sont simplements redirigées.
*
* Ainsi, la table de vérités:
*
* code | s=symbole | s=final | opération
* -----+-----------+---------+----------
* 3 | 1 | 1 | Clonage
* 2 | 1 | 0 | Ref
* 1 | 0 | 1 | Clonage
* 0 | 0 | 0 | Ref
*
* Il n'y a donc qu'une opération (Clonage) qui dépend de s=final.
*
*/
if(bnode.isFinalNode()){
bnode=Node.createClone(bnode);
}
bnode.derefTo(snode);
return bnode;
}
}
public Node eval(Node startAt) throws Exception {
/**
* formes: (set! node) : place NOTHING...
* (set! node valuable)
*/
eval_(startAt);
return null;
}
}