Beispiel #1
0
        private void CheckForUndeclaredIdent(ASTProgram root, CheckerInformation info)
        {
            UsedIdents usedIdents = new UsedIdents(info);

            root.GetUsedIdents(usedIdents);
            info.CurrentNamespace = null;
            //Check to see if each local outflow parameter was initialized
            foreach (string ident in info.ProcFuncs)
            {
                foreach (ASTParam param in info.ProcFuncs[ident].Params)
                {
                    if (param.FlowMode == FlowMode.OUT && (!usedIdents.LocalInitialized.ContainsKey(ident) || !usedIdents.LocalInitialized[ident].Contains(param.Ident)))
                    {
                        throw new CheckerException("The outflow parameter '" + param.Ident + "' of the procedure/function '" + ident + "' was not initialized");
                    }
                }
            }
            //Check if each global outflow parameter was initialized
            foreach (string global in info.Globals)
            {
                if (info.Globals[global] is ASTParam)
                {
                    ASTParam param = (ASTParam)info.Globals[global];
                    if (param.FlowMode == FlowMode.OUT && !usedIdents.GlobalInitialized.Contains(param.Ident))
                    {
                        throw new CheckerException("The global outflow parameter '" + param.Ident + "' of the program was not initialized");
                    }
                }
            }
        }
Beispiel #2
0
 public UsedIdents(CheckerInformation info)
 {
     AllowInit         = true;
     this.info         = info;
     GlobalInitialized = new List <string>();
     LocalInitialized  = new Dictionary <string, List <string> >();
 }
Beispiel #3
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            if (Type != Type.DECIMAL && Type != Type.INT32)
            {
                throw new IVirtualMachine.InternalError("Use of invalid (not existing) casting type " + Type.ToString());
            }
            Type exprType = Expr.GetExpressionType(info);

            if (exprType != Type.DECIMAL && exprType != Type.INT32)
            {
                throw new IVirtualMachine.InternalError("Cannot cast from type " + exprType.ToString());
            }
            loc = Expr.GenerateCode(loc, vm, info);
            if (Type != exprType)
            {
                if (Type == Type.DECIMAL && exprType == Type.INT32)
                {
                    vm.IntToDecimal(loc++);
                }
                else if (Type == Type.INT32 && exprType == Type.DECIMAL)
                {
                    vm.DecimalToInt(loc++);
                }
                else
                {
                    throw new IVirtualMachine.InternalError("Invalid casting operation");
                }
            }
            return(loc);
        }
Beispiel #4
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);
     }
 }
Beispiel #5
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            //Get abstract declaration
            ASTProcFuncDecl callee = info.ProcFuncs[Ident];

            loc = ASTCmdCall.GenerateCallingCode(loc, vm, info, callee, ExprList);
            return(loc);
        }
Beispiel #6
0
        private void OptainNamespaceInformation(ASTProgram root, CheckerInformation info)
        {
            int globalAddress = 0;

            //Add global parameters
            foreach (ASTParam param in root.Params)
            {
                param.Address = globalAddress++;
                info.Globals.addDeclaration(param);
            }
            //Add Global Variables, Functions and Procedures
            //And add local variables and parameters of the Function and Procedures
            foreach (ASTCpsDecl declaration in root.Declarations)
            {
                if (declaration is ASTStoDecl)
                {
                    //Add global storage identifier
                    declaration.Address = globalAddress++;
                    info.Globals.addDeclaration((ASTStoDecl)declaration);
                }
                else if (declaration is ASTProcFuncDecl)
                {
                    ASTProcFuncDecl procFunc = (ASTProcFuncDecl)declaration;
                    //Add function or procedure identifier
                    declaration.Address = -1;
                    info.ProcFuncs.addDeclaration(procFunc);
                    Namespace <IASTStoDecl> ns = new Namespace <IASTStoDecl>();
                    info.Namespaces.Add(declaration.Ident, ns);
                    //Relative address: The framepointer is one above the last parameter. Meaning the last parameter has the relative address -1 and the first -Params.Count
                    int paramAddress = -procFunc.Params.Count;
                    //Relative address: out copy, inout copy and local identifiers. Starting 3 addresses behind the frame pointer.
                    int localAddress = 3;
                    //Add local params of this function/procedure
                    foreach (ASTParam localParam in procFunc.Params)
                    {
                        if (localParam.OptMechmode == MechMode.COPY && (localParam.FlowMode == FlowMode.OUT || localParam.FlowMode == FlowMode.INOUT))
                        {
                            localParam.Address         = localAddress++;
                            localParam.AddressLocation = paramAddress++;
                        }
                        else
                        {
                            localParam.Address = paramAddress++;
                        }
                        ns.addDeclaration(localParam);
                    }
                    //Add local storage identifier of this function/procedure
                    foreach (ASTCpsDecl localDeclaration in ((ASTProcFuncDecl)declaration).Declarations)
                    {
                        if (localDeclaration is ASTStoDecl)
                        {
                            localDeclaration.Address = localAddress++;
                            ns.addDeclaration((ASTStoDecl)localDeclaration);
                        }
                    }
                }
            }
        }
Beispiel #7
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);
        }
Beispiel #8
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);
        }
Beispiel #9
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);
     }
 }
Beispiel #10
0
        public void Check(ASTProgram root, CheckerInformation info)
        {
            //Fill namespaces with declaration identifiers
            //Throws an exception if an identifier is declared more then once in a namespace
            OptainNamespaceInformation(root, info);
            //Is any applied identifier declared and initialized?
            CheckForUndeclaredIdent(root, info);
            //Checks if the function parameters are valid
            CheckFunctionParameter(root, info);

            //TODO: Check: if only specified globals are accessed in procedures/functions
            //TODO: Check: Only const globals are allowed in functions
            //TODO: Check: Are only different parameters provided to a procedure as references (Never more then one reference to the same storage)
            //TODO: test05.iml: local constant variables should not be modifiable
        }
Beispiel #11
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            int conditionLoc = loc;

            loc = Condition.GenerateCode(loc, vm, info);
            int condJumpLoc = loc++; //Placeholder for conditonal jump out of while loop

            foreach (ASTCpsCmd cmd in Commands)
            {
                loc = cmd.GenerateCode(loc, vm, info);
            }
            vm.UncondJump(loc++, conditionLoc);
            //Fill in placeholder
            vm.CondJump(condJumpLoc, loc);
            return(loc);
        }
Beispiel #12
0
 static void Main(string[] args)
 {
     if (args.Length != 1)
     {
         Console.WriteLine("Compiler usage: iml <program>"); return;
     }
     //TestVirtualMachine.Test(); return;
     try
     {
         //Scanner
         Scanner scanner = new Scanner();
         var     list    = scanner.Scan(new StreamReader(args[0]));
         Console.WriteLine("[" + String.Join(", ", list) + "]");
         Console.WriteLine();
         //Parser
         Parser parser = new Parser();
         var    tree   = parser.Parse(list);
         //Converter
         var ast = tree.ToAbstractSyntax();
         Console.WriteLine(ast.ToString());
         Console.WriteLine();
         if (!(ast is ASTProgram))
         {
             throw new IVirtualMachine.InternalError("Generation of Abstract Syntax Tree failed.");
         }
         ASTProgram program = (ASTProgram)ast;
         //Checker
         CheckerInformation info           = new CheckerInformation();
         ScopeChecker       contextChecker = new ScopeChecker();
         contextChecker.Check(program, info);
         //Code Generator
         IVirtualMachine vm = new VirtualMachine(1000, 1000);
         program.GenerateCode(0, vm, info);
         Console.WriteLine(vm.ToString());
         Console.WriteLine();
         //Executuion
         vm.Execute();
     }
     catch (Exception ex)
     {
         Console.WriteLine("Failed: " + ex.Message);
         //*Only for debuging of the compiler */ Console.WriteLine(ex.StackTrace);
     }
 }
Beispiel #13
0
 private void CheckFunctionParameter(ASTProgram root, CheckerInformation info)
 {
     //Functions can only have one out/inout param (this has to be the first one)
     foreach (string ident in info.ProcFuncs)
     {
         if (info.ProcFuncs[ident].IsFunc)
         {
             var paramIttr = info.ProcFuncs[ident].Params.GetEnumerator();
             paramIttr.MoveNext();
             while (paramIttr.MoveNext())
             {
                 if (paramIttr.Current.FlowMode == FlowMode.OUT || paramIttr.Current.FlowMode == FlowMode.INOUT)
                 {
                     throw new CheckerException("A function can not have out/inout parameter.");
                 }
             }
         }
     }
 }
Beispiel #14
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            loc = Condition.GenerateCode(loc, vm, info);
            int condJumpLoc = loc++; //Placeholder

            foreach (ASTCpsCmd cmd in TrueCommands)
            {
                loc = cmd.GenerateCode(loc, vm, info);
            }
            int uncondJumpLoc = loc++;     //Placeholder2

            vm.CondJump(condJumpLoc, loc); //Fill in Placeholder
            foreach (ASTCpsCmd cmd in FalseCommands)
            {
                loc = cmd.GenerateCode(loc, vm, info);
            }
            vm.UncondJump(uncondJumpLoc, loc); //Fill in Placeholder2
            return(loc);
        }
Beispiel #15
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            loc = Expr.GenerateCode(loc, vm, info);

            var type = GetExpressionType(info);

            if (type == Type.BOOL)
            {
                //1 NE 1 == 0
                //0 NE 1 == 1
                vm.IntLoad(loc++, 1);
                vm.IntNE(loc++);
            }
            else
            {
                throw new IVirtualMachine.InternalError(
                          "Cannot negate Non-Bool value " + Expr.ToString());
            }

            return(loc);
        }
Beispiel #16
0
        public override Type GetExpressionType(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!");
                    }
                    var paramIttr = callee.Params.GetEnumerator();
                    if (!paramIttr.MoveNext())
                    {
                        throw new IVirtualMachine.InternalError("No return param found for function");
                    }
                    return(paramIttr.Current.Type);
                }
                else
                {
                    throw new IVirtualMachine.InternalError("Call to unkown function '" + Ident + "'");
                }
            }
            else
            {
                if (info.CurrentNamespace != null &&
                    info.Namespaces.ContainsKey(info.CurrentNamespace) &&
                    info.Namespaces[info.CurrentNamespace].ContainsIdent(Ident))
                {
                    return(info.Namespaces[info.CurrentNamespace].GetIdent(Ident).Type);
                }

                if (info.Globals.ContainsIdent(Ident))
                {
                    return(info.Globals.GetIdent(Ident).Type);
                }

                throw new IVirtualMachine.InternalError("Use of unkwon identifier '" + Ident + "'");
            }
        }
Beispiel #17
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            loc = Expr.GenerateCode(loc, vm, info);

            var type = GetExpressionType(info);

            if (type == Type.INT32)
            {
                vm.IntInv(loc++);
            }
            else if (type == Type.DECIMAL)
            {
                vm.DecimalInv(loc++);
            }
            else
            {
                throw new IVirtualMachine.InternalError(
                          "Cannot inverse " + type.ToString() + " value " + Expr.ToString());
            }

            return(loc);
        }
Beispiel #18
0
 public abstract int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info);
Beispiel #19
0
 public int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
 {
     throw new IVirtualMachine.InternalError("ASTOptInit.GenerateCode was called. This should never happen!");
 }
Beispiel #20
0
 public override Type GetExpressionType(CheckerInformation info)
 {
     return(this.Type);
 }
Beispiel #21
0
 public int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
 {
     return(loc);
 }
Beispiel #22
0
 public override Type GetExpressionType(CheckerInformation info)
 {
     return(Expr.GetExpressionType(info));
 }
Beispiel #23
0
 public override Type GetExpressionType(CheckerInformation info)
 {
     return(Type.BOOL);
 }
Beispiel #24
0
 public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
 {
     vm.IntLoad(loc++, Value ? 1 : 0);
     return(loc);
 }
Beispiel #25
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);
        }
Beispiel #26
0
 public virtual int GenerateLValue(int loc, IVirtualMachine vm, CheckerInformation info, bool hasToBeLValue = true)
 {
     throw new IVirtualMachine.InternalError("Expression is no LValue");
 }
Beispiel #27
0
 public abstract Type GetExpressionType(CheckerInformation info);