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