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); } if (recvHandler.CanChangeState == true) { if (!method.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null)) { throw handler.ChangeStateInNonVoidFunction(context); } method.CanChangeState = true; } if (recvHandler.CanRaiseEvent == true) { if (!method.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null)) { throw handler.RaiseEventInNonVoidFunction(context); } method.CanRaiseEvent = true; } foreach (var callee in recvHandler.Callees) { method.AddCallee(callee); } cases.Add(pEvent, recvHandler); } } method.CanReceive = true; return(new ReceiveStmt(context, cases)); }
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")); }
private PLanguageType ResolveType(PParser.TypeContext typeContext) { return(TypeResolver.ResolveType(typeContext, CurrentScope, Handler)); }