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)); }
public override object VisitVarDecl(PParser.VarDeclContext context) { foreach (var varName in context.idenList()._names) { var variable = method.Scope.Put(varName.GetText(), varName, VariableRole.Local); variable.Type = TypeResolver.ResolveType(context.type(), method.Scope, handler); method.AddLocalVariable(variable); } return(null); }
public override IPExpr VisitKeywordExpr(PParser.KeywordExprContext context) { switch (context.fun.Text) { case "keys": { IPExpr expr = Visit(context.expr()); if (!(expr.Type.Canonicalize() is MapType mapType)) { throw handler.TypeMismatch(expr, TypeKind.Map); } return(new KeysExpr(context, expr, new SequenceType(mapType.KeyType))); } case "values": { IPExpr expr = Visit(context.expr()); if (!(expr.Type.Canonicalize() is MapType mapType)) { throw handler.TypeMismatch(expr, TypeKind.Map); } return(new ValuesExpr(context, expr, new SequenceType(mapType.ValueType))); } case "sizeof": { var expr = Visit(context.expr()); if (!(expr.Type.Canonicalize() is SequenceType) && !(expr.Type.Canonicalize() is MapType) && !(expr.Type.Canonicalize() is SetType)) { throw handler.TypeMismatch(expr, TypeKind.Map, TypeKind.Sequence, TypeKind.Set); } return(new SizeofExpr(context, expr)); } case "default": { PLanguageType type = TypeResolver.ResolveType(context.type(), table, handler); return(new DefaultExpr(context, type.Canonicalize())); } default: { throw handler.InternalError(context, new ArgumentException($"Unknown keyword expression {context.fun.Text}", nameof(context))); } } }
public override IPExpr VisitCastExpr(PParser.CastExprContext context) { var subExpr = Visit(context.expr()); var oldType = subExpr.Type; var 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)); }