package abstrasy.pcfx;
import abstrasy.ASymbol;
import abstrasy.Heap;
import abstrasy.Node;
import abstrasy.PCoder;
import abstrasy.interpreter.InterpreterException;
import abstrasy.interpreter.StdErrors;
/**
* 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_label extends PCFx {
public PCFx_label() {
}
/**
* eval
*
* @param startAt Node
* @return Node
* @throws Exception
* @todo Implémenter cette méthode abstrasy.PCFx
*/
public Node eval(Node startAt) throws Exception {
/**
* formes: (label 'symbole) -> NOTHING
* (label 'symbole valuable) -> valuable
*/
/**
* Vérification élémentaire de la syntaxe
*/
startAt.isGoodArgsCnt(2, 3);
/**
* début du traitement
*/
ASymbol symbole_n = startAt.getSubNode(1, Node.TYPE_QSYMBOL).getSymbol();
//dépréciation 2012-05-31 : Node register = null;
if (symbole_n.getStr().charAt(0) == PCoder.REG) {
if (symbole_n.getStr().indexOf(PCoder.SEP) < 0) {
// seul les espace de nom sont acceptables...
throw new InterpreterException(StdErrors.Illegal_access_to_register);
}
}
//System.out.println("DEF:"+snode);
if (startAt.size() == 2) {
Node tmpn = Node.createNothing();
Heap.defv(symbole_n, tmpn);
return Node.createRef(tmpn);
}
else {
// il y a une valeur d'affectation...
Node rnode = startAt.getSubNode(2, Node.VTYPE_VALUABLE);
/**
* Etablissement du code de conditions pour (define 't s) :
* 1 : s est final.
* 2 : s est un symbole.
* 4 : t est immutable.
*
* Remarque: Au niveau du Heap, si le symbole recherché est immutable,
* un .newRef() .setImmutable() est tjrs réalisé d'office.
*
* D'où la table de vérités en considérant que t est toujours un symbole:
*
* code | t=immutable | s=symbole | s=final | opération
* -----+-------------+-----------+---------+----------
* 7 | 1 | 1 | 1 | Référence
* 6 | 1 | 1 | 0 | Clonage
* 5 | 1 | 0 | 1 | Référence
* 4 | 1 | 0 | 0 | Référence
* 3 | 0 | 1 | 1 | Clonage
* 2 | 0 | 1 | 0 | Référence
* 1 | 0 | 0 | 1 | Clonage
* 0 | 0 | 0 | 0 | // dépréciationnewRef (16/12/20010)
*
*/
boolean isImmutable=symbole_n.isImmutable();
int code = (isImmutable ? 4: 0) + (startAt.isNodeType(2, Node.TYPE_SYMBOL) ? 2: 0) + (rnode.isFinalNode() ? 1: 0);
//dépréciation 2012-05-31 : register=Heap.createUseOnceRegisterGlobalSymbol(isImmutable);
/**
* Dispatching des fonctionnalités selon le code:
* - Référence : 7, 2, 5, 4
* - Clonage : 6, 3 ,1
* dépréciation de deRef : 0
*/
switch (code) {
/* case 0:{
Node drf=rnode.deref();
Heap.setv(snode.value, drf);
Heap.setv(register.value, drf);
break;
}
*/
case 6: case 4: case 3: case 1:{
Node tmpn=Node.createClone(rnode);
if(isImmutable){
/**
* si le symbole est immutable, transposer la finalité à tous les fils.
*/
Node.allFinal(tmpn);
}
else if(tmpn.isFinalNode()) {
/**
* si la valeur est finale, un symbole immutable est requis...
*/
throw new InterpreterException(StdErrors.Immutable_symbol_required);
}
Heap.defv(symbole_n, tmpn);
/*
* Heap.defv(register.getString(), tmpn);
*
* Dépréciation : Il suffit de retourner directement le contenant de la donnée.
* ------------- Ceci constitue une optimisation puisqu'elle évite 2 étapes:
* 1) la création d'un symbole à lecture destructive
* 2) sa lecture et sa destruction.
*
* l.bruninx, 2012-05-31.
*
*/
return Node.createRef(tmpn);
}
default:{
Heap.defv(symbole_n, rnode);
// dépréciation : Heap.defv(register.getString(), rnode);
// l.bruninx, 2012-05-31.
return Node.createRef(rnode);
}
}
}
}
}