Пример #1
0
        public override IPStmt VisitGotoStmt(PParser.GotoStmtContext context)
        {
            PParser.StateNameContext stateNameContext = context.stateName();
            string          stateName = stateNameContext.state.GetText();
            IStateContainer current   = machine;

            foreach (PParser.IdenContext token in stateNameContext._groups)
            {
                current = current?.GetGroup(token.GetText());
                if (current == null)
                {
                    throw handler.MissingDeclaration(token, "group", token.GetText());
                }
            }

            AST.States.State state = current?.GetState(stateName);
            if (state == null)
            {
                throw handler.MissingDeclaration(stateNameContext.state, "state", stateName);
            }

            PLanguageType expectedType =
                state.Entry?.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null;

            IPExpr[] rvaluesList = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), exprVisitor).ToArray();
            foreach (IPExpr arg in rvaluesList)
            {
                if (arg is LinearAccessRefExpr linearArg && linearArg.LinearType == LinearType.Swap)
                {
                    throw handler.InvalidSwap(linearArg, "swap not allowed on goto");
                }
            }

            IPExpr payload;

            if (rvaluesList.Length == 0)
            {
                payload = null;
            }
            else if (rvaluesList.Length == 1)
            {
                payload = rvaluesList[0];
            }
            else
            {
                payload = new UnnamedTupleExpr(context, rvaluesList);
            }

            PLanguageType payloadType = payload?.Type ?? PrimitiveType.Null;

            if (!expectedType.IsAssignableFrom(payloadType))
            {
                throw handler.TypeMismatch(context, payloadType, expectedType);
            }

            method.CanChangeState = true;
            return(new GotoStmt(context, state, payload));
        }
Пример #2
0
        public override IPStmt VisitReceiveStmt(PParser.ReceiveStmtContext context)
        {
            if (machine?.IsSpec == true)
            {
                throw handler.IllegalMonitorOperation(context, context.RECEIVE().Symbol, machine);
            }

            Dictionary <PEvent, Function> cases = new Dictionary <PEvent, Function>();

            foreach (PParser.RecvCaseContext caseContext in context.recvCase())
            {
                Function recvHandler =
                    new Function(caseContext.anonEventHandler())
                {
                    Scope          = table.MakeChildScope(),
                    Owner          = method.Owner,
                    ParentFunction = method,
                    Role           = FunctionRole.ReceiveHandler
                };

                if (caseContext.anonEventHandler().funParam() is PParser.FunParamContext param)
                {
                    Variable paramVar = recvHandler.Scope.Put(param.name.GetText(), param, VariableRole.Param);
                    paramVar.Type = TypeResolver.ResolveType(param.type(), recvHandler.Scope, handler);
                    recvHandler.Signature.Parameters.Add(paramVar);
                }

                FunctionBodyVisitor.PopulateMethod(handler, recvHandler);

                foreach (PParser.EventIdContext eventIdContext in caseContext.eventList().eventId())
                {
                    if (!table.Lookup(eventIdContext.GetText(), out PEvent pEvent))
                    {
                        throw handler.MissingDeclaration(eventIdContext, "event", eventIdContext.GetText());
                    }

                    if (cases.ContainsKey(pEvent))
                    {
                        throw handler.DuplicateReceiveCase(eventIdContext, pEvent);
                    }

                    PLanguageType expectedType =
                        recvHandler.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null;
                    if (!expectedType.IsAssignableFrom(pEvent.PayloadType))
                    {
                        throw handler.TypeMismatch(caseContext.anonEventHandler(), expectedType,
                                                   pEvent.PayloadType);
                    }

                    cases.Add(pEvent, recvHandler);
                }
            }

            method.CanReceive = true;
            return(new ReceiveStmt(context, cases));
        }
Пример #3
0
        public override IPExpr VisitCastExpr(PParser.CastExprContext context)
        {
            IPExpr        subExpr = Visit(context.expr());
            PLanguageType oldType = subExpr.Type;
            PLanguageType newType = TypeResolver.ResolveType(context.type(), table, handler);

            if (context.cast.Text.Equals("as"))
            {
                if (!newType.IsAssignableFrom(oldType) && !oldType.IsAssignableFrom(newType))
                {
                    throw handler.IncomparableTypes(context, oldType, newType);
                }
                return(new CastExpr(context, subExpr, newType));
            }
            if (context.cast.Text.Equals("to"))
            {
                if (oldType.IsSameTypeAs(PrimitiveType.Int))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(subExpr);
                    }
                    if (newType.IsSameTypeAs(PrimitiveType.Float) || PLanguageType.TypeIsOfKind(newType, TypeKind.Enum))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (oldType.IsSameTypeAs(PrimitiveType.Float))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Float))
                    {
                        return(subExpr);
                    }
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (PLanguageType.TypeIsOfKind(oldType, TypeKind.Enum))
                {
                    // TODO: are enum-to-enum coersions allowed?
                    if (newType.IsSameTypeAs(oldType))
                    {
                        return(subExpr);
                    }
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                throw handler.IncomparableTypes(context, oldType, newType);
            }
            throw new ArgumentException(nameof(context));
        }
Пример #4
0
        private (VariableAccessExpr, IPStmt) SaveInTemporary(IPExpr expr, PLanguageType tempType)
        {
            Antlr4.Runtime.ParserRuleContext location = expr.SourceLocation;
            Variable temp = function.Scope.Put($"$tmp{numTemp++}", location, VariableRole.Local | VariableRole.Temp);

            Debug.Assert(tempType.IsAssignableFrom(expr.Type));
            temp.Type = tempType;
            function.AddLocalVariable(temp);
            AssignStmt stmt = new AssignStmt(location, new VariableAccessExpr(location, temp), expr);

            return(new VariableAccessExpr(location, temp), stmt);
        }
Пример #5
0
 public static void CheckArgument(ITranslationErrorHandler handler, ParserRuleContext context,
                                  PLanguageType argumentType, IPExpr arg)
 {
     if (arg is ILinearRef linearRef)
     {
         if (linearRef.LinearType.Equals(LinearType.Swap) && !arg.Type.IsSameTypeAs(argumentType))
         {
             throw handler.TypeMismatch(context, arg.Type, argumentType);
         }
     }
     if (!argumentType.IsAssignableFrom(arg.Type))
     {
         throw handler.TypeMismatch(context, arg.Type, argumentType);
     }
 }
Пример #6
0
        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));
        }
Пример #7
0
        public override IPStmt VisitReceiveStmt(PParser.ReceiveStmtContext context)
        {
            // TODO: can receive statements have event variables as their cases?
            var cases = new Dictionary <PEvent, Function>();

            foreach (PParser.RecvCaseContext caseContext in context.recvCase())
            {
                var recvHandler =
                    new Function(caseContext.anonEventHandler())
                {
                    Scope = table.MakeChildScope(),
                    Owner = method.Owner,
                    Role  = FunctionRole.ReceiveHandler
                };

                if (caseContext.anonEventHandler().funParam() is PParser.FunParamContext param)
                {
                    Variable paramVar = recvHandler.Scope.Put(param.name.GetText(), param, VariableRole.Param);
                    paramVar.Type = TypeResolver.ResolveType(param.type(), recvHandler.Scope, handler);
                    recvHandler.Signature.Parameters.Add(paramVar);
                }

                FunctionBodyVisitor.PopulateMethod(handler, recvHandler);

                foreach (PParser.EventIdContext eventIdContext in caseContext.eventList().eventId())
                {
                    if (!table.Lookup(eventIdContext.GetText(), out PEvent pEvent))
                    {
                        throw handler.MissingDeclaration(eventIdContext, "event", eventIdContext.GetText());
                    }
                    if (cases.ContainsKey(pEvent))
                    {
                        throw handler.IssueError(eventIdContext, $"duplicate case for event {pEvent.Name} in receive");
                    }
                    PLanguageType expectedType =
                        recvHandler.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null;
                    if (!expectedType.IsAssignableFrom(pEvent.PayloadType))
                    {
                        throw handler.TypeMismatch(caseContext.anonEventHandler().funParam(), expectedType,
                                                   pEvent.PayloadType);
                    }
                    cases.Add(pEvent, recvHandler);
                }
            }
            return(new ReceiveStmt(context, cases));
        }
Пример #8
0
        public override IPStmt VisitGotoStmt(PParser.GotoStmtContext context)
        {
            PParser.StateNameContext stateNameContext = context.stateName();
            string          stateName = stateNameContext.state.GetText();
            IStateContainer current   = machine;

            foreach (PParser.IdenContext token in stateNameContext._groups)
            {
                current = current?.GetGroup(token.GetText());
                if (current == null)
                {
                    throw handler.MissingDeclaration(token, "group", token.GetText());
                }
            }
            State state = current?.GetState(stateName);

            if (state == null)
            {
                throw handler.MissingDeclaration(stateNameContext.state, "state", stateName);
            }
            IPExpr        payload      = null;
            PLanguageType expectedType =
                state.Entry.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null;

            if (context.rvalueList()?.rvalue() is PParser.RvalueContext[] rvalues)
            {
                if (rvalues.Length == 1)
                {
                    payload = exprVisitor.Visit(rvalues[0]);
                }
                else
                {
                    IPExpr[] tupleFields = rvalues.Select(exprVisitor.Visit).ToArray();
                    payload = new UnnamedTupleExpr(context, tupleFields,
                                                   new TupleType(tupleFields.Select(f => f.Type).ToList()));
                }
            }
            PLanguageType payloadType = payload?.Type ?? PrimitiveType.Null;

            if (!expectedType.IsAssignableFrom(payloadType))
            {
                throw handler.TypeMismatch(context, payloadType, expectedType);
            }
            return(new GotoStmt(context, state, payload));
        }
Пример #9
0
        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));
        }
Пример #10
0
 public bool IsSameTypeAs(PLanguageType otherType)
 {
     return(IsAssignableFrom(otherType) && otherType.IsAssignableFrom(this));
 }
Пример #11
0
        public override IPExpr VisitCastExpr(PParser.CastExprContext context)
        {
            IPExpr        subExpr = Visit(context.expr());
            PLanguageType oldType = subExpr.Type;
            PLanguageType newType = TypeResolver.ResolveType(context.type(), table, handler);

            if (context.cast.Text.Equals("as"))
            {
                if (!newType.IsAssignableFrom(oldType) && !oldType.IsAssignableFrom(newType))
                {
                    throw handler.IncomparableTypes(context, oldType, newType);
                }

                return(new CastExpr(context, subExpr, newType));
            }

            if (context.cast.Text.Equals("to"))
            {
                if (!(newType is PermissionType || newType.IsSameTypeAs(PrimitiveType.Int) ||
                      newType.IsSameTypeAs(PrimitiveType.Float)))
                {
                    throw handler.IllegalTypeInCoerceExpr(context);
                }

                if (oldType.IsSameTypeAs(PrimitiveType.Int))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(subExpr);
                    }

                    if (newType.IsSameTypeAs(PrimitiveType.Float) || PLanguageType.TypeIsOfKind(newType, TypeKind.Enum))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (oldType.IsSameTypeAs(PrimitiveType.Float))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Float))
                    {
                        return(subExpr);
                    }

                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (PLanguageType.TypeIsOfKind(oldType, TypeKind.Enum))
                {
                    // TODO: are enum-to-enum coersions allowed?
                    if (newType.IsSameTypeAs(oldType))
                    {
                        return(subExpr);
                    }

                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (oldType.IsSameTypeAs(PrimitiveType.Machine) || oldType is PermissionType)
                {
                    if (newType.IsSameTypeAs(oldType))
                    {
                        return(subExpr);
                    }

                    if (newType is PermissionType)
                    {
                        if (oldType.IsSameTypeAs(PrimitiveType.Machine))
                        {
                            return(new CoerceExpr(context, subExpr, newType));
                        }

                        if (oldType is PermissionType)
                        {
                            if (newType.AllowedPermissions.Value.Any(x => !oldType.AllowedPermissions.Value.Contains(x))
                                )
                            {
                                throw handler.IllegalInterfaceCoerce(context, oldType, newType);
                            }

                            return(new CoerceExpr(context, subExpr, newType));
                        }
                    }
                }

                throw handler.IncomparableTypes(context, oldType, newType);
            }

            throw handler.InternalError(context, new ArgumentOutOfRangeException(nameof(context), "invalid cast"));
        }