Esempio n. 1
0
        public static int GenerateCallingCode(int loc, IVirtualMachine vm, CheckerInformation info, ASTProcFuncDecl callee, List <ASTExpression> exprList)
        {
            //Allocate Return Location on Stack
            if (callee.IsFunc)
            {
                vm.Alloc(loc++, 1);
            }
            //Evaluate argument expressions
            var paramIttr = callee.Params.GetEnumerator();

            //Omit return param for functions
            if (callee.IsFunc)
            {
                if (!paramIttr.MoveNext())
                {
                    throw new IVirtualMachine.InternalError("No return param found for function");
                }
            }
            foreach (ASTExpression expr in exprList)
            {
                if (!paramIttr.MoveNext())
                {
                    throw new IVirtualMachine.InternalError("Too many arguments");
                }
                ASTParam param = paramIttr.Current;
                if (param.OptMechmode != MechMode.COPY || (param.FlowMode == FlowMode.OUT || param.FlowMode == FlowMode.INOUT))
                {
                    bool modifiable = param.OptChangemode == ChangeMode.VAR;
                    loc = expr.GenerateLValue(loc, vm, info, modifiable); //Load address on the stack
                }
                else
                {
                    loc = expr.GenerateCode(loc, vm, info); //Load value on the stack
                }
            }
            if (paramIttr.MoveNext())
            {
                throw new IVirtualMachine.InternalError("Too few arguments");
            }
            //Address of the function is not known.
            //So it has to be stored that at this loc should be a call to the function/procedure.
            if (callee.Address >= 0)
            {
                vm.Call(loc, callee.Address);
            }
            else
            {
                if (!info.Calls.ContainsKey(callee.Ident))
                {
                    info.Calls.Add(callee.Ident, new List <int>());
                }
                info.Calls[callee.Ident].Add(loc);
            }
            ++loc;
            return(loc);
        }
Esempio n. 2
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);
        }
Esempio n. 3
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;
            }
        }