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); }
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); }
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); } }
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); }
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); }
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); }
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); }
public abstract int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info);
public int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info) { throw new IVirtualMachine.InternalError("ASTOptInit.GenerateCode was called. This should never happen!"); }
public int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info) { return(loc); }
public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info) { vm.IntLoad(loc++, Value ? 1 : 0); return(loc); }
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); }
static TestVirtualMachine() { TestVirtualMachine.vm = new VirtualMachine(CODE_SIZE, STORE_SIZE); }
public virtual int GenerateLValue(int loc, IVirtualMachine vm, CheckerInformation info, bool hasToBeLValue = true) { throw new IVirtualMachine.InternalError("Expression is no LValue"); }