//m[m][b] := c; //m:A b:B c:C // type(m) = [A] ([B]C) // ==> m [m := m[m] [b:=c]] // ==> MU<[A]([B]C)>(m, m ,MU<[B]C>( ML<[A]([B]C)>(m,m), b, c ) //m[m] := b // ==> m := m[m:=b] // ==> m := MU<[A]B>(m,m,b) ///////////////////////////////////////////////////////////////////////////////////// private Expression getAssignmentSourceExpression(MapAssignLhs target, Expression source) { var arguments = new List <Expression>(); arguments.Add(procedure.expressionFactory.makeExpression(target.Map.AsExpr)); foreach (var e in target.Indexes) { arguments.Add(procedure.expressionFactory.makeExpression(e)); } arguments.Add(source); var mt = arguments[0].type as MapType; Debug.Assert(mt != null); var argumentTypes = new IType[arguments.Count]; for (int i = 0; i < arguments.Count; i++) { argumentTypes[i] = arguments[i].type; } IType resultType = arguments[0].type; var typeArguments = new IType[target.TypeParameters.FormalTypeParams.Count]; for (int i = 0; i < typeArguments.Length; i++) { typeArguments[i] = makeType(target.TypeParameters[target.TypeParameters.FormalTypeParams[i]]); } Expression recSource = new BasicFAE( BasicMapWrite.makeMapWrite(typeArguments, argumentTypes, resultType), new ExpressionList(arguments) ); return(getAssignmentSourceExpression(target.Map, recSource)); }
//////////////////////////////////////////////////////////////////////////////////// private Expression makeExpression(NAryExpr fae, bool old) { if (fae.Fun is TypeCoercion) { return(makeExpression(fae.Args[0], old)); } var arguments = new ExpressionList((from Expr e in fae.Args select makeExpression(e, old)).ToArray()); Function function; if (fae.Fun is MapSelect) { var typeArguments = new IType[fae.TypeParameters.FormalTypeParams.Count]; for (int i = 0; i < fae.TypeParameters.FormalTypeParams.Count; i++) { typeArguments[i] = makeType(fae.TypeParameters[fae.TypeParameters.FormalTypeParams[i]]); } var argumentTypes = TypeTuple.make(from a in arguments select a.type); function = BasicMapRead.mapRead( typeArguments, argumentTypes, makeType(fae.Type) ); } else if (fae.Fun is MapStore) { var typeArguments = new IType[fae.TypeParameters.FormalTypeParams.Count]; for (int i = 0; i < fae.TypeParameters.FormalTypeParams.Count; i++) { typeArguments[i] = makeType(fae.TypeParameters[fae.TypeParameters.FormalTypeParams[i]]); } function = BasicMapWrite.makeMapWrite(typeArguments, (from a in arguments select a.type).ToArray(), makeType(fae.ShallowType)); } else if (fae.Fun.FunctionName == "==" || fae.Fun.FunctionName == "!=") { if (arguments[0].type.isEquivalent(arguments[1].type)) { function = BFunction.eq(arguments[0].type); } else { Debug.Assert(!arguments[0].type.isGround || !arguments[1].type.isGround); function = BFunction.eq(arguments[0].type, arguments[1].type); } if (fae.Fun.FunctionName == "!=") { arguments = new ExpressionList( new BasicFAE( function, arguments ) ); function = scope.getFunction("!", TypeTuple.make()); } } else if (fae.Fun.FunctionName == "<:") { function = scope.getFunction(fae.Fun.FunctionName, TypeTuple.make(new[] { arguments[0].type })); } else if (fae.Fun.FunctionName == BFunctionTemplate.iteName) { function = scope.getFunction(fae.Fun.FunctionName, TypeTuple.make(new[] { arguments[1].type })); } else if (fae.Fun.FunctionName == @"-" && fae.Fun.ArgumentCount == 1) { arguments = new ExpressionList(new[] { new BasicLiteralExpression(IntegerValue.make(0)), arguments[0] }); function = scope.getFunction(@"-", TypeTuple.make()); } else { var typeArguments = TypeTuple.make((fae.TypeParameters == null) ? new IType[0] : (from ftp in fae.TypeParameters.FormalTypeParams select scope.typeFactory.makeTypeI(fae.TypeParameters[ftp], context))); function = scope.getFunction(fae.Fun.FunctionName, typeArguments); } var result = new BoogieFunctionApplicationExpression(fae, function, arguments); Debug.Assert(result.type.ToStringN() == makeType(fae.Type == null ? fae.ShallowType : fae.Type).ToStringN()); Debug.Assert(result != null); foreach (var fv in result.freeVariables) { Debug.Assert(context.lookupVariableByOwnName(fv.name) == fv); } foreach (var ftv in result.freeTypeVariables) { Debug.Assert(ReferenceEquals(context.lookupTypeVariable(ftv.name), ftv)); } return(result); }