package abstrasy.pcfx;
import abstrasy.Heap;
import abstrasy.Node;
import abstrasy.PCoder;
import abstrasy.ASymbol;
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_define extends PCFx {
public PCFx_define() {
}
/**
* eval
*
* @param startAt Node
* @return Node
* @throws Exception
* @todo Implémenter cette méthode abstrasy.PCFx
*/
public Node eval(Node startAt) throws Exception {
/**
* formes: (define 'symbole)
* (define 'symbole 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();
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) {
Heap.defv(symbole_n, Node.createNothing());
}
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 | Clonage
* 3 | 0 | 1 | 1 | Clonage
* 2 | 0 | 1 | 0 | Référence
* 1 | 0 | 0 | 1 | Clonage
* 0 | 0 | 0 | 0 | référence // dépréciation de DeRef (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);
//if(snode.value.equals("rxx")) System.out.println("Define "+snode.value+" "+(rnode.isFinalNode() ? "FINAL":""));
/**
* Dispatching des fonctionnalités selon le code:
* - Référence : 7, 2, 5,0
* - Clonage : 6, 3 ,1, 4
* dépréciation de deRef : 0
*/
switch (code) {
//case 0: Heap.setv(snode.value, rnode.deref());
// 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);
break;
}
default: Heap.defv(symbole_n, rnode);
}
}
return null;
}
}