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"); } } } }
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); }
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); }
private void AssertNotConstant(ASTParam sto) { if (sto.OptChangemode == null || sto.OptChangemode.Value != ChangeMode.VAR) { if (!IsInit) { throw new CheckerException("Can't modify constant parameter '" + Ident + "'"); } } //Default Changemode is const! if (sto.FlowMode == FlowMode.IN && sto.OptMechmode != MechMode.COPY) { throw new CheckerException("Can't modify 'in ref' parameter '" + Ident + "'"); } }