/* Initialize temporary goal variables in the dictionary */
        private void InitializeGoalTemporaryVariables(PrologCodeTerm goal)
        {
            /* Free all registers */
            PrologRegisterTable.Instance.FreeAllRegisters();

            int reg = 0;

            if (goal is PrologCodePredicate)
            {
                PrologCodePredicate g = (PrologCodePredicate)goal;

                if (g.Arity > 0)
                {
                    foreach (PrologCodeTerm var in g.Arguments)
                    {
                        if (var is PrologCodeVariable)
                        {
                            PrologVariableDictionaryEntry entry = _dictionary.GetVariable(((PrologCodeVariable)var).Name);
                            if (entry != null)
                            {
                                if (entry.IsTemporary && entry.TemporaryIndex == -1)
                                {
                                    _dictionary.AllocateTemporaryVariable(entry, reg);
                                }
                            }
                            reg++;
                        }
                    }
                }
            }
        }
        public void Add(object key, object val)
        {
            string name = (string)key;


            if (this.Contains(key))
            {
                PrologVariableDictionaryEntry entry = GetEntry((string)key);
                entry.Occurrences     += 1;
                entry.LastGoal         = _currentGoalIndex;
                entry.LastGoalArgument = _currentArgumentIndex;
            }
            else
            {
                PrologVariableDictionaryEntry variable = new PrologVariableDictionaryEntry(name, -1);
                variable.Occurrences      = 0;
                variable.FirstGoal        = _currentGoalIndex;
                variable.IsReferenced     = false;
                variable.IsGlobal         = false;
                variable.Occurrences     += 1;
                variable.LastGoal         = _currentGoalIndex;
                variable.LastGoalArgument = _currentArgumentIndex;
                variable.IsReferenced     = false;
                _items.Add(variable);
            }
        }
        private bool ResolveConflicts(PrologCodeTerm term, int index)
        {
            PrologVariableDictionaryEntry entry = _dictionary.GetVariable(index);

            if (_dictionary.CurrentGoalIndex != 1 || entry == null || entry.LastGoalArgument < index)
            {
                PrologRegisterTable.Instance.AllocateRegister(index);
                return(false);
            }
            if (term is PrologCodePredicate)
            {
                PrologCodePredicate predicate = (PrologCodePredicate)term;
                for (int i = index + 1; i < entry.LastGoalArgument; i++)
                {
                    if (predicate.Name == entry.Name &&
                        (_dictionary.GetVariable(i) == null || ResolveConflicts(term, i)))
                    {
                        entry.TemporaryIndex = i;
                        _generator.Emit(OpCodes.Put_Value, X(index), X(i));
                        return(true);
                    }
                }
                // I WAS HERE
            }
            //return true; THIS WAS THERE
            entry.TemporaryIndex = PrologRegisterTable.Instance.FindRegister();
            _generator.Emit(OpCodes.Put_Value, X(index), X(entry.TemporaryIndex));
            return(true);
        }
        public void Remove(object key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            string name = (string)key;

            for (int i = 0; i < _items.Count; i++)
            {
                PrologVariableDictionaryEntry entry = (PrologVariableDictionaryEntry)_items[i];
                if (entry.Name == name)
                {
                    _items.RemoveAt(i);
                    return;
                }
            }
        }
 public void AllocatePermanentVariable(PrologVariableDictionaryEntry entry, int reg)
 {
     entry.PermanentIndex = reg;
 }
 public void AllocateTemporaryVariable(PrologVariableDictionaryEntry entry, int reg)
 {
     _registers.AllocateRegister(reg);
     entry.TemporaryIndex = reg;
 }
        private void CompileGoalRecordVariable(PrologCodeVariable var)
        {
            PrologVariableDictionaryEntry entry = _dictionary.GetVariable(var.Name);

            if (entry.IsReferenced)
            {
                /* Compile build value here ... */
                if (entry.IsTemporary)
                {
                    if (entry.IsGlobal)
                    {
                        _generator.Emit(OpCodes.Set_Value, X(entry.TemporaryIndex));
                    }
                    else
                    {
                        _generator.Emit(OpCodes.Set_Local_Value, X(entry.TemporaryIndex));
                        entry.IsGlobal = true;
                    }
                }
                else
                {
                    if (entry.IsGlobal)
                    {
                        if (entry.TemporaryIndex != -1)
                        {
                            _generator.Emit(OpCodes.Set_Value, X(entry.TemporaryIndex));
                        }
                        else
                        {
                            _generator.Emit(OpCodes.Set_Value, Y(entry.PermanentIndex));
                        }
                    }
                    else
                    {
                        if (entry.TemporaryIndex != -1)
                        {
                            _generator.Emit(OpCodes.Set_Local_Value, X(entry.TemporaryIndex));
                        }
                        else
                        {
                            _generator.Emit(OpCodes.Set_Local_Value, Y(entry.PermanentIndex));
                        }
                    }
                }
            }
            else
            {
                if (entry.IsTemporary)
                {
                    if (entry.Occurrences == 1)
                    {
                        _generator.Emit(OpCodes.Set_Void, "1");
                    }
                    else
                    {
                        _generator.Emit(OpCodes.Set_Variable, X(entry.TemporaryIndex));
                    }
                }
                else
                {
                    _generator.Emit(OpCodes.Set_Variable, Y(entry.PermanentIndex));
                }
                entry.IsGlobal = true;
            }
        }
        private void CompileGoalVariable(PrologCodeVariable var, int i)
        {
            PrologVariableDictionaryEntry entry = _dictionary.GetVariable(var.Name);

            if (entry.IsTemporary)
            {
                if (entry.TemporaryIndex != i)
                {
                    ResolveConflicts(var, i);
                }
                if (entry.IsReferenced)
                {
                    if (entry.TemporaryIndex != i)
                    {
                        _generator.Emit(OpCodes.Put_Value, X(entry.TemporaryIndex), X(i));
                    }
                }
                else
                {
                    if (entry.TemporaryIndex != i)
                    {
                        _generator.Emit(OpCodes.Put_Variable, X(entry.TemporaryIndex), X(i));
                    }
                    else
                    {
                        _generator.Emit(OpCodes.Put_Variable, X(i), X(i));
                    }
                    entry.IsGlobal = true;
                }
            }
            else
            {
                ResolveConflicts(var, i);
                if (entry.IsReferenced)
                {
                    if (entry.IsUnsafe && !entry.IsGlobal &&
                        _dictionary.InLastGoal)
                    {
                        _generator.Emit(OpCodes.Put_Unsafe_Value, Y(entry.PermanentIndex), X(i));
                        entry.IsUnsafe = false;
                    }
                    else
                    {
                        if (entry.TemporaryIndex != -1)
                        {
                            _generator.Emit(OpCodes.Put_Value, X(entry.TemporaryIndex), X(i));
                        }
                        else
                        {
                            _generator.Emit(OpCodes.Put_Value, Y(entry.PermanentIndex), X(i));
                        }
                    }
                }
                else
                {
                    _generator.Emit(OpCodes.Put_Variable, Y(entry.PermanentIndex), X(i));
                }

                if (entry.TemporaryIndex == -1)
                {
                    entry.TemporaryIndex = i;
                }
                else
                {
                    // No
                }
            }
        }
        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();
        }
        private void CompileStructArguments(ArrayList arguments)
        {
            ArrayList records = new ArrayList();

            // TODO: Why is it 20 here? was there a maximum number of records originally.
            for (int i = 0; i < 20; i++)
            {
                records.Add(new Record());
            }

            int nRecs = 0;

            for (int i = 0; i < arguments.Count; i++)
            {
                PrologCodeTerm term = (PrologCodeTerm)arguments[i];

                if (term is PrologCodeNilAtom)
                {
                    _generator.Emit(OpCodes.Unify_Constant, "[]");
                }
                else if (term is PrologCodeAtom)
                {
                    if (term is PrologCodeConstantAtom)
                    {
                        _generator.Emit(OpCodes.Unify_Constant, ((PrologCodeConstantAtom)term).Value);
                    }
                    else if (term is PrologCodeIntegerAtom)
                    {
                        _generator.Emit(OpCodes.Unify_Constant, ((PrologCodeIntegerAtom)term).Value.ToString());
                    }
                    else if (term is PrologCodeFloatAtom)
                    {
                        _generator.Emit(OpCodes.Unify_Constant, ((PrologCodeFloatAtom)term).Value.ToString());
                    }
                    else if (term is PrologCodeStringAtom)
                    {
                        _generator.Emit(OpCodes.Unify_Constant, ((PrologCodeStringAtom)term).Value);
                    }
                }
                else if (term is PrologCodeVariable)
                {
                    PrologVariableDictionaryEntry entry = _dictionary.GetVariable(((PrologCodeVariable)term).Name);
                    if (entry.IsReferenced)
                    {
                        if (entry.IsTemporary)
                        {
                            if (entry.IsGlobal)
                            {
                                _generator.Emit(OpCodes.Unify_Value, X(entry.TemporaryIndex));
                            }
                            else
                            {
                                // TODO: maybe this should be unify_variable
                                _generator.Emit(OpCodes.Unify_Local_Value, X(entry.TemporaryIndex));
                                entry.IsGlobal = true;
                            }
                        }
                        else
                        {
                            if (entry.IsGlobal)
                            {
                                _generator.Emit(OpCodes.Unify_Value, Y(entry.PermanentIndex));
                            }
                            else
                            {
                                _generator.Emit(OpCodes.Unify_Local_Value, Y(entry.PermanentIndex));
                            }
                        }
                    }
                    // not referenced
                    else
                    {
                        if (entry.IsTemporary)
                        {
                            if (entry.Occurrences == 1)
                            {
                                _generator.Emit(OpCodes.Unify_Void, "1");
                            }
                            else
                            {   // used to be i < entry.TemporaryIndex
                                if (_currArgN < entry.TemporaryIndex && entry.TemporaryIndex < headArity)
                                {
                                    entry.TemporaryIndex = PrologRegisterTable.Instance.FindRegister();
                                }
                                _generator.Emit(OpCodes.Unify_Variable, X(entry.TemporaryIndex));
                            }
                        }
                        else
                        {
                            _generator.Emit(OpCodes.Unify_Variable, Y(entry.PermanentIndex));
                        }
                        entry.IsGlobal = true;
                    }
                }
                else if (term is PrologCodeEmptyList)
                {
                    _generator.Emit(OpCodes.Unify_Constant, "[]");
                }
                else
                {
                    ((Record)records[nRecs]).Term           = term;
                    ((Record)records[nRecs]).TemporaryIndex = PrologRegisterTable.Instance.FindRegister();
                    _generator.Emit(OpCodes.Unify_Variable, X(((Record)records[nRecs]).TemporaryIndex));
                    nRecs++;
                }
            }
            for (int i = 0; i < nRecs; i++)
            {
                Record r = (Record)records[i];
                if (r.Term is PrologCodeNonEmptyList)
                {
                    _generator.Emit(OpCodes.Get_List, X(r.TemporaryIndex));
                    PrologRegisterTable.Instance.FreeRegister(r.TemporaryIndex);
                    ArrayList listArguments       = new ArrayList();
                    PrologCodeNonEmptyList NEList = (PrologCodeNonEmptyList)r.Term;
                    listArguments.Add(NEList.Head);
                    listArguments.Add(NEList.Tail);
                    CompileStructArguments(listArguments);
                }
                else if (r.Term is PrologCodePredicate)
                {
                    PrologCodePredicate structure = (PrologCodePredicate)r.Term;
                    _generator.Emit(OpCodes.Get_Structure, structure.Name + "/" + structure.Arity, X(r.TemporaryIndex));
                    CompileStructArguments(structure.Arguments);
                }

                else
                {
                    throw new PrologCompilerException("Unknown argument type (" + r.Term.GetType().ToString() + ") in structure arguments");
                }
            }
        }
        private void CompileHeadArguments(ArrayList arguments)
        {
            for (int i = 0; i < arguments.Count; i++)
            {
                _currArgN = i;
                PrologCodeTerm arg = (PrologCodeTerm)arguments[i];

                if (arg is PrologCodeNilAtom || arg is PrologCodeEmptyList)
                {
                    _generator.Emit(OpCodes.Get_Constant, "[]", X(i));
                }
                else if (arg is PrologCodeAtom)
                {
                    if (arg is PrologCodeConstantAtom)
                    {
                        _generator.Emit(OpCodes.Get_Constant, ((PrologCodeConstantAtom)arg).Value, X(i));
                    }
                    else if (arg is PrologCodeIntegerAtom)
                    {
                        _generator.Emit(OpCodes.Get_Constant, ((PrologCodeIntegerAtom)arg).Value.ToString(), X(i));
                    }
                    else if (arg is PrologCodeFloatAtom)
                    {
                        _generator.Emit(OpCodes.Get_Constant, ((PrologCodeFloatAtom)arg).Value.ToString(), X(i));
                    }
                    else if (arg is PrologCodeStringAtom)
                    {
                        _generator.Emit(OpCodes.Get_Constant, ((PrologCodeStringAtom)arg).Value, X(i));
                    }
                }
                else if (arg is PrologCodeVariable)
                {
                    if (_dictionary.GoalCount == 0)
                    {
                        // warning: singleton variable
                    }
                    PrologVariableDictionaryEntry entry = _dictionary.GetVariable(((PrologCodeVariable)arg).Name);
                    if (entry.IsTemporary)
                    {
                        if (entry.IsReferenced && entry.TemporaryIndex != i)
                        {
                            _generator.Emit(OpCodes.Get_Value, X(entry.TemporaryIndex), X(i));
                        }
                    }
                    else
                    {
                        if (entry.IsReferenced)
                        {
                            _generator.Emit(OpCodes.Get_Value, Y(entry.PermanentIndex), X(i));
                        }
                        else
                        {
                            _generator.Emit(OpCodes.Get_Variable, Y(entry.PermanentIndex), X(i));
                        }
                    }
                }
                else if (arg is PrologCodeNonEmptyList)
                {
                    _generator.Emit(OpCodes.Get_List, X(i));
                    ArrayList listArguments       = new ArrayList();
                    PrologCodeNonEmptyList NEList = (PrologCodeNonEmptyList)arg;
                    listArguments.Add(NEList.Head);
                    listArguments.Add(NEList.Tail);
                    CompileStructArguments(listArguments);
                }
                else if (arg is PrologCodePredicate)
                {
                    PrologCodePredicate structure = (PrologCodePredicate)arg;
                    _generator.Emit(OpCodes.Get_Structure, structure.Name + "/" + structure.Arity, X(i));
                    CompileStructArguments(structure.Arguments);
                }
                else
                {
                    throw new PrologCompilerException("Unknown argument type (" + arg.GetType().ToString() + ") in head arguments");
                }
            }
        }
 public void AllocateTemporaryVariable(PrologVariableDictionaryEntry entry, int reg)
 {
     _registers.AllocateRegister(reg);
     entry.TemporaryIndex = reg;
 }
 public void AllocatePermanentVariable(PrologVariableDictionaryEntry entry, int reg)
 {
     entry.PermanentIndex = reg;
 }
        public void Add(object key, object val)
        {
            string name = (string)key;

            if(this.Contains(key))
            {
                PrologVariableDictionaryEntry entry = GetEntry((string)key);
                entry.Occurrences += 1;
                entry.LastGoal = _currentGoalIndex;
                entry.LastGoalArgument = _currentArgumentIndex;
            }
            else
            {
                PrologVariableDictionaryEntry variable = new PrologVariableDictionaryEntry(name, -1);
                variable.Occurrences = 0;
                variable.FirstGoal = _currentGoalIndex;
                variable.IsReferenced = false;
                variable.IsGlobal = false;
                variable.Occurrences += 1;
                variable.LastGoal = _currentGoalIndex;
                variable.LastGoalArgument = _currentArgumentIndex;
                variable.IsReferenced = false;
                _items.Add(variable);
            }
        }