package abstrasy.pcfx;
import abstrasy.ASymbol;
import abstrasy.Heap;
import abstrasy.Node;
import abstrasy.PCoder;
import abstrasy.SELF;
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_namespace extends PCFx {
public PCFx_namespace() {
}
public Node eval(Node startAt) throws Exception {
/**
* forme : (object <final> 'symbol { ... }/vobj)
* (object <final> {...}/vobj ->
* (object <final>) ->
* (object <final>'symbol)
* 0 +1 2
*/
boolean forceFinal = startAt.elementAt(1).getSymbolicValue().isPCode(PCoder.PC_FINAL);
int offset=forceFinal ? 1:0;
/**
* vérification élémentaire
*/
ASymbol symbol = null;
Node fn = null;
switch (startAt.size()-offset) {
case 3:
{
symbol = startAt.getSubNode(1+offset, Node.TYPE_QSYMBOL).getSymbol();
fn = startAt.getSubNode(2+offset, Node.TYPE_LAZY | Node.TYPE_NAMESPACE);
break;
}
case 2:
{
fn = startAt.getSubNode(1+offset, Node.TYPE_LAZY | Node.TYPE_NAMESPACE | Node.TYPE_QSYMBOL);
if (fn.isQSymbol()) {
symbol = fn.getSymbol();
fn = null;
}
break;
}
case 1:
{
break;
}
default:
{
throw new InterpreterException(StdErrors.Argument_count_mismatch);
}
}
Node moduleNode;
if (fn == null) {
/**
* forme (object)
*/
Heap heap = new Heap();
moduleNode = new Node(heap);
moduleNode.setType(Node.TYPE_NAMESPACE);
moduleNode.setFinalNode(false);
if (symbol != null) {
/**
* forme (object 'symbol)
*/
if(forceFinal && !symbol.isImmutable()){
throw new InterpreterException(StdErrors.Immutable_symbol_required);
}
else{
Heap.defv(symbol, moduleNode.letFinal(symbol.isImmutable()));
}
}
}
else if (fn.isNamespace()) {
/**
* fn est vObject...
*/
if (symbol != null) {
/**
* Attention, il faut respecter la finalité...
*
* objet | symbol | # | Op.
* final | final | |
* ------+--------+---+------
* 0 | 0 | 0 | deref
* 0 | 1 | 1 | clone
* 1 | 0 | 2 | clone
* 1 | 1 | 3 | deref
*
*/
int code = (fn.isFinalNode() ? 2: 0) + (symbol.isImmutable() ? 1: 0);
switch (code) {
case 0:
case 3:{
Heap heap = new Heap((Heap)fn.getExternal());
moduleNode = new Node(heap);
moduleNode.setType(Node.TYPE_NAMESPACE);
moduleNode.setFinalNode(false);
break;
}
default:
moduleNode = Node.createClone(fn);
}
if(forceFinal && !symbol.isImmutable()){
throw new InterpreterException(StdErrors.Immutable_symbol_required);
}
else{
Heap.defv(symbol, moduleNode.letFinal(symbol.isImmutable()));
}
}
else {
/**
* pas de symbole...
* On clone d'office...
*/
moduleNode = Node.createClone(fn);
}
}
else {
/**
* fn est lazy...
*/
Heap heap = new Heap();
moduleNode = new Node(heap);
moduleNode.setType(Node.TYPE_NAMESPACE);
moduleNode.setFinalNode(false);
if (symbol != null) {
if(forceFinal && !symbol.isImmutable()){
throw new InterpreterException(StdErrors.Immutable_symbol_required);
}
else{
Heap.defv(symbol, moduleNode.letFinal(symbol.isImmutable()));
}
}
Heap.push();
Node old_self = SELF.swap(moduleNode);
Node tmpn = fn.exec(true);
if (tmpn != null) {
throw new InterpreterException(StdErrors.extend(StdErrors.Void_return_results, tmpn.toString()));
}
SELF.restore(old_self);
Heap.pull();
}
return (symbol != null ? null: moduleNode.letFinal(forceFinal));
}
}