コード例 #1
0
        public Clause Add(CodeSentence codeSentence)
        {
            if (codeSentence == null)
            {
                throw new ArgumentNullException("codeSentence");
            }
            if (codeSentence.Head == null)
            {
                throw new ArgumentException("Query cannot be added to program.", "codeSentence");
            }
            var functor = Functor.Create(codeSentence.Head.Functor);

            if (functor == Functor.PragmaFunctor)
            {
                ProcessPragma(codeSentence);
                return(null);
            }

            // Find procedure associated with codeSentence.  Create a new procedure if necessary.
            //
            Procedure procedure;

            if (!Procedures.TryGetProcedure(functor, out procedure))
            {
                procedure = Procedures.Add(functor);
            }

            // Create clause for codeSentence.
            //
            var clause = procedure.Clauses.Add(codeSentence);

            return(clause);
        }
コード例 #2
0
        internal Clause Add(CodeSentence codeSentence)
        {
            if (codeSentence == null)
            {
                throw new ArgumentNullException("codeSentence");
            }
            if (codeSentence.Head == null)
            {
                throw new ArgumentException("Query cannot be added to program.", "codeSentence");
            }
            if (Functor.Create(codeSentence.Head.Functor) != Procedure.Functor)
            {
                throw new ArgumentException("Clause not member of procedure.", "codeSentence");
            }
            if (Contains(codeSentence))
            {
                throw new ArgumentException("Item already exists.", "codeSentence");
            }

            Clause clause = new Clause(this, codeSentence);

            Items.Add(clause);
            Procedure.InvalidateInstructionStream();
            Procedure.InvalidatePosition();
            Procedure.Container.Program.Touch();

            return(clause);
        }
コード例 #3
0
        void Put(CodeCompoundTerm codeCompoundTerm, WamInstructionRegister targetRegister, LibraryList libraries)
        {
            var childrenRegisters = new WamInstructionRegister[codeCompoundTerm.Children.Count];

            // Build substructures.
            //
            for (var idx = 0; idx < codeCompoundTerm.Children.Count; ++idx)
            {
                var child = codeCompoundTerm.Children[idx];
                if (child.IsCodeList)
                {
                    child = ConvertCodeList(child.AsCodeList);
                }
                if (child.IsCodeCompoundTerm)
                {
                    childrenRegisters[idx] = GetNextTemporaryRegister();
                    Put(child, childrenRegisters[idx], libraries);
                }
            }

            var functor = Functor.Create(codeCompoundTerm.Functor);

            InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.PutStructure, functor, targetRegister));
            for (var idx = 0; idx < codeCompoundTerm.Children.Count; ++idx)
            {
                var child = codeCompoundTerm.Children[idx];

                if (child.IsCodeList)
                {
                    child = ConvertCodeList(child.AsCodeList);
                }
                if (child.IsCodeVariable)
                {
                    var variableName     = child.AsCodeVariable.Name;
                    var variableRegister = GetRegisterAssignment(variableName);
                    if (variableRegister.IsUnused)
                    {
                        variableRegister = GetNextPermanentRegister(variableName);
                        InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.SetUnboundVariable, variableRegister));
                    }
                    else
                    {
                        InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.SetBoundVariable, variableRegister));
                    }
                }
                else if (child.IsCodeCompoundTerm)
                {
                    InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.SetBoundVariable, childrenRegisters[idx]));
                }
                else if (child.IsCodeValue)
                {
                    InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.SetValue, WamValue.Create(child.AsCodeValue)));
                }
                else
                {
                    throw new InvalidOperationException("Unsupported codeTerm type.");
                }
            }
        }
コード例 #4
0
        public static WamCompoundTerm Create(CodeCompoundTerm codeCompoundTerm)
        {
            var functor = Functor.Create(codeCompoundTerm.Functor);
            var result  = WamCompoundTerm.Create(functor);

            for (var index = 0; index < functor.Arity; ++index)
            {
                result.Children[index] = WamReferenceTarget.Create(codeCompoundTerm.Children[index]);
            }
            return(result);
        }
コード例 #5
0
ファイル: Compiler.cs プロジェクト: russlank/Prolog.NET
        private void Call(CodeFunctor codeFunctor, LibraryList libraries)
        {
            Functor functor = Functor.Create(codeFunctor);

            if (functor == Functor.CutFunctor)
            {
                InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.Cut));
            }
            else if (libraries.Contains(functor))
            {
                InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.LibraryCall, functor));
            }
            else
            {
                InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.Call, functor));
            }
        }
コード例 #6
0
        public bool Contains(CodeSentence codeSentence)
        {
            if (codeSentence == null)
            {
                throw new ArgumentNullException("codeSentence");
            }
            if (codeSentence.Head == null)
            {
                throw new ArgumentException("Program cannot contain query.", "codeSentence");
            }

            var       functor = Functor.Create(codeSentence.Head.Functor);
            Procedure procedure;

            if (Procedures.TryGetProcedure(functor, out procedure))
            {
                if (procedure.Clauses.Contains(codeSentence))
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #7
0
ファイル: Compiler.cs プロジェクト: russlank/Prolog.NET
        private void Execute(CodeFunctor codeFunctor)
        {
            Functor functor = Functor.Create(codeFunctor);

            InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.Execute, functor));
        }
コード例 #8
0
ファイル: Compiler.cs プロジェクト: russlank/Prolog.NET
        private void Get(CodeCompoundTerm codeCompoundTerm, WamInstructionRegister sourceRegister)
        {
            WamInstructionRegister[] childrenRegisters = new WamInstructionRegister[codeCompoundTerm.Children.Count];

            InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.GetStructure, sourceRegister, Functor.Create(codeCompoundTerm.Functor)));
            for (int idx = 0; idx < codeCompoundTerm.Children.Count; ++idx)
            {
                CodeTerm child = codeCompoundTerm.Children[idx];

                if (child.IsCodeList)
                {
                    child = ConvertCodeList(child.AsCodeList);
                }

                if (child.IsCodeVariable)
                {
                    string variableName = child.AsCodeVariable.Name;
                    WamInstructionRegister variableRegister = GetRegisterAssignment(variableName);
                    if (variableRegister.IsUnused)
                    {
                        variableRegister = GetNextPermanentRegister(variableName);
                        InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.UnifyUnboundVariable, variableRegister));
                    }
                    else
                    {
                        InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.UnifyBoundVariable, variableRegister));
                    }
                }
                else if (child.IsCodeCompoundTerm)
                {
                    childrenRegisters[idx] = GetNextTemporaryRegister();
                    InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.UnifyUnboundVariable, childrenRegisters[idx]));
                }
                else if (child.IsCodeValue)
                {
                    InstructionStreamBuilder.Write(new WamInstruction(WamInstructionOpCodes.UnifyValue, WamValue.Create(child.AsCodeValue)));
                }
                else
                {
                    throw new InvalidOperationException("Unsupported codeTerm type.");
                }
            }

            // Build substructures.
            //
            for (int idx = 0; idx < codeCompoundTerm.Children.Count; ++idx)
            {
                CodeTerm child = codeCompoundTerm.Children[idx];

                if (child.IsCodeList)
                {
                    child = ConvertCodeList(child.AsCodeList);
                }

                if (child.IsCodeCompoundTerm)
                {
                    Get(child, childrenRegisters[idx]);
                }
            }
        }
コード例 #9
0
ファイル: Compiler.cs プロジェクト: russlank/Prolog.NET
        public WamInstructionStream Compile(CodeSentence codeSentence, Functor functor, int index, bool isLast, LibraryList libraries, bool optimize)
        {
            Initialize();

            // When true, indicates we are compiling code for a procedure clause.  When false, indicates we
            // are compiling for an ad hoc query.
            //
            bool isClause = (functor != null);

            if (isClause)
            {
                WamInstructionStreamClauseAttribute clauseAttribute = new WamInstructionStreamClauseAttribute(
                    m_instructionStreamBuilder.NextIndex,
                    functor,
                    index);
                m_instructionStreamBuilder.AddAttribute(clauseAttribute);
            }

            if (isClause)
            {
                if (isLast)
                {
                    if (index == 0)
                    {
                        // Procedure only has one clause in it.  No retry logic required.
                    }
                    else
                    {
                        TrustMe();
                    }
                }
                else
                {
                    if (index == 0)
                    {
                        TryMeElse(functor, index + 1);
                    }
                    else
                    {
                        RetryMeElse(functor, index + 1);
                    }
                }
            }

            Allocate();

            if (codeSentence.Head != null)
            {
                for (int idx = 0; idx < codeSentence.Head.Children.Count; ++idx)
                {
                    Get(codeSentence.Head.Children[idx], GetArgumentRegister(idx));
                }
            }

            if (codeSentence.Body.Count > 0)
            {
                for (int idxProcedure = 0; idxProcedure < codeSentence.Body.Count; ++idxProcedure)
                {
                    CodeCompoundTerm codeCompoundTerm = codeSentence.Body[idxProcedure];

                    for (int idxArgument = 0; idxArgument < codeCompoundTerm.Children.Count; ++idxArgument)
                    {
                        Put(codeCompoundTerm.Children[idxArgument], GetArgumentRegister(idxArgument), libraries);
                    }

                    bool isLastCall = (idxProcedure == codeSentence.Body.Count - 1);

                    if (isClause)
                    {
                        if (isLastCall)
                        {
                            if (optimize &&
                                !libraries.Contains(Functor.Create(codeCompoundTerm.Functor)) &&
                                codeCompoundTerm.Functor != CodeFunctor.CutFunctor)
                            {
                                Deallocate();
                                Execute(codeCompoundTerm.Functor);
                            }
                            else
                            {
                                Call(codeCompoundTerm.Functor, libraries);
                                Deallocate();
                                Proceed();
                            }
                        }
                        else
                        {
                            Call(codeCompoundTerm.Functor, libraries);
                        }
                    }
                    else // isQuery
                    {
                        Call(codeCompoundTerm.Functor, libraries);

                        if (isLastCall)
                        {
                            Success();
                        }
                    }
                }
            }
            else // fact
            {
                if (isClause)
                {
                    Deallocate();
                    Proceed();
                }
                else // isQuery
                {
                    // No action required.
                }
            }

            return(InstructionStreamBuilder.ToInstructionStream());
        }