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"); } } } }
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); } } } } }
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 }
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); } }
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."); } } } } }