public override IPExpr VisitFunCallExpr(PParser.FunCallExprContext context) { string funName = context.fun.GetText(); if (!table.Lookup(funName, out Function function)) { throw handler.MissingDeclaration(context.fun, "function", funName); } // Check the arguments IPExpr[] arguments = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), this).ToArray(); ISet <Variable> linearVariables = new HashSet <Variable>(); if (function.Signature.Parameters.Count != arguments.Length) { throw handler.IncorrectArgumentCount(context, arguments.Length, function.Signature.Parameters.Count); } for (int i = 0; i < arguments.Length; i++) { IPExpr argument = arguments[i]; PLanguageType paramType = function.Signature.Parameters[i].Type; if (!paramType.IsAssignableFrom(argument.Type)) { throw handler.TypeMismatch(context.rvalueList().rvalue(i), argument.Type, paramType); } if (argument is ILinearRef linearRef) { if (linearRef.LinearType == LinearType.Swap && !linearRef.Type.IsSameTypeAs(paramType)) { throw handler.TypeMismatch(context, linearRef.Type, paramType); } if (linearVariables.Contains(linearRef.Variable)) { throw handler.RelinquishedWithoutOwnership(linearRef); } linearVariables.Add(linearRef.Variable); } } method.AddCallee(function); return(new FunCallExpr(context, function, arguments)); }
public override IPExpr VisitFunCallExpr(PParser.FunCallExprContext context) { string funName = context.fun.GetText(); if (!table.Lookup(funName, out Function function)) { throw handler.MissingDeclaration(context.fun, "function", funName); } // Check the arguments // TODO: linearly typed arguments var arguments = (context.rvalueList()?.rvalue().Select(Visit) ?? Enumerable.Empty <IPExpr>()).ToArray(); ISet <Variable> linearVariables = new HashSet <Variable>(); for (var i = 0; i < arguments.Length; i++) { IPExpr argument = arguments[i]; PLanguageType paramType = function.Signature.Parameters[i].Type; if (!paramType.IsAssignableFrom(argument.Type)) { throw handler.TypeMismatch(context.rvalueList().rvalue(i), argument.Type, paramType); } if (argument is ILinearRef linearRef) { if (linearRef.LinearType == LinearType.Swap && !linearRef.Type.IsSameTypeAs(paramType)) { throw handler.TypeMismatch(context, linearRef.Type, paramType); } if (linearVariables.Contains(linearRef.Variable)) { throw handler.RelinquishedWithoutOwnership(linearRef); } linearVariables.Add(linearRef.Variable); } } return(new FunCallExpr(context, function, arguments)); }
private ISet <Variable> ProcessExpr(ISet <Variable> unavailable, IPExpr expression) { Contract.Requires(expression != null); switch (expression) { case CloneExpr cloneExpr: unavailable = ProcessExpr(unavailable, cloneExpr.Term); break; case CastExpr castExpr: unavailable = ProcessExpr(unavailable, castExpr.SubExpr); break; case CoerceExpr coerceExpr: unavailable = ProcessExpr(unavailable, coerceExpr.SubExpr); break; case ContainsKeyExpr containsKeyExpr: unavailable = ProcessExpr(unavailable, containsKeyExpr.Map); unavailable = ProcessExpr(unavailable, containsKeyExpr.Key); break; case CtorExpr ctorExpr: unavailable = ProcessArgList(ctorExpr.Arguments, unavailable, ArgOptions.SwapNotAllowed); break; case FunCallExpr funCallExpr: unavailable = ProcessArgList(funCallExpr.Arguments, unavailable); funCallExprs.Add(funCallExpr); break; case KeysExpr keysExpr: unavailable = ProcessExpr(unavailable, keysExpr.Expr); break; case LinearAccessRefExpr linearAccessRefExpr: if (unavailable.Contains(linearAccessRefExpr.Variable) || linearAccessRefExpr.Variable.Role.Equals(VariableRole.Field)) { throw handler.RelinquishedWithoutOwnership(linearAccessRefExpr); } if (linearAccessRefExpr.LinearType.Equals(LinearType.Move)) { unavailable.Add(linearAccessRefExpr.Variable); } break; case UnaryOpExpr unaryOp: unavailable = ProcessExpr(unavailable, unaryOp.SubExpr); break; case MapAccessExpr mapAccessExpr: unavailable = ProcessExpr(unavailable, mapAccessExpr.MapExpr); unavailable = ProcessExpr(unavailable, mapAccessExpr.IndexExpr); break; case BinOpExpr binOp: unavailable = ProcessExpr(unavailable, binOp.Lhs); unavailable = ProcessExpr(unavailable, binOp.Rhs); break; case NamedTupleAccessExpr namedTupleAccessExpr: unavailable = ProcessExpr(unavailable, namedTupleAccessExpr.SubExpr); break; case NamedTupleExpr namedTupleExpr: unavailable = ProcessArgList(namedTupleExpr.TupleFields, unavailable, ArgOptions.SwapNotAllowed); break; case SeqAccessExpr seqAccessExpr: unavailable = ProcessExpr(unavailable, seqAccessExpr.SeqExpr); unavailable = ProcessExpr(unavailable, seqAccessExpr.IndexExpr); break; case SizeofExpr sizeofExpr: unavailable = ProcessExpr(unavailable, sizeofExpr.Expr); break; case TupleAccessExpr tupleAccessExpr: unavailable = ProcessExpr(unavailable, tupleAccessExpr.SubExpr); break; case UnnamedTupleExpr unnamedTupleExpr: unavailable = ProcessArgList(unnamedTupleExpr.TupleFields, unavailable, ArgOptions.SwapNotAllowed); break; case ValuesExpr valuesExpr: unavailable = ProcessExpr(unavailable, valuesExpr.Expr); break; case VariableAccessExpr variableAccessExpr: if (unavailable.Contains(variableAccessExpr.Variable)) { throw handler.UseWithoutOwnership(variableAccessExpr); } break; case BoolLiteralExpr _: case DefaultExpr _: case EnumElemRefExpr _: case EventRefExpr _: case FairNondetExpr _: case FloatLiteralExpr _: case IntLiteralExpr _: case NondetExpr _: case NullLiteralExpr _: case ThisRefExpr _: // nothing to do break; default: throw handler.InternalError(expression.SourceLocation, new ArgumentOutOfRangeException(nameof(expression))); } return(unavailable); }