public void GenerateCodeFromClause(PrologCodeClause clause, ArrayList instructions)
{
/* Do we need to allocate an environment? */
bool hasEnvironment = clause.Goals.Count > 1;
/* Initialize variable dictionary */
_dictionary = new PrologVariableDictionary();
/* Build the variable dictionary for this clause */
_dictionary.Build(clause);
/* Free all registers */
PrologRegisterTable registers = PrologRegisterTable.Instance;
registers.FreeAllRegisters();
/* Prepare head variables for code generation */
int reg = 0;
if (clause.Head.Arity > 0)
{
headArity = clause.Head.Arity;
foreach (PrologCodeTerm argument in clause.Head.Arguments)
{
if (argument is PrologCodeVariable)
{
PrologCodeVariable var = (PrologCodeVariable)argument;
PrologVariableDictionaryEntry entry = _dictionary.GetVariable(var.Name);
if (entry != null)
{
if (entry.IsTemporary && entry.TemporaryIndex == -1)
{
entry.IsReferenced = true;
_dictionary.AllocateTemporaryVariable(entry, reg);
}
}
//BUG: reg++;
}
reg++;
}
}
/* Prepare first goal variables */
int xreg = 0;
PrologCodeTerm fg = null;
if (clause.Goals.Count > 0)
{
fg = (PrologCodeTerm)clause.Goals[0];
}
if (fg is PrologCodePredicate)
{
PrologCodePredicate firstGoal = (PrologCodePredicate)fg;
if (firstGoal.Name == "!")
{
hasEnvironment = true;
}
if (firstGoal.Arity > 0)
{
foreach (PrologCodeTerm variable in firstGoal.Arguments)
{
if (variable is PrologCodeVariable)
{
PrologVariableDictionaryEntry entry = _dictionary.GetVariable(((PrologCodeVariable)variable).Name);
if (entry != null)
{
if (entry.IsTemporary && entry.TemporaryIndex == -1)
{
if (!registers.InUse(xreg))
{
_dictionary.AllocateTemporaryVariable(entry, xreg);
}
}
}
}
xreg++;
}
}
}
/* Reserve required registers */
for (int i = 0; i < Math.Max(reg, xreg); i++)
{
registers.AllocateRegister(i);
}
/* Emit predicate label */
_generator.DeclareProcedure(clause.Head.Name, clause.Head.Arity);
/* Allocate an environment if needed */
if (hasEnvironment)
{
_generator.Emit(OpCodes.Allocate);
}
/* Compile clause head */
CompileClauseHead(clause.Head, instructions);
/* Set current goal to 1 */
_dictionary.CurrentGoalIndex = 1;
if (clause.Goals.Count == 0)
{
_generator.EndProcedure();
/* Reset variable dictionary */
_dictionary.Reset();
instructions = _generator.Instructions;
return;
}
/* Compile first goal */
CompileGoal(fg, instructions);
_dictionary.CurrentGoalIndex++;
/* Compile the rest of the goals */
for (int goalIndex = 1; goalIndex < clause.Goals.Count; goalIndex++)
{
PrologCodeTerm goal = (PrologCodeTerm)clause.Goals[goalIndex];
InitializeGoalTemporaryVariables(goal);
/* reserve registers */
for (int i = 0; i < reg; i++)
{
registers.AllocateRegister(i);
}
/* Clear temporary index of permanent variables */
_dictionary.ClearTempIndexOfPermanentVariables();
/* Compile goal */
CompileGoal(goal, instructions);
/* Advance to next goal */
_dictionary.CurrentGoalIndex += 1;
}
/* Reset instruction set, code pointer, and variable
* dictionary.
*/
_dictionary.Reset();
}