Example #1
0
 public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
 {
     if (IsFuncCall)
     {
         if (info.ProcFuncs.ContainsIdent(Ident))
         {
             ASTProcFuncDecl callee = info.ProcFuncs[Ident];
             if (!callee.IsFunc)
             {
                 throw new IVirtualMachine.InternalError("Calls inside expresssions can only be made to functions but never to procedures!");
             }
             loc = ASTCmdCall.GenerateCallingCode(loc, vm, info, callee, OptInitOrExprList);
             return(loc);
         }
         else
         {
             throw new IVirtualMachine.InternalError("Call to unkown function '" + Ident + "'");
         }
     }
     else
     {
         loc = GenerateLValue(loc, vm, info, false);
         vm.Deref(loc++);
         return(loc);
     }
 }
Example #2
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            int copies = 0;

            foreach (ASTParam param in Params)
            {
                if (param.OptMechmode == MechMode.COPY && (param.FlowMode == FlowMode.INOUT || param.FlowMode == FlowMode.OUT))
                {
                    ++copies;
                }
            }
            vm.Enter(loc++, copies + Declarations.Count, 0);
            //CopyIn of inout copy parameters
            foreach (ASTParam param in Params)
            {
                if (param.OptMechmode == MechMode.COPY && param.FlowMode == FlowMode.INOUT)
                {
                    vm.CopyIn(loc++, param.AddressLocation.Value, param.Address);
                }
            }
            //Generate body
            foreach (ASTCpsCmd cmd in Commands)
            {
                loc = cmd.GenerateCode(loc, vm, info);
            }
            //CopyOut of inout copy and out copy parameters
            bool omit = IsFunc;

            foreach (ASTParam param in Params)
            {
                if (omit)
                {
                    omit = false;
                }
                else
                {
                    if (param.OptMechmode == MechMode.COPY && (param.FlowMode == FlowMode.INOUT || param.FlowMode == FlowMode.OUT))
                    {
                        vm.CopyOut(loc++, param.Address, param.AddressLocation.Value);
                    }
                }
            }
            if (IsFunc)
            {
                //CopyOut return value
                //Can't use standard CopyOut, becuase it works with absolute target address and not with top of stack as needed!
                var      paramIttr = Params.GetEnumerator(); paramIttr.MoveNext();
                ASTParam result    = paramIttr.Current;
                vm.LoadRel(loc++, result.Address);
                vm.Deref(loc++);
                vm.LoadRel(loc++, result.AddressLocation.Value);
                vm.Store(loc++);
            }
            //Return
            vm.Return(loc++, Params.Count - (IsFunc ? 1 : 0)); //For function the return size is one smaller, leaving the function expression result on the stack!
            return(loc);
        }
Example #3
0
 public override int GenerateLValue(int loc, IVirtualMachine vm, CheckerInformation info, bool hasToBeLValue = true)
 {
     if (IsFuncCall)
     {
         throw new IVirtualMachine.InternalError("The result of a function can't be an LValue");
     }
     else
     {
         //Write address to the top of the stack
         if (info.CurrentNamespace != null &&
             info.Namespaces.ContainsKey(info.CurrentNamespace) &&
             info.Namespaces[info.CurrentNamespace].ContainsIdent(Ident))
         {
             IASTStoDecl storage = info.Namespaces[info.CurrentNamespace][Ident];
             if (hasToBeLValue)
             {
                 AssertNotConstant(storage);
             }
             if (storage is ASTStoDecl || (storage is ASTParam && ((ASTParam)storage).OptMechmode == MechMode.COPY))
             {
                 //Local Identifier or parameter with mechmode COPY
                 vm.LoadRel(loc++, storage.Address);
             }
             else if (storage is ASTParam)
             {
                 //If mechmode is null: default = Mechmode.REF
                 //Load parameter with mechmode REF
                 vm.LoadRel(loc++, storage.Address); //Relative Address to fp
                 vm.Deref(loc++);                    //Deref to get global Address
                 //With another Deref the value is loaded
             }
             else
             {
                 //Should never happen as long as no new type is added
                 throw new IVirtualMachine.InternalError("Unknown Identifier Type");
             }
         }
         else if (info.Globals.ContainsIdent(Ident))
         {
             IASTStoDecl storage = info.Globals[Ident];
             if (hasToBeLValue)
             {
                 AssertNotConstant(storage);
             }
             vm.IntLoad(loc++, storage.Address);
         }
         else
         {
             throw new IVirtualMachine.InternalError("Access of undeclared Identifier " + Ident);
         }
         return(loc);
     }
 }
Example #4
0
        public int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            //Allocate global storage
            vm.Alloc(loc++, info.Globals.Count);
            //Load input params
            foreach (ASTParam param in Params)
            {
                if (param.FlowMode == FlowMode.IN || param.FlowMode == FlowMode.INOUT)
                {
                    //Load address where to save the input
                    vm.IntLoad(loc++, param.Address);
                    //Switch between types:
                    switch (param.Type)
                    {
                    case Type.INT32:
                        vm.IntInput(loc++, param.Ident);
                        break;

                    case Type.BOOL:
                        vm.BoolInput(loc++, param.Ident);
                        break;

                    case Type.DECIMAL:
                        vm.DecimalInput(loc++, param.Ident);
                        break;
                    }
                }
            }
            //Generate main code
            foreach (ASTCpsCmd cmd in Commands)
            {
                loc = cmd.GenerateCode(loc, vm, info);
            }
            //Add output code
            foreach (ASTParam param in Params)
            {
                if (param.FlowMode == FlowMode.OUT || param.FlowMode == FlowMode.INOUT)
                {
                    //Load output value
                    vm.IntLoad(loc++, param.Address);
                    vm.Deref(loc++);
                    //Switch between types:
                    switch (param.Type)
                    {
                    case Type.INT32:
                        vm.IntOutput(loc++, param.Ident);
                        break;

                    case Type.BOOL:
                        vm.BoolOutput(loc++, param.Ident);
                        break;

                    case Type.DECIMAL:
                        vm.DecimalOutput(loc++, param.Ident);
                        break;
                    }
                }
            }
            //Add stop as last command
            vm.Stop(loc++);
            //Generate functions/procedures
            foreach (string ident in info.ProcFuncs)
            {
                ASTProcFuncDecl procFunc = info.ProcFuncs[ident];
                procFunc.Address = loc;
                //Add calls, now that the function/procedure address is known
                if (info.Calls.ContainsKey(ident) && info.Calls[ident] != null)
                {
                    foreach (int callLoc in info.Calls[ident])
                    {
                        vm.Call(callLoc, procFunc.Address);
                    }
                }
                //Change current namespace
                info.CurrentNamespace = ident;
                //Generate code for function/procedure
                loc = procFunc.GenerateCode(loc, vm, info);
                //Reset namespace
                info.CurrentNamespace = null;
            }
            return(loc);
        }
Example #5
0
/*
 *  program intDiv
 *  global
 *    proc divide(in copy m:int, in copy n:int, out ref q:int, out ref r:int)
 *    do
 *      q init := 0;
 *      r init := m;
 *      while r >= n do
 *        q := q + 1;
 *        r := r - n
 *      endwhile
 *    endproc;
 *
 *    var m:int;
 *    var n:int;
 *    var q:int;
 *    var r:int
 *  do
 *    ? m init;
 *    ? n init;
 *    call divide(m, n, q init, r init);
 *    ! q;
 *    ! r
 *  endprogram
 */

        public static void Test()
        {
            try {
                vm.Alloc(0, 4);
                vm.IntLoad(1, 0);
                vm.IntInput(2, "m");
                vm.IntLoad(3, 1);
                vm.IntInput(4, "n");
                vm.Alloc(5, 0);
                vm.IntLoad(6, 0);
                vm.Deref(7);
                vm.IntLoad(8, 1);
                vm.Deref(9);
                vm.IntLoad(10, 2);
                vm.IntLoad(11, 3);
                vm.Call(12, 20);
                vm.IntLoad(13, 2);
                vm.Deref(14);
                vm.IntOutput(15, "q");
                vm.IntLoad(16, 3);
                vm.Deref(17);
                vm.IntOutput(18, "r");
                vm.Stop(19);
                vm.Enter(20, 0, 0);
                vm.IntLoad(21, 0);
                vm.LoadRel(22, (-2));
                vm.Deref(23);
                vm.Store(24);
                vm.LoadRel(25, (-4));
                vm.Deref(26);
                vm.LoadRel(27, (-1));
                vm.Deref(28);
                vm.Store(29);
                vm.LoadRel(30, (-1));
                vm.Deref(31);
                vm.Deref(32);
                vm.LoadRel(33, (-3));
                vm.Deref(34);
                vm.IntGE(35);
                vm.CondJump(36, 55);
                vm.LoadRel(37, (-2));
                vm.Deref(38);
                vm.Deref(39);
                vm.IntLoad(40, 1);
                vm.IntAdd(41);
                vm.LoadRel(42, (-2));
                vm.Deref(43);
                vm.Store(44);
                vm.LoadRel(45, (-1));
                vm.Deref(46);
                vm.Deref(47);
                vm.LoadRel(48, (-3));
                vm.Deref(49);
                vm.IntSub(50);
                vm.LoadRel(51, (-1));
                vm.Deref(52);
                vm.Store(53);
                vm.UncondJump(54, 30);
                vm.Return(55, 4);
            } catch (IVirtualMachine.CodeTooSmallError e) {
                Console.WriteLine(e.ToString());
                return;
            }

            try {
                vm.Execute();
            } catch (IVirtualMachine.ExecutionError e) {
                Console.WriteLine(e.ToString());
                return;
            }
        }