package code.instr;

import code.space.Computation;
import code.space.Space;
import code.stuff.Logger;
import code.stuff.Tracer;
import code.symbols.DataSymbol;
import code.table.MapTable;
import code.table.ModuleTable;
import code.term.Term;
import code.term.TermImpl;

/**
 * Construct a term from a (root) symbol and a bunch of arguments. The
 * arguments are popped from the pre-term stack (where they were pushed in
 * reverse order). The number of arguments is the arity of the root symbol.
 *
 * It would be nice to compute the arity only once.  However, the
 * arity is not available at the time a MakeTerm instruction is 
 * constructed.  The compiler could include it in the byte code.
 * Or, one could consider a pass on the instructions after all 
 * the modules have been loaded. 
 *
 * @author Sergio Antoy
 * @since June 17, 2003
 */

public class MakeTerm implements Instruction {
    private final int root;

    public MakeTerm(String moduleName, String symbolName) {
	this.root = ModuleTable.getId(moduleName, symbolName);
    }

    public void execute(Computation computation) {
	DataSymbol s = MapTable.getSymbol(root);
        byte arity = s.arity;
        Term[] argument = new Term[arity];
        for (int i = 0; i < arity; i++)
            argument[i] = (Term) Space.instance.preTerm.pop();
        Term term = new Term(root, argument);
        Space.instance.preTerm.push(term);
        if (Tracer.instruction) {
	    Logger.logln(computation.getIdString() + ": MakeTerm: " + term);
	    /*  Longer version
            Logger.log(computation.getIdString() + ": MakeTerm: "
		       + s.symbolName);
	    if (arity > 0) {
		Logger.log(" with ");
		for (int i = 0; i < arity; i++)
		    Logger.log(argument[i].toString() + ",");
	    }
	    Logger.logln(" gives " + term);
	    */
        }
    }

    public String printAsTxtLoadable() {
        DataSymbol symbol = MapTable.getSymbol(root);
        return "MakeTerm \"" + symbol.symbolName + 
	    "\" \"" + symbol.moduleName + "\"";
    }

}
