package abstrasy.pcfx;
import abstrasy.Heap;
import abstrasy.Interpreter;
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_actor extends PCFx {
public PCFx_actor() {
}
/**
* eval
*
* @param startAt Node
* @return Node
* @throws Exception
* @todo Implémenter cette méthode abstrasy.PCFx
*/
public Node eval(Node startAt) throws Exception {
startAt.isGoodArgsLength(false, 2);
/**
* Formes possibles: (actor {...})
* 0 1 -> toujours la fonction.
*
* (actor {...} [arg0...argN])
* 0 1 2 -> arguments
*
* (actor {...} alias nom)
* 0 1 S-2 S-1
*
* (actor {...} [arg0...argN] alias nom)
* 0 1 2 S-2 S-1
*
* Variantes: (actor 'symbole ...) // since 2012-05-14.
* 0 1 +2 ...
*
* (actor void ...) // since 2012-05-14.
*/
/**
* Premier élément peut être un symbole quoté ou une expression paresseuse...
*/
int i = 1;
Node arg0 = startAt.getSubNode(i++, Node.TYPE_LAZY | Node.TYPE_QSYMBOL | Node.TYPE_PCODE);
/**
* S'agit-il d'un lazy ?
*/
Node symbole = null;
Node functionNode = null;
if (arg0.isLazy())
functionNode = arg0; // si lazy, symbole=null;
else if (arg0.isQSymbol()) {
symbole = arg0; // sinon, assigner symbole, puis chercher lazy...
functionNode = startAt.getSubNode(i++, Node.TYPE_LAZY);
}
else {
if (!arg0.isPCode(PCoder.PC_VOID))
throw new InterpreterException(StdErrors.Syntax_error);
// dans le cas de void, arg0 <- null ; sinon != null...
arg0 = null;
functionNode = startAt.getSubNode(i++, Node.TYPE_LAZY);
}
/**
* on crée ici la liste argv si elle existe:
*/
Node argv = Node.createCList();
if (startAt.size() > i) {
Node snode = startAt.getSubNode(i, Node.TYPE_CLIST | Node.TYPE_PCODE);
if (snode.getQType()==Node.TYPE_CLIST) {
i++;
//for(int j=0;j<snode.size();j++){
// argv.addElement(snode.elementAt(j).deref());
//}
/*
* Par souci de conformité avec les règles du langage, actor ne déréférence pas les
* données transmises en argument.
*
* Comme dans le cas des genérateurs de liste, il peut être nécessaire de déréférencer
* une données dans le cas de l'utilisation de actor. En effet, on ne sait pas exactement
* à quel moment, l'acteur accèdera aux données. Si la données est transférée par référence,
* sa valeur peut être modifiée entre le moment où sa référence est ajoutée aux arguments et
* le moment où elle sera effectivement utilisée par l'acteur.
*
* Le programmeur doit tenir compte de cela lorsqu'il réalise un appel d'acteur avec arguments.
*
*/
argv.appendChildsOf(snode);
}
}
/**
* on récupère le nom du thread s'il existe...
*/
Node nameNode = null;
if (startAt.size() > i) {
startAt.requirePCode(i++, PCoder.PC_ALIAS);
nameNode = startAt.getSubNode(i++, Node.TYPE_STRING);
}
//System.out.println("***"+nameNode);
/**
* s'il y a encore des paramètres, il y a un problème...
*/
if (i < startAt.size()) {
throw new InterpreterException(StdErrors.Syntax_error);
}
Interpreter interpreter = Interpreter.interpr_getNewThreadInterpreter((nameNode == null ? null: nameNode.getString()));
/*
* En clonant functionNode, on évite la nécessité de synchronoser les accès à functionNode...
*/
Node exnode = Node.createClone(functionNode);
exnode.setType(Node.TYPE_EXPR);
interpreter.setNode(exnode);
interpreter.setInterpreterArgs(argv);
interpreter.setOutputTextArea(Interpreter.mySelf().getOutputTextArea());
interpreter.setLogTextArea(Interpreter.mySelf().getLogTextArea());
interpreter.start();
Node id_node = new Node(interpreter.getName());
if (symbole != null) {
// il y a un symbole...
Heap.defv(symbole.getSymbol(), id_node);
// statique...
return null;
}
if (arg0 == null)
// cas void...
return null;
// pas de symbole...
return id_node;
}
}