public override IPStmt VisitRemoveStmt(PParser.RemoveStmtContext context) { IPExpr variable = exprVisitor.Visit(context.lvalue()); IPExpr value = exprVisitor.Visit(context.expr()); if (PLanguageType.TypeIsOfKind(variable.Type, TypeKind.Sequence)) { if (!PrimitiveType.Int.IsAssignableFrom(value.Type)) { throw handler.TypeMismatch(context.expr(), value.Type, PrimitiveType.Int); } } else if (PLanguageType.TypeIsOfKind(variable.Type, TypeKind.Map)) { var map = (MapType)variable.Type.Canonicalize(); if (!map.KeyType.IsAssignableFrom(value.Type)) { throw handler.TypeMismatch(context.expr(), value.Type, map.KeyType); } } else { throw handler.TypeMismatch(variable, TypeKind.Sequence, TypeKind.Map); } return(new RemoveStmt(context, variable, value)); }
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)); }
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")); }