Exemple #1
0
            private void CompileMatcher(byte register, byte argument, object obj)
            {
                obj = Term.Deref(obj);
                var lv = obj as LogicVariable;

                if (lv != null)
                {
                    var info = env[lv];
                    if (register != NoRegister || info.register != argument)   // If top level and first occurance, don't bother.
                    {
                        env.InsureAllocated(info);
                        if (info.AlreadyStored)
                        {
                            Emit(Opcode.MatchVar, info.register);
                        }
                        else
                        {
                            Emit(Opcode.MatchVarFirst, SymbolTable.IndexOf(lv.Name), info.register);
                        }
                        EmitOperand(register, argument);
                    }
                    env.OneUseCompiled(info);
                }
                else
                {
                    var structure = obj as Structure;
                    if (structure != null)
                    {
                        Structure s = structure;
                        byte      destinationRegister = (register == NoRegister)?argument:this.env.GetRegister();
                        this.Emit(Opcode.MatchStructure, SymbolTable.IndexOf(s.Functor), (byte)s.Arity);
                        ushort backPatchAddress = this.CurrentPC;
                        this.EmitUShort(0);
                        this.EmitOperand(register, argument, destinationRegister);
                        for (byte i = 0; i < s.Arity; i++)
                        {
                            this.CompileMatcher(destinationRegister, i, s.Argument(i));
                        }
                        this.BackPatch(backPatchAddress, this.CurrentPC);
                        if (register != NoRegister)
                        {
                            this.env.FreeRegister(destinationRegister);
                        }
                    }
                    else
                    {
                        this.Emit(Opcode.MatchLiteral, GlobalLiteralTable.IndexOf(obj));
                        this.EmitOperand(register, argument);
                    }
                }
            }
 private void CompileBuildLiteral(object term, byte argRegister, byte argument)
 {
     Emit(Opcode.BuildLiteral, GlobalLiteralTable.IndexOf(term));
     EmitOperand(argRegister, argument);
 }
            private void CompileGoal(Structure goal, ref ushort failAddress, ref ushort backPatchAddress)
            {
                byte continuationRegister = env.GetRegister();
                // Allocate registers to goal arguments.
                var argRegisters = new byte[goal.Arity];

                for (int i = 0; i < goal.Arity; i++)
                {
                    object arg = goal.Argument(i);
                    if (arg is Structure)
                    {
                        argRegisters[i] = env.GetRegister();
                    }
                    else
                    {
                        var @var = arg as LogicVariable;
                        if (@var != null)
                        {
                            argRegisters[i] = this.env.InsureRegisterAndLock(@var);
                        }
                        else
                        {
                            // It's a literal.
                            argRegisters[i] = NoRegister;
                        }
                    }
                }

                // Build goal arguments into registers.
                for (int i = 0; i < goal.Arity; i++)
                {
                    if (argRegisters[i] != NoRegister)
                    {
                        CompileBuild(goal.Argument(i), NoRegister, argRegisters[i]);
                    }
                }

                // Emit call instruction
                ushort startOfCallInstruction = CurrentPC;

                BackPatch(backPatchAddress, startOfCallInstruction);
                PrologPrimitives.PrimitiveImplementation primitiveImplementation;
                bool isPrimitive = PrologPrimitives.Implementations.TryGetValue(goal.Functor,
                                                                                out primitiveImplementation);

                // Call header
                Emit(isPrimitive?Opcode.CallPrimitive : Opcode.Call, continuationRegister);
                EmitUShort(failAddress);
                backPatchAddress = CurrentPC;
                EmitUShort(0);      // This will get backpatched
                // Call target
                if (isPrimitive)
                {
                    EmitUShort(PrimitiveTable.IndexOf(primitiveImplementation));
                    EmitByte((byte)goal.Arity);
                }
                else
                {
                    EmitUShort(PredicateTable.IndexOf(this.knowledgeBase.EntryForStoring(goal.PredicateIndicator)));
                }
                // Call arguments
                for (int i = 0; i < goal.Arity; i++)
                {
                    byte reg = argRegisters[i];
                    if (reg == NoRegister)
                    {
                        EmitUShort((ushort)(0x8000 + GlobalLiteralTable.IndexOf(goal.Argument(i))));
                    }
                    else
                    {
                        EmitByte(reg);
                    }
                }
                failAddress = startOfCallInstruction;
            }